aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp5
-rw-r--r--llvm/tools/llvm-gsymutil/Opts.td5
-rw-r--r--llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp47
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp2
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp2
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp2
-rw-r--r--llvm/tools/llvm-jitlink/llvm-jitlink.cpp77
-rw-r--r--llvm/tools/llvm-link/llvm-link.cpp5
-rw-r--r--llvm/tools/llvm-profgen/PerfReader.cpp19
9 files changed, 132 insertions, 32 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 41d3615..5636782 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -24,6 +24,8 @@
namespace llvm {
namespace exegesis {
+#include "RISCVGenExegesis.inc"
+
namespace {
// Stores constant value to a general-purpose (integer) register.
@@ -132,8 +134,7 @@ public:
};
ExegesisRISCVTarget::ExegesisRISCVTarget()
- : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
- RISCV_MC::isOpcodeAvailable) {}
+ : ExegesisTarget(RISCVCpuPfmCounters, RISCV_MC::isOpcodeAvailable) {}
bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const {
return Arch == Triple::riscv32 || Arch == Triple::riscv64;
diff --git a/llvm/tools/llvm-gsymutil/Opts.td b/llvm/tools/llvm-gsymutil/Opts.td
index d61b418..89cd3ce 100644
--- a/llvm/tools/llvm-gsymutil/Opts.td
+++ b/llvm/tools/llvm-gsymutil/Opts.td
@@ -17,7 +17,10 @@ defm convert :
Eq<"convert",
"Convert the specified file to the GSYM format.\nSupported files include ELF and mach-o files that will have their debug info (DWARF) and symbol table converted">;
def merged_functions :
- FF<"merged-functions", "Encode merged function information for functions in debug info that have matching address ranges.\nWithout this option one function per unique address range will be emitted.">;
+ FF<"merged-functions", "When used with --convert, encodes merged function information for functions in debug info that have matching address ranges.\n"
+ "Without this option one function per unique address range will be emitted.\n"
+ "When used with --address/--addresses-from-stdin, all merged functions for a particular address will be displayed.\n"
+ "Without this option only one function will be displayed.">;
def dwarf_callsites : FF<"dwarf-callsites", "Load call site info from DWARF, if available">;
defm callsites_yaml_file :
Eq<"callsites-yaml-file", "Load call site info from YAML file. Useful for testing.">, Flags<[HelpHidden]>;
diff --git a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
index aed4ae7..654da68 100644
--- a/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
+++ b/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
@@ -98,7 +98,7 @@ static uint64_t SegmentSize;
static bool Quiet;
static std::vector<uint64_t> LookupAddresses;
static bool LookupAddressesFromStdin;
-static bool StoreMergedFunctionInfo = false;
+static bool UseMergedFunctions = false;
static bool LoadDwarfCallSites = false;
static std::string CallSiteYamlPath;
@@ -181,7 +181,7 @@ static void parseArgs(int argc, char **argv) {
}
LookupAddressesFromStdin = Args.hasArg(OPT_addresses_from_stdin);
- StoreMergedFunctionInfo = Args.hasArg(OPT_merged_functions);
+ UseMergedFunctions = Args.hasArg(OPT_merged_functions);
if (Args.hasArg(OPT_callsites_yaml_file_EQ)) {
CallSiteYamlPath = Args.getLastArgValue(OPT_callsites_yaml_file_EQ);
@@ -380,7 +380,7 @@ static llvm::Error handleObjectFile(ObjectFile &Obj, const std::string &OutFile,
// functions in the first FunctionInfo with that address range. Do this right
// after loading the DWARF data so we don't have to deal with functions from
// the symbol table.
- if (StoreMergedFunctionInfo)
+ if (UseMergedFunctions)
Gsym.prepareMergedFunctions(Out);
// Get the UUID and convert symbol table to GSYM.
@@ -508,24 +508,37 @@ static llvm::Error convertFileToGSYM(OutputAggregator &Out) {
}
static void doLookup(GsymReader &Gsym, uint64_t Addr, raw_ostream &OS) {
- if (auto Result = Gsym.lookup(Addr)) {
- // If verbose is enabled dump the full function info for the address.
- if (Verbose) {
- if (auto FI = Gsym.getFunctionInfo(Addr)) {
- OS << "FunctionInfo for " << HEX64(Addr) << ":\n";
- Gsym.dump(OS, *FI);
- OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+ if (UseMergedFunctions) {
+ if (auto Results = Gsym.lookupAll(Addr)) {
+ OS << "Found " << Results->size() << " functions at address "
+ << HEX64(Addr) << ":\n";
+ for (size_t i = 0; i < Results->size(); ++i) {
+ OS << " " << Results->at(i);
+
+ if (i != Results->size() - 1)
+ OS << "\n";
}
}
- OS << Result.get();
- } else {
+ } else { /* UseMergedFunctions == false */
+ if (auto Result = Gsym.lookup(Addr)) {
+ // If verbose is enabled dump the full function info for the address.
+ if (Verbose) {
+ if (auto FI = Gsym.getFunctionInfo(Addr)) {
+ OS << "FunctionInfo for " << HEX64(Addr) << ":\n";
+ Gsym.dump(OS, *FI);
+ OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+ }
+ }
+ OS << Result.get();
+ } else {
+ if (Verbose)
+ OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
+ OS << HEX64(Addr) << ": ";
+ logAllUnhandledErrors(Result.takeError(), OS, "error: ");
+ }
if (Verbose)
- OS << "\nLookupResult for " << HEX64(Addr) << ":\n";
- OS << HEX64(Addr) << ": ";
- logAllUnhandledErrors(Result.takeError(), OS, "error: ");
+ OS << "\n";
}
- if (Verbose)
- OS << "\n";
}
int llvm_gsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
index 5271fdb..6db78926 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
@@ -66,6 +66,8 @@ static Expected<Symbol &> getCOFFStubTarget(LinkGraph &G, Block &B) {
namespace llvm {
Error registerCOFFGraphInfo(Session &S, LinkGraph &G) {
+ std::lock_guard<std::mutex> Lock(S.M);
+
auto FileName = sys::path::filename(G.getName());
if (S.FileInfos.count(FileName)) {
return make_error<StringError>("When -check is passed, file names must be "
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index a8c804a..6aa8941 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -101,6 +101,8 @@ static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI,
namespace llvm {
Error registerELFGraphInfo(Session &S, LinkGraph &G) {
+ std::lock_guard<std::mutex> Lock(S.M);
+
auto FileName = sys::path::filename(G.getName());
if (S.FileInfos.count(FileName)) {
return make_error<StringError>("When -check is passed, file names must be "
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
index 2c60c80..2fc56c9 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
@@ -69,6 +69,8 @@ static Expected<Symbol &> getMachOStubTarget(LinkGraph &G, Block &B) {
namespace llvm {
Error registerMachOGraphInfo(Session &S, LinkGraph &G) {
+ std::lock_guard<std::mutex> Lock(S.M);
+
auto FileName = sys::path::filename(G.getName());
if (S.FileInfos.count(FileName)) {
return make_error<StringError>("When -check is passed, file names must be "
diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 96a3e5b..963c363 100644
--- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -91,6 +91,10 @@ static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
cl::desc("input files"),
cl::cat(JITLinkCategory));
+static cl::opt<size_t> MaterializationThreads(
+ "num-threads", cl::desc("Number of materialization threads to use"),
+ cl::init(std::numeric_limits<size_t>::max()), cl::cat(JITLinkCategory));
+
static cl::list<std::string>
LibrarySearchPaths("L",
cl::desc("Add dir to the list of library search paths"),
@@ -400,6 +404,7 @@ bool lazyLinkingRequested() {
}
static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
+ std::lock_guard<std::mutex> Lock(S.M);
// If this graph is part of the test harness there's nothing to do.
if (S.HarnessFiles.empty() || S.HarnessFiles.count(G.getName()))
@@ -450,7 +455,11 @@ static Error applyHarnessPromotions(Session &S, LinkGraph &G) {
return Error::success();
}
-static void dumpSectionContents(raw_ostream &OS, LinkGraph &G) {
+static void dumpSectionContents(raw_ostream &OS, Session &S, LinkGraph &G) {
+ std::lock_guard<std::mutex> Lock(S.M);
+
+ outs() << "Relocated section contents for " << G.getName() << ":\n";
+
constexpr orc::ExecutorAddrDiff DumpWidth = 16;
static_assert(isPowerOf2_64(DumpWidth), "DumpWidth must be a power of two");
@@ -842,7 +851,7 @@ static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {
S.CreateMemoryManager = createSharedMemoryManager;
return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
- std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),
+ std::make_unique<DynamicThreadPoolTaskDispatcher>(MaterializationThreads),
std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
#endif
}
@@ -984,10 +993,21 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
auto PageSize = sys::Process::getPageSize();
if (!PageSize)
return PageSize.takeError();
+ std::unique_ptr<TaskDispatcher> Dispatcher;
+ if (MaterializationThreads == 0)
+ Dispatcher = std::make_unique<InPlaceTaskDispatcher>();
+ else {
+#if LLVM_ENABLE_THREADS
+ Dispatcher = std::make_unique<DynamicThreadPoolTaskDispatcher>(
+ MaterializationThreads);
+#else
+ llvm_unreachable("MaterializationThreads should be 0");
+#endif
+ }
+
EPC = std::make_unique<SelfExecutorProcessControl>(
- std::make_shared<SymbolStringPool>(),
- std::make_unique<InPlaceTaskDispatcher>(), std::move(TT), *PageSize,
- createInProcessMemoryManager());
+ std::make_shared<SymbolStringPool>(), std::move(Dispatcher),
+ std::move(TT), *PageSize, createInProcessMemoryManager());
}
Error Err = Error::success();
@@ -1221,6 +1241,7 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) {
if (ShowGraphsRegex)
PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {
+ std::lock_guard<std::mutex> Lock(M);
// Print graph if ShowLinkGraphs is specified-but-empty, or if
// it contains the given graph.
if (ShowGraphsRegex->match(G.getName())) {
@@ -1239,9 +1260,8 @@ void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) {
[this](LinkGraph &G) { return applyHarnessPromotions(*this, G); });
if (ShowRelocatedSectionContents)
- PassConfig.PostFixupPasses.push_back([](LinkGraph &G) -> Error {
- outs() << "Relocated section contents for " << G.getName() << ":\n";
- dumpSectionContents(outs(), G);
+ PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {
+ dumpSectionContents(outs(), *this, G);
return Error::success();
});
@@ -1613,6 +1633,46 @@ static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
}
}
+#if LLVM_ENABLE_THREADS
+ if (MaterializationThreads == std::numeric_limits<size_t>::max()) {
+ if (auto HC = std::thread::hardware_concurrency())
+ MaterializationThreads = HC;
+ else {
+ errs() << "Warning: std::thread::hardware_concurrency() returned 0, "
+ "defaulting to -num-threads=1.\n";
+ MaterializationThreads = 1;
+ }
+ }
+#else
+ if (MaterializationThreads.getNumOccurrences() &&
+ MaterializationThreads != 0) {
+ errs() << "Warning: -num-threads was set, but LLVM was built with threads "
+ "disabled. Resetting to -num-threads=0\n";
+ }
+ MaterializationThreads = 0;
+#endif
+
+ if (!!OutOfProcessExecutor.getNumOccurrences() ||
+ !!OutOfProcessExecutorConnect.getNumOccurrences()) {
+ if (NoExec)
+ return make_error<StringError>("-noexec cannot be used with " +
+ OutOfProcessExecutor.ArgStr + " or " +
+ OutOfProcessExecutorConnect.ArgStr,
+ inconvertibleErrorCode());
+
+ if (MaterializationThreads == 0)
+ return make_error<StringError>("-threads=0 cannot be used with " +
+ OutOfProcessExecutor.ArgStr + " or " +
+ OutOfProcessExecutorConnect.ArgStr,
+ inconvertibleErrorCode());
+ }
+
+#ifndef NDEBUG
+ if (DebugFlag && MaterializationThreads != 0)
+ errs() << "Warning: debugging output is not thread safe. "
+ "Use -num-threads=0 to stabilize output.\n";
+#endif // NDEBUG
+
// Only one of -oop-executor and -oop-executor-connect can be used.
if (!!OutOfProcessExecutor.getNumOccurrences() &&
!!OutOfProcessExecutorConnect.getNumOccurrences())
@@ -2502,6 +2562,7 @@ int main(int argc, char *argv[]) {
if (Timers)
Timers->JITLinkTG.printAll(errs());
reportLLVMJITLinkError(EntryPoint.takeError());
+ ExitOnErr(S->ES.endSession());
exit(1);
}
diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp
index 34bb6ce..0f4a4d5 100644
--- a/llvm/tools/llvm-link/llvm-link.cpp
+++ b/llvm/tools/llvm-link/llvm-link.cpp
@@ -449,9 +449,8 @@ static bool linkFiles(const char *argv0, LLVMContext &Context, Linker &L,
}
// Promotion
- if (renameModuleForThinLTO(*M, *Index,
- /*ClearDSOLocalOnDeclarations=*/false))
- return true;
+ renameModuleForThinLTO(*M, *Index,
+ /*ClearDSOLocalOnDeclarations=*/false);
}
if (Verbose)
diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp
index 111c546..ad113ed 100644
--- a/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -42,6 +42,11 @@ static cl::opt<bool>
cl::opt<bool> ShowDetailedWarning("show-detailed-warning",
cl::desc("Show detailed warning message."));
+static cl::opt<int> CSProfMaxUnsymbolizedCtxDepth(
+ "csprof-max-unsymbolized-context-depth", cl::init(-1),
+ cl::desc("Keep the last K contexts while merging unsymbolized profile. -1 "
+ "means no depth limit."));
+
extern cl::opt<std::string> PerfTraceFilename;
extern cl::opt<bool> ShowDisassemblyOnly;
extern cl::opt<bool> ShowSourceLocations;
@@ -172,7 +177,19 @@ std::shared_ptr<AddrBasedCtxKey> AddressStack::getContextKey() {
std::shared_ptr<AddrBasedCtxKey> KeyStr = std::make_shared<AddrBasedCtxKey>();
KeyStr->Context = Stack;
CSProfileGenerator::compressRecursionContext<uint64_t>(KeyStr->Context);
- CSProfileGenerator::trimContext<uint64_t>(KeyStr->Context);
+ // MaxContextDepth(--csprof-max-context-depth) is used to trim both symbolized
+ // and unsymbolized profile context. Sometimes we want to at least preserve
+ // the inlinings for the leaf frame(the profiled binary inlining),
+ // --csprof-max-context-depth may not be flexible enough, in this case,
+ // --csprof-max-unsymbolized-context-depth is used to limit the context for
+ // unsymbolized profile. If both are set, use the minimum of them.
+ int Depth = CSProfileGenerator::MaxContextDepth != -1
+ ? CSProfileGenerator::MaxContextDepth
+ : KeyStr->Context.size();
+ Depth = CSProfMaxUnsymbolizedCtxDepth != -1
+ ? std::min(static_cast<int>(CSProfMaxUnsymbolizedCtxDepth), Depth)
+ : Depth;
+ CSProfileGenerator::trimContext<uint64_t>(KeyStr->Context, Depth);
return KeyStr;
}