diff --git a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c @@ -0,0 +1,15 @@ +// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s +// RUN: llvm-profdata show --debug-info-correlation --all-functions %t | FileCheck %s + +// RUN: %clang_pgogen -o %t.no.dbg -mllvm --debug-info-correlate -mllvm --disable-vp=true %s +// RUN: not llvm-profdata show --debug-info-correlation %t.no.dbg 2>&1 | FileCheck %s --check-prefix NO-DBG +// NO-DBG: unable to correlate profile: could not find any profile metadata in debug info + +void a() {} +void b() {} +int main() { return 0; } + +// CHECK: a +// CHECK: b +// CHECK: main +// CHECK: Found profile metadata for 3 functions. diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -529,6 +529,11 @@ /// Return the name section data. inline StringRef getNameData() const { return Data; } + + void dumpNames(raw_ostream &OS) const { + for (StringRef S : NameTab.keys()) + OS << S << "\n"; + } }; Error InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) { diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h --- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h +++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h @@ -35,6 +35,15 @@ /// to their functions. virtual Error correlateProfileData() = 0; + /// Return the number of ProfileData elements. + llvm::Optional getDataSize() const; + + /// Return a pointer to the names string that this class constructs. + const char *getNamesPointer() const { return Names.c_str(); } + + /// Return the number of bytes in the names string. + size_t getNamesSize() const { return Names.size(); } + static const char *FunctionNameAttributeName; static const char *CFGHashAttributeName; static const char *NumCountersAttributeName; @@ -59,6 +68,9 @@ InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr Ctx) : Ctx(std::move(Ctx)), Kind(K) {} + std::string Names; + std::vector NamesVec; + private: static llvm::Expected> get(std::unique_ptr Buffer); @@ -83,19 +95,12 @@ /// Return the number of ProfileData elements. size_t getDataSize() const { return Data.size(); } - /// Return a pointer to the names string that this class constructs. - const char *getNamesPointer() const { return Names.c_str(); } - - /// Return the number of bytes in the names string. - size_t getNamesSize() const { return Names.size(); } - static llvm::Expected>> get(std::unique_ptr Ctx, const object::ObjectFile &Obj); protected: std::vector> Data; - std::string Names; Error correlateProfileData() override; virtual void correlateProfileDataImpl() = 0; @@ -107,7 +112,6 @@ InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind, std::unique_ptr Ctx) : InstrProfCorrelator(Kind, std::move(Ctx)){}; - std::vector NamesVec; llvm::DenseSet CounterOffsets; // Byte-swap the value if necessary. diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -88,6 +88,15 @@ instrprof_error::unable_to_correlate_profile, "not an object file"); } +Optional InstrProfCorrelator::getDataSize() const { + if (auto *C = dyn_cast>(this)) { + return C->getDataSize(); + } else if (auto *C = dyn_cast>(this)) { + return C->getDataSize(); + } + return {}; +} + namespace llvm { template <> diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -2486,6 +2486,27 @@ return 0; } +static int showDebugInfoCorrelation(const std::string &Filename, + bool ShowAllFunctions, raw_fd_ostream &OS) { + std::unique_ptr Correlator; + if (auto Err = InstrProfCorrelator::get(Filename).moveInto(Correlator)) + exitWithError(std::move(Err), Filename); + if (auto Err = Correlator->correlateProfileData()) + exitWithError(std::move(Err), Filename); + + InstrProfSymtab Symtab; + if (auto Err = Symtab.create( + StringRef(Correlator->getNamesPointer(), Correlator->getNamesSize()))) + exitWithError(std::move(Err), Filename); + + if (ShowAllFunctions) + Symtab.dumpNames(OS); + OS << "Found profile metadata for " << Correlator->getDataSize() + << " functions.\n"; + + return 0; +} + static int show_main(int argc, const char *argv[]) { cl::opt Filename(cl::Positional, cl::Required, cl::desc("")); @@ -2549,6 +2570,10 @@ "extbinary format")); cl::opt ShowBinaryIds("binary-ids", cl::init(false), cl::desc("Show binary ids in the profile. ")); + cl::opt DebugInfoCorrelation( + "debug-info-correlation", cl::init(false), + cl::desc("Read and exctract profile metadata from debug info and show " + "the functions it found.")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); @@ -2566,6 +2591,9 @@ if (ShowAllFunctions && !ShowFunction.empty()) WithColor::warning() << "-function argument ignored: showing all functions\n"; + if (DebugInfoCorrelation) + return showDebugInfoCorrelation(Filename, ShowAllFunctions, OS); + if (ProfileKind == instr) return showInstrProfile( Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,