Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:12

0001 //===- CtxProfAnalysis.h - maintain contextual profile info   -*- C++ ---*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 #ifndef LLVM_ANALYSIS_CTXPROFANALYSIS_H
0010 #define LLVM_ANALYSIS_CTXPROFANALYSIS_H
0011 
0012 #include "llvm/ADT/SetVector.h"
0013 #include "llvm/IR/GlobalValue.h"
0014 #include "llvm/IR/InstrTypes.h"
0015 #include "llvm/IR/IntrinsicInst.h"
0016 #include "llvm/IR/PassManager.h"
0017 #include "llvm/ProfileData/PGOCtxProfReader.h"
0018 #include <optional>
0019 
0020 namespace llvm {
0021 
0022 class CtxProfAnalysis;
0023 
0024 // Setting initial capacity to 1 because all contexts must have at least 1
0025 // counter, and then, because all contexts belonging to a function have the same
0026 // size, there'll be at most one other heap allocation.
0027 using CtxProfFlatProfile =
0028     std::map<GlobalValue::GUID, SmallVector<uint64_t, 1>>;
0029 
0030 /// The instrumented contextual profile, produced by the CtxProfAnalysis.
0031 class PGOContextualProfile {
0032   friend class CtxProfAnalysis;
0033   friend class CtxProfAnalysisPrinterPass;
0034   struct FunctionInfo {
0035     uint32_t NextCounterIndex = 0;
0036     uint32_t NextCallsiteIndex = 0;
0037     const std::string Name;
0038     PGOCtxProfContext Index;
0039     FunctionInfo(StringRef Name) : Name(Name) {}
0040   };
0041   std::optional<PGOCtxProfContext::CallTargetMapTy> Profiles;
0042   // For the GUIDs in this module, associate metadata about each function which
0043   // we'll need when we maintain the profiles during IPO transformations.
0044   std::map<GlobalValue::GUID, FunctionInfo> FuncInfo;
0045 
0046   /// Get the GUID of this Function if it's defined in this module.
0047   GlobalValue::GUID getDefinedFunctionGUID(const Function &F) const;
0048 
0049   // This is meant to be constructed from CtxProfAnalysis, which will also set
0050   // its state piecemeal.
0051   PGOContextualProfile() = default;
0052 
0053   void initIndex();
0054 
0055 public:
0056   PGOContextualProfile(const PGOContextualProfile &) = delete;
0057   PGOContextualProfile(PGOContextualProfile &&) = default;
0058 
0059   operator bool() const { return Profiles.has_value(); }
0060 
0061   const PGOCtxProfContext::CallTargetMapTy &profiles() const {
0062     return *Profiles;
0063   }
0064 
0065   bool isFunctionKnown(const Function &F) const {
0066     return getDefinedFunctionGUID(F) != 0;
0067   }
0068 
0069   StringRef getFunctionName(GlobalValue::GUID GUID) const {
0070     auto It = FuncInfo.find(GUID);
0071     if (It == FuncInfo.end())
0072       return "";
0073     return It->second.Name;
0074   }
0075 
0076   uint32_t getNumCounters(const Function &F) const {
0077     assert(isFunctionKnown(F));
0078     return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex;
0079   }
0080 
0081   uint32_t getNumCallsites(const Function &F) const {
0082     assert(isFunctionKnown(F));
0083     return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex;
0084   }
0085 
0086   uint32_t allocateNextCounterIndex(const Function &F) {
0087     assert(isFunctionKnown(F));
0088     return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex++;
0089   }
0090 
0091   uint32_t allocateNextCallsiteIndex(const Function &F) {
0092     assert(isFunctionKnown(F));
0093     return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex++;
0094   }
0095 
0096   using ConstVisitor = function_ref<void(const PGOCtxProfContext &)>;
0097   using Visitor = function_ref<void(PGOCtxProfContext &)>;
0098 
0099   void update(Visitor, const Function &F);
0100   void visit(ConstVisitor, const Function *F = nullptr) const;
0101 
0102   const CtxProfFlatProfile flatten() const;
0103 
0104   bool invalidate(Module &, const PreservedAnalyses &PA,
0105                   ModuleAnalysisManager::Invalidator &) {
0106     // Check whether the analysis has been explicitly invalidated. Otherwise,
0107     // it's stateless and remains preserved.
0108     auto PAC = PA.getChecker<CtxProfAnalysis>();
0109     return !PAC.preservedWhenStateless();
0110   }
0111 };
0112 
0113 class CtxProfAnalysis : public AnalysisInfoMixin<CtxProfAnalysis> {
0114   const std::optional<StringRef> Profile;
0115 
0116 public:
0117   static AnalysisKey Key;
0118   explicit CtxProfAnalysis(std::optional<StringRef> Profile = std::nullopt);
0119 
0120   using Result = PGOContextualProfile;
0121 
0122   PGOContextualProfile run(Module &M, ModuleAnalysisManager &MAM);
0123 
0124   /// Get the instruction instrumenting a callsite, or nullptr if that cannot be
0125   /// found.
0126   static InstrProfCallsite *getCallsiteInstrumentation(CallBase &CB);
0127 
0128   /// Get the instruction instrumenting a BB, or nullptr if not present.
0129   static InstrProfIncrementInst *getBBInstrumentation(BasicBlock &BB);
0130 
0131   /// Get the step instrumentation associated with a `select`
0132   static InstrProfIncrementInstStep *getSelectInstrumentation(SelectInst &SI);
0133 
0134   // FIXME: refactor to an advisor model, and separate
0135   static void collectIndirectCallPromotionList(
0136       CallBase &IC, Result &Profile,
0137       SetVector<std::pair<CallBase *, Function *>> &Candidates);
0138 };
0139 
0140 class CtxProfAnalysisPrinterPass
0141     : public PassInfoMixin<CtxProfAnalysisPrinterPass> {
0142 public:
0143   enum class PrintMode { Everything, YAML };
0144   explicit CtxProfAnalysisPrinterPass(raw_ostream &OS);
0145 
0146   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
0147   static bool isRequired() { return true; }
0148 
0149 private:
0150   raw_ostream &OS;
0151   const PrintMode Mode;
0152 };
0153 
0154 /// Assign a GUID to functions as metadata. GUID calculation takes linkage into
0155 /// account, which may change especially through and after thinlto. By
0156 /// pre-computing and assigning as metadata, this mechanism is resilient to such
0157 /// changes (as well as name changes e.g. suffix ".llvm." additions).
0158 
0159 // FIXME(mtrofin): we can generalize this mechanism to calculate a GUID early in
0160 // the pass pipeline, associate it with any Global Value, and then use it for
0161 // PGO and ThinLTO.
0162 // At that point, this should be moved elsewhere.
0163 class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
0164 public:
0165   explicit AssignGUIDPass() = default;
0166 
0167   /// Assign a GUID *if* one is not already assign, as a function metadata named
0168   /// `GUIDMetadataName`.
0169   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
0170   static const char *GUIDMetadataName;
0171   // This should become GlobalValue::getGUID
0172   static uint64_t getGUID(const Function &F);
0173 };
0174 
0175 } // namespace llvm
0176 #endif // LLVM_ANALYSIS_CTXPROFANALYSIS_H