24#define DEBUG_TYPE "ctx_prof"
29 cl::desc(
"Use the specified contextual profile file"));
32 "ctx-profile-printer-level",
35 "everything",
"print everything - most verbose"),
36 clEnumValN(CtxProfAnalysisPrinterPass::PrintMode::YAML,
"yaml",
37 "just the yaml representation of the profile")),
38 cl::desc(
"Verbosity level of the contextual profile printer pass."));
43 for (
auto &
F : M.functions()) {
44 if (
F.isDeclaration())
51 {ConstantAsMetadata::get(ConstantInt::get(
52 Type::getInt64Ty(M.getContext()), GUID))}));
58 if (
F.isDeclaration()) {
63 assert(MD &&
"guid not found for defined function");
64 return cast<ConstantInt>(cast<ConstantAsMetadata>(MD->getOperand(0))
66 ->stripPointerCasts())
86 M.getContext().emitError(
"could not open contextual profile file: " +
93 M.getContext().emitError(
"contextual profile file is invalid: " +
99 for (
const auto &
F : M)
100 if (!
F.isDeclaration())
102 MaybeCtx->find(GUID) != MaybeCtx->end())
103 ProfileRootsInModule.
insert(GUID);
107 if (!ProfileRootsInModule.
contains(RootGuid))
108 MaybeCtx->erase(RootGuid);
111 if (MaybeCtx->empty())
117 for (
const auto &
F : M) {
118 if (
F.isDeclaration())
121 assert(GUID &&
"guid not found for defined function");
122 const auto &Entry =
F.begin();
124 for (
const auto &
I : *Entry)
125 if (
auto *
C = dyn_cast<InstrProfIncrementInst>(&
I)) {
127 static_cast<uint32_t>(
C->getNumCounters()->getZExtValue());
133 for (
const auto &BB :
F)
134 for (
const auto &
I : BB)
135 if (
auto *
C = dyn_cast<InstrProfCallsite>(&
I)) {
137 static_cast<uint32_t>(
C->getNumCounters()->getZExtValue());
140 auto [It, Ins] =
Result.FuncInfo.insert(
141 {GUID, PGOContextualProfile::FunctionInfo(
F.getName())});
144 It->second.NextCallsiteIndex = MaxCallsites;
145 It->second.NextCounterIndex = MaxCounters;
149 Result.Profiles = std::move(*MaybeCtx);
155PGOContextualProfile::getDefinedFunctionGUID(
const Function &
F)
const {
168 OS <<
"No contextual profile was provided.\n";
173 OS <<
"Function Info:\n";
174 for (
const auto &[
Guid, FuncInfo] :
C.FuncInfo)
175 OS <<
Guid <<
" : " << FuncInfo.Name
176 <<
". MaxCounterID: " << FuncInfo.NextCounterIndex
177 <<
". MaxCallsiteID: " << FuncInfo.NextCallsiteIndex <<
"\n";
181 OS <<
"\nCurrent Profile:\n";
187 OS <<
"\nFlat Profile:\n";
188 auto Flat =
C.flatten();
202 if (
auto *IPC = dyn_cast<InstrProfCallsite>(Prev))
204 assert(!isa<CallBase>(Prev) &&
205 "didn't expect to find another call, that's not the callsite "
206 "instrumentation, before an instrumentable callsite");
213 if (
auto *Incr = dyn_cast<InstrProfIncrementInst>(&
I))
214 if (!isa<InstrProfIncrementInstStep>(&
I))
223 if (
auto *Step = dyn_cast<InstrProfIncrementInstStep>(Prev))
228template <
class ProfilesTy,
class ProfTy>
231 std::function<void(ProfTy &)> Traverser = [&](
auto &Ctx) {
233 for (
auto &[
_, SubCtxSet] : Ctx.callsites())
234 for (
auto &[__, Subctx] : SubCtxSet)
237 for (
auto &[
_,
P] : Profiles)
241void PGOContextualProfile::initIndex() {
245 for (
auto &[
Guid, FI] : FuncInfo)
246 InsertionPoints[
Guid] = &FI.Index;
247 preorderVisit<PGOCtxProfContext::CallTargetMapTy, PGOCtxProfContext>(
249 auto InsertIt = InsertionPoints.
find(Ctx.
guid());
250 if (InsertIt == InsertionPoints.
end())
256 InsertIt->second->Next = &Ctx;
257 Ctx.Previous = InsertIt->second;
258 InsertIt->second = &Ctx;
265 for (
auto *Node = FuncInfo.find(
G)->second.Index.Next; Node;
276 for (
const auto *Node = FuncInfo.find(
G)->second.Index.Next; Node;
282 assert(Profiles.has_value());
287 auto [It, Ins] = Flat.insert({Ctx.
guid(), {}});
293 "All contexts corresponding to a function should have the exact "
294 "same number of counters.");
295 for (
size_t I = 0, E = It->second.size();
I < E; ++
I)
303 SetVector<std::pair<CallBase *, Function *>> &Candidates) {
308 const uint32_t CallID = Instr->getIndex()->getZExtValue();
314 for (
const auto &[
Guid,
_] : Targets->second)
317 if (
Target->hasFnAttribute(Attribute::AlwaysInline))
318 Candidates.insert({&IC, Target});
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
static void preorderVisit(ProfilesTy &Profiles, function_ref< void(ProfTy &)> Visitor)
static cl::opt< CtxProfAnalysisPrinterPass::PrintMode > PrintLevel("ctx-profile-printer-level", cl::init(CtxProfAnalysisPrinterPass::PrintMode::YAML), cl::Hidden, cl::values(clEnumValN(CtxProfAnalysisPrinterPass::PrintMode::Everything, "everything", "print everything - most verbose"), clEnumValN(CtxProfAnalysisPrinterPass::PrintMode::YAML, "yaml", "just the yaml representation of the profile")), cl::desc("Verbosity level of the contextual profile printer pass."))
cl::opt< std::string > UseCtxProfile("use-ctx-profile", cl::init(""), cl::Hidden, cl::desc("Use the specified contextual profile file"))
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
Reader for contextual iFDO profile, which comes in bitstream format.
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
static uint64_t getGUID(const Function &F)
static const char * GUIDMetadataName
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
Assign a GUID if one is not already assign, as a function metadata named GUIDMetadataName.
LLVM Basic Block Representation.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCaller()
Helper to get the caller (the parent function).
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
CtxProfAnalysisPrinterPass(raw_ostream &OS)
PGOContextualProfile run(Module &M, ModuleAnalysisManager &MAM)
static InstrProfIncrementInst * getBBInstrumentation(BasicBlock &BB)
Get the instruction instrumenting a BB, or nullptr if not present.
static InstrProfIncrementInstStep * getSelectInstrumentation(SelectInst &SI)
Get the step instrumentation associated with a select
static void collectIndirectCallPromotionList(CallBase &IC, Result &Profile, SetVector< std::pair< CallBase *, Function * > > &Candidates)
static InstrProfCallsite * getCallsiteInstrumentation(CallBase &CB)
Get the instruction instrumenting a callsite, or nullptr if that cannot be found.
PGOContextualProfile Result
CtxProfAnalysis(std::optional< StringRef > Profile=std::nullopt)
iterator find(const_arg_type_t< KeyT > Val)
Implements a dense probed hash-table based set.
Represents either an error or a value T.
std::error_code getError() const
GUID getGUID() const
Return a 64-bit global unique ID constructed from global value name (i.e.
static bool isExternalLinkage(LinkageTypes Linkage)
This represents the llvm.instrprof.callsite intrinsic.
static bool canInstrumentCallsite(const CallBase &CB)
This represents the llvm.instrprof.increment.step intrinsic.
This represents the llvm.instrprof.increment intrinsic.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
A Module instance is used to store all the information related to an LLVM module.
The instrumented contextual profile, produced by the CtxProfAnalysis.
void visit(ConstVisitor, const Function *F=nullptr) const
const CtxProfFlatProfile flatten() const
void update(Visitor, const Function &F)
bool isFunctionKnown(const Function &F) const
A node (context) in the loaded contextual profile, suitable for mutation during IPO passes.
GlobalValue::GUID guid() const
const SmallVectorImpl< uint64_t > & counters() const
std::map< GlobalValue::GUID, PGOCtxProfContext > CallTargetMapTy
const CallsiteMapTy & callsites() const
Expected< std::map< GlobalValue::GUID, PGOCtxProfContext > > loadContexts()
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This class represents the LLVM 'select' instruction.
A vector that has set insertion semantics.
StringRef - Represent a constant reference to a string, i.e.
Target - Wrapper for Target specific information.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
Pass manager infrastructure for declaring and invalidating analyses.
@ C
The default llvm calling convention, compatible with C.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
std::map< GlobalValue::GUID, SmallVector< uint64_t, 1 > > CtxProfFlatProfile
void convertCtxProfToYaml(raw_ostream &OS, const PGOCtxProfContext::CallTargetMapTy &)
const char * toString(DWARFSectionKind Kind)
Implement std::hash so that hash_code can be used in STL containers.
A special type used by analysis passes to provide an address that identifies that particular analysis...