diff options
Diffstat (limited to 'llvm/lib/ProfileData/InstrProfCorrelator.cpp')
| -rw-r--r-- | llvm/lib/ProfileData/InstrProfCorrelator.cpp | 165 |
1 files changed, 105 insertions, 60 deletions
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp index c822d81f8bef..24d828f69c71 100644 --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -16,21 +16,28 @@ #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/WithColor.h" #include <optional> #define DEBUG_TYPE "correlator" using namespace llvm; -/// Get the __llvm_prf_cnts section. -Expected<object::SectionRef> getCountersSection(const object::ObjectFile &Obj) { +/// Get profile section. +Expected<object::SectionRef> getInstrProfSection(const object::ObjectFile &Obj, + InstrProfSectKind IPSK) { + Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat(); + std::string ExpectedSectionName = + getInstrProfSectionName(IPSK, ObjFormat, + /*AddSegmentInfo=*/false); for (auto &Section : Obj.sections()) if (auto SectionName = Section.getName()) - if (SectionName.get() == INSTR_PROF_CNTS_SECT_NAME) + if (SectionName.get() == ExpectedSectionName) return Section; return make_error<InstrProfError>( instrprof_error::unable_to_correlate_profile, - "could not find counter section (" INSTR_PROF_CNTS_SECT_NAME ")"); + "could not find section (" + Twine(ExpectedSectionName) + ")"); } const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name"; @@ -40,7 +47,7 @@ const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters"; llvm::Expected<std::unique_ptr<InstrProfCorrelator::Context>> InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj) { - auto CountersSection = getCountersSection(Obj); + auto CountersSection = getInstrProfSection(Obj, IPSK_cnts); if (auto Err = CountersSection.takeError()) return std::move(Err); auto C = std::make_unique<Context>(); @@ -52,30 +59,35 @@ InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer, } llvm::Expected<std::unique_ptr<InstrProfCorrelator>> -InstrProfCorrelator::get(StringRef DebugInfoFilename) { - auto DsymObjectsOrErr = - object::MachOObjectFile::findDsymObjectMembers(DebugInfoFilename); - if (auto Err = DsymObjectsOrErr.takeError()) - return std::move(Err); - if (!DsymObjectsOrErr->empty()) { - // TODO: Enable profile correlation when there are multiple objects in a - // dSYM bundle. - if (DsymObjectsOrErr->size() > 1) - return make_error<InstrProfError>( - instrprof_error::unable_to_correlate_profile, - "using multiple objects is not yet supported"); - DebugInfoFilename = *DsymObjectsOrErr->begin(); - } - auto BufferOrErr = - errorOrToExpected(MemoryBuffer::getFile(DebugInfoFilename)); - if (auto Err = BufferOrErr.takeError()) - return std::move(Err); +InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) { + if (FileKind == DEBUG_INFO) { + auto DsymObjectsOrErr = + object::MachOObjectFile::findDsymObjectMembers(Filename); + if (auto Err = DsymObjectsOrErr.takeError()) + return std::move(Err); + if (!DsymObjectsOrErr->empty()) { + // TODO: Enable profile correlation when there are multiple objects in a + // dSYM bundle. + if (DsymObjectsOrErr->size() > 1) + return make_error<InstrProfError>( + instrprof_error::unable_to_correlate_profile, + "using multiple objects is not yet supported"); + Filename = *DsymObjectsOrErr->begin(); + } + auto BufferOrErr = errorOrToExpected(MemoryBuffer::getFile(Filename)); + if (auto Err = BufferOrErr.takeError()) + return std::move(Err); - return get(std::move(*BufferOrErr)); + return get(std::move(*BufferOrErr), FileKind); + } + return make_error<InstrProfError>( + instrprof_error::unable_to_correlate_profile, + "unsupported correlation kind (only DWARF debug info is supported)"); } llvm::Expected<std::unique_ptr<InstrProfCorrelator>> -InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer) { +InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer, + ProfCorrelatorKind FileKind) { auto BinOrErr = object::createBinary(*Buffer); if (auto Err = BinOrErr.takeError()) return std::move(Err); @@ -86,9 +98,11 @@ InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer) { return std::move(Err); auto T = Obj->makeTriple(); if (T.isArch64Bit()) - return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj); + return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj, + FileKind); if (T.isArch32Bit()) - return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj); + return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj, + FileKind); } return make_error<InstrProfError>( instrprof_error::unable_to_correlate_profile, "not an object file"); @@ -130,29 +144,33 @@ template <class IntPtrT> llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>> InstrProfCorrelatorImpl<IntPtrT>::get( std::unique_ptr<InstrProfCorrelator::Context> Ctx, - const object::ObjectFile &Obj) { - if (Obj.isELF() || Obj.isMachO()) { - auto DICtx = DWARFContext::create(Obj); - return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(std::move(DICtx), - std::move(Ctx)); + const object::ObjectFile &Obj, ProfCorrelatorKind FileKind) { + if (FileKind == DEBUG_INFO) { + if (Obj.isELF() || Obj.isMachO()) { + auto DICtx = DWARFContext::create(Obj); + return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>( + std::move(DICtx), std::move(Ctx)); + } + return make_error<InstrProfError>( + instrprof_error::unable_to_correlate_profile, + "unsupported debug info format (only DWARF is supported)"); } return make_error<InstrProfError>( instrprof_error::unable_to_correlate_profile, - "unsupported debug info format (only DWARF is supported)"); + "unsupported correlation file type (only DWARF is supported)"); } template <class IntPtrT> -Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData() { +Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData(int MaxWarnings) { assert(Data.empty() && Names.empty() && NamesVec.empty()); - correlateProfileDataImpl(); - if (Data.empty() || NamesVec.empty()) + correlateProfileDataImpl(MaxWarnings); + if (this->Data.empty()) return make_error<InstrProfError>( instrprof_error::unable_to_correlate_profile, - "could not find any profile metadata in debug info"); - auto Result = - collectPGOFuncNameStrings(NamesVec, /*doCompression=*/false, Names); - CounterOffsets.clear(); - NamesVec.clear(); + "could not find any profile data metadata in correlated file"); + Error Result = correlateProfileNameImpl(); + this->CounterOffsets.clear(); + this->NamesVec.clear(); return Result; } @@ -180,13 +198,14 @@ template <> struct yaml::SequenceElementTraits<InstrProfCorrelator::Probe> { }; template <class IntPtrT> -Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(raw_ostream &OS) { +Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(int MaxWarnings, + raw_ostream &OS) { InstrProfCorrelator::CorrelationData Data; - correlateProfileDataImpl(&Data); + correlateProfileDataImpl(MaxWarnings, &Data); if (Data.Probes.empty()) return make_error<InstrProfError>( instrprof_error::unable_to_correlate_profile, - "could not find any profile metadata in debug info"); + "could not find any profile data metadata in debug info"); yaml::Output YamlOS(OS); YamlOS << Data; return Error::success(); @@ -207,11 +226,15 @@ void InstrProfCorrelatorImpl<IntPtrT>::addProbe(StringRef FunctionName, // In this mode, CounterPtr actually stores the section relative address // of the counter. maybeSwap<IntPtrT>(CounterOffset), + // TODO: MC/DC is not yet supported. + /*BitmapOffset=*/maybeSwap<IntPtrT>(0), maybeSwap<IntPtrT>(FunctionPtr), // TODO: Value profiling is not yet supported. /*ValuesPtr=*/maybeSwap<IntPtrT>(0), maybeSwap<uint32_t>(NumCounters), /*NumValueSites=*/{maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)}, + // TODO: MC/DC is not yet supported. + /*NumBitmapBytes=*/maybeSwap<uint32_t>(0), }); NamesVec.push_back(FunctionName.str()); } @@ -260,7 +283,10 @@ bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die) { template <class IntPtrT> void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl( - InstrProfCorrelator::CorrelationData *Data) { + int MaxWarnings, InstrProfCorrelator::CorrelationData *Data) { + bool UnlimitedWarnings = (MaxWarnings == 0); + // -N suppressed warnings means we can emit up to N (unsuppressed) warnings + int NumSuppressedWarnings = -MaxWarnings; auto maybeAddProbe = [&](DWARFDie Die) { if (!isDIEOfProbe(Die)) return; @@ -297,28 +323,30 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl( } } if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) { - LLVM_DEBUG(dbgs() << "Incomplete DIE for probe\n\tFunctionName: " - << FunctionName << "\n\tCFGHash: " << CFGHash - << "\n\tCounterPtr: " << CounterPtr - << "\n\tNumCounters: " << NumCounters); - LLVM_DEBUG(Die.dump(dbgs())); + if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) { + WithColor::warning() + << "Incomplete DIE for function " << FunctionName + << ": CFGHash=" << CFGHash << " CounterPtr=" << CounterPtr + << " NumCounters=" << NumCounters << "\n"; + LLVM_DEBUG(Die.dump(dbgs())); + } return; } uint64_t CountersStart = this->Ctx->CountersSectionStart; uint64_t CountersEnd = this->Ctx->CountersSectionEnd; if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) { - LLVM_DEBUG( - dbgs() << "CounterPtr out of range for probe\n\tFunction Name: " - << FunctionName << "\n\tExpected: [0x" - << Twine::utohexstr(CountersStart) << ", 0x" - << Twine::utohexstr(CountersEnd) << ")\n\tActual: 0x" - << Twine::utohexstr(*CounterPtr)); - LLVM_DEBUG(Die.dump(dbgs())); + if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) { + WithColor::warning() + << format("CounterPtr out of range for function %s: Actual=0x%x " + "Expected=[0x%x, 0x%x)\n", + *FunctionName, *CounterPtr, CountersStart, CountersEnd); + LLVM_DEBUG(Die.dump(dbgs())); + } return; } - if (!FunctionPtr) { - LLVM_DEBUG(dbgs() << "Could not find address of " << *FunctionName - << "\n"); + if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) { + WithColor::warning() << format("Could not find address of function %s\n", + *FunctionName); LLVM_DEBUG(Die.dump(dbgs())); } IntPtrT CounterOffset = *CounterPtr - CountersStart; @@ -348,4 +376,21 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl( for (auto &CU : DICtx->dwo_units()) for (const auto &Entry : CU->dies()) maybeAddProbe(DWARFDie(CU.get(), &Entry)); + + if (!UnlimitedWarnings && NumSuppressedWarnings > 0) + WithColor::warning() << format("Suppressed %d additional warnings\n", + NumSuppressedWarnings); +} + +template <class IntPtrT> +Error DwarfInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() { + if (this->NamesVec.empty()) { + return make_error<InstrProfError>( + instrprof_error::unable_to_correlate_profile, + "could not find any profile name metadata in debug info"); + } + auto Result = + collectGlobalObjectNameStrings(this->NamesVec, + /*doCompression=*/false, this->Names); + return Result; } |
