Go to the documentation of this file.
20 #define DEBUG_TYPE "correlator"
30 return make_error<InstrProfError>(
32 "could not find counter section (" INSTR_PROF_CNTS_SECT_NAME
")");
43 if (
auto Err = CountersSection.takeError())
45 auto C = std::make_unique<Context>();
47 C->CountersSectionStart = CountersSection->getAddress();
48 C->CountersSectionEnd =
C->CountersSectionStart + CountersSection->getSize();
55 auto DsymObjectsOrErr =
57 if (
auto Err = DsymObjectsOrErr.takeError())
59 if (!DsymObjectsOrErr->empty()) {
62 if (DsymObjectsOrErr->size() > 1)
63 return make_error<InstrProfError>(
65 "using multiple objects is not yet supported");
66 DebugInfoFilename = *DsymObjectsOrErr->
begin();
70 if (
auto Err = BufferOrErr.takeError())
79 if (
auto Err = BinOrErr.takeError())
82 if (
auto *Obj = dyn_cast<object::ObjectFile>(BinOrErr->get())) {
84 if (
auto Err = CtxOrErr.takeError())
86 auto T = Obj->makeTriple();
92 return make_error<InstrProfError>(
98 return C->getDataSize();
100 return C->getDataSize();
109 std::unique_ptr<InstrProfCorrelator::Context>
Ctx)
114 std::unique_ptr<InstrProfCorrelator::Context> Ctx)
119 return C->getKind() == InstrProfCorrelatorKind::CK_32Bit;
123 return C->getKind() == InstrProfCorrelatorKind::CK_64Bit;
128 template <
class IntPtrT>
131 std::unique_ptr<InstrProfCorrelator::Context> Ctx,
134 auto DICtx = DWARFContext::create(Obj);
135 return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(
std::move(DICtx),
138 return make_error<InstrProfError>(
139 instrprof_error::unable_to_correlate_profile,
140 "unsupported debug info format (only DWARF is supported)");
143 template <
class IntPtrT>
145 assert(
Data.empty() && Names.empty() && NamesVec.empty());
146 correlateProfileDataImpl();
147 if (
Data.empty() || NamesVec.empty())
148 return make_error<InstrProfError>(
149 instrprof_error::unable_to_correlate_profile,
150 "could not find any profile metadata in debug info");
153 CounterOffsets.clear();
158 template <
class IntPtrT>
161 IntPtrT CounterOffset,
165 if (!CounterOffsets.insert(CounterOffset).second)
169 maybeSwap<uint64_t>(CFGHash),
172 maybeSwap<IntPtrT>(CounterOffset),
173 maybeSwap<IntPtrT>(FunctionPtr),
175 maybeSwap<IntPtrT>(0),
176 maybeSwap<uint32_t>(NumCounters),
177 {maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
179 NamesVec.push_back(FunctionName.
str());
182 template <
class IntPtrT>
185 auto Locations = Die.
getLocations(dwarf::DW_AT_location);
192 for (
auto &Location : *Locations) {
195 for (
auto &
Op : Expr) {
196 if (
Op.getCode() == dwarf::DW_OP_addr) {
197 return Op.getRawOperand(0);
198 }
else if (
Op.getCode() == dwarf::DW_OP_addrx) {
200 if (
auto SA = DU.getAddrOffsetSectionItem(
Index))
208 template <
class IntPtrT>
213 if (Die.
getTag() != dwarf::DW_TAG_variable)
215 if (!ParentDie.isSubprogramDIE())
219 if (
const char *
Name = Die.
getName(DINameKind::ShortName))
224 template <
class IntPtrT>
226 auto maybeAddProbe = [&](
DWARFDie Die) {
227 if (!isDIEOfProbe(Die))
236 if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
238 auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
239 auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
240 if (!AnnotationFormName || !AnnotationFormValue)
242 auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
243 if (
auto Err = AnnotationNameOrErr.takeError()) {
247 StringRef AnnotationName = *AnnotationNameOrErr;
249 InstrProfCorrelator::FunctionNameAttributeName) == 0) {
251 AnnotationFormValue->getAsCString().moveInto(FunctionName))
253 }
else if (AnnotationName.
compare(
254 InstrProfCorrelator::CFGHashAttributeName) == 0) {
255 CFGHash = AnnotationFormValue->getAsUnsignedConstant();
256 }
else if (AnnotationName.
compare(
257 InstrProfCorrelator::NumCountersAttributeName) == 0) {
258 NumCounters = AnnotationFormValue->getAsUnsignedConstant();
261 if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
263 << FunctionName <<
"\n\tCFGHash: " << CFGHash
264 <<
"\n\tCounterPtr: " << CounterPtr
265 <<
"\n\tNumCounters: " << NumCounters);
269 uint64_t CountersStart = this->Ctx->CountersSectionStart;
270 uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
271 if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
273 dbgs() <<
"CounterPtr out of range for probe\n\tFunction Name: "
274 << FunctionName <<
"\n\tExpected: [0x"
275 << Twine::utohexstr(CountersStart) <<
", 0x"
276 << Twine::utohexstr(CountersEnd) <<
")\n\tActual: 0x"
277 << Twine::utohexstr(*CounterPtr));
282 LLVM_DEBUG(
dbgs() <<
"Could not find address of " << *FunctionName
286 this->addProbe(*FunctionName, *CFGHash, *CounterPtr - CountersStart,
287 FunctionPtr.getValueOr(0), *NumCounters);
289 for (
auto &
CU : DICtx->normal_units())
290 for (
const auto &Entry :
CU->dies())
292 for (
auto &
CU : DICtx->dwo_units())
293 for (
const auto &Entry :
CU->dies())
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
This is an optimization pass for GlobalISel generic memory operations.
static const char * NumCountersAttributeName
static Expected< std::vector< std::string > > findDsymObjectMembers(StringRef Path)
If the input path is a .dSYM bundle (as created by the dsymutil tool), return the paths to the object...
bool isLittleEndian() const
llvm::Optional< size_t > getDataSize() const
Return the number of ProfileData elements.
uint64_t ComputeHash(StringRef K)
static const char * CFGHashAttributeName
Tagged union holding either a T or a Error.
bool isNULL() const
Returns true for a valid DIE that terminates a sibling chain.
iterator_range< iterator > children() const
void consumeError(Error Err)
Consume a Error without doing anything.
Optional< uint64_t > toAddress(const Optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an address.
InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template pointer type so that the Pro...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes DWARF debug info as input to...
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
(vector float) vec_cmpeq(*A, *B) C
static const char * FunctionNameAttributeName
const std::unique_ptr< InstrProfCorrelator::Context > Ctx
StringRef getInstrProfCountersVarPrefix()
Return the name prefix of profile counter variables.
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
void dump(raw_ostream &OS, unsigned indent=0, DIDumpOptions DumpOpts=DIDumpOptions()) const
Dump the DIE and all of its attributes to the supplied stream.
InstrProfCorrelatorImpl(std::unique_ptr< InstrProfCorrelator::Context > Ctx)
static llvm::Expected< std::unique_ptr< InstrProfCorrelator > > get(StringRef DebugInfoFilename)
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Error collectPGOFuncNameStrings(ArrayRef< std::string > NameStrs, bool doCompression, std::string &Result)
Given a vector of strings (function PGO names) NameStrs, the method generates a combined string Resul...
static bool classof(const InstrProfCorrelator *C)
Expected< object::SectionRef > getCountersSection(const object::ObjectFile &Obj)
Get the __llvm_prf_cnts section.
Expected< DWARFLocationExpressionsVector > getLocations(dwarf::Attribute Attr) const
static llvm::Expected< std::unique_ptr< Context > > get(std::unique_ptr< MemoryBuffer > Buffer, const object::ObjectFile &Obj)
std::unique_ptr< MemoryBuffer > Buffer
StringRef - Represent a constant reference to a string, i.e.
This class is the base class for all object file types.
DWARFUnit * getDwarfUnit() const
const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
static llvm::Expected< std::unique_ptr< InstrProfCorrelatorImpl< IntPtrT > > > get(std::unique_ptr< InstrProfCorrelator::Context > Ctx, const object::ObjectFile &Obj)
DWARFDie getParent() const
Get the parent of this DIE object.
uint8_t getAddressByteSize() const
Should compile to something r4 addze r3 instead we get
Lightweight error class with error context and mandatory checking.
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
dwarf::Tag getTag() const
static const bool IsLittleEndianHost
@ unable_to_correlate_profile
section_iterator_range sections() const
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
InstrProfCorrelator - A base class used to create raw instrumentation data to their functions.
static MemoryLocation getLocation(Instruction *I)
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
LLVM_NODISCARD int compare(StringRef RHS) const
compare - Compare two strings; the result is -1, 0, or 1 if this string is lexicographically less tha...
decltype(auto) LLVM_NODISCARD dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.