• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- CtxProfAnalysis.h - maintain contextual profile info   -*- C++ ---*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 #ifndef LLVM_ANALYSIS_CTXPROFANALYSIS_H
10 #define LLVM_ANALYSIS_CTXPROFANALYSIS_H
11 
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/IR/GlobalValue.h"
14 #include "llvm/IR/InstrTypes.h"
15 #include "llvm/IR/IntrinsicInst.h"
16 #include "llvm/IR/PassManager.h"
17 #include "llvm/ProfileData/PGOCtxProfReader.h"
18 
19 namespace llvm {
20 
21 class CtxProfAnalysis;
22 
23 // Setting initial capacity to 1 because all contexts must have at least 1
24 // counter, and then, because all contexts belonging to a function have the same
25 // size, there'll be at most one other heap allocation.
26 using CtxProfFlatProfile =
27     DenseMap<GlobalValue::GUID, SmallVector<uint64_t, 1>>;
28 
29 /// The instrumented contextual profile, produced by the CtxProfAnalysis.
30 class PGOContextualProfile {
31   friend class CtxProfAnalysis;
32   friend class CtxProfAnalysisPrinterPass;
33   struct FunctionInfo {
34     uint32_t NextCounterIndex = 0;
35     uint32_t NextCallsiteIndex = 0;
36     const std::string Name;
37 
FunctionInfoFunctionInfo38     FunctionInfo(StringRef Name) : Name(Name) {}
39   };
40   std::optional<PGOCtxProfContext::CallTargetMapTy> Profiles;
41   // For the GUIDs in this module, associate metadata about each function which
42   // we'll need when we maintain the profiles during IPO transformations.
43   DenseMap<GlobalValue::GUID, FunctionInfo> FuncInfo;
44 
45   /// Get the GUID of this Function if it's defined in this module.
46   GlobalValue::GUID getDefinedFunctionGUID(const Function &F) const;
47 
48   // This is meant to be constructed from CtxProfAnalysis, which will also set
49   // its state piecemeal.
50   PGOContextualProfile() = default;
51 
52 public:
53   PGOContextualProfile(const PGOContextualProfile &) = delete;
54   PGOContextualProfile(PGOContextualProfile &&) = default;
55 
56   operator bool() const { return Profiles.has_value(); }
57 
profiles()58   const PGOCtxProfContext::CallTargetMapTy &profiles() const {
59     return *Profiles;
60   }
61 
isFunctionKnown(const Function & F)62   bool isFunctionKnown(const Function &F) const {
63     return getDefinedFunctionGUID(F) != 0;
64   }
65 
allocateNextCounterIndex(const Function & F)66   uint32_t allocateNextCounterIndex(const Function &F) {
67     assert(isFunctionKnown(F));
68     return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex++;
69   }
70 
allocateNextCallsiteIndex(const Function & F)71   uint32_t allocateNextCallsiteIndex(const Function &F) {
72     assert(isFunctionKnown(F));
73     return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex++;
74   }
75 
76   const CtxProfFlatProfile flatten() const;
77 
invalidate(Module &,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)78   bool invalidate(Module &, const PreservedAnalyses &PA,
79                   ModuleAnalysisManager::Invalidator &) {
80     // Check whether the analysis has been explicitly invalidated. Otherwise,
81     // it's stateless and remains preserved.
82     auto PAC = PA.getChecker<CtxProfAnalysis>();
83     return !PAC.preservedWhenStateless();
84   }
85 };
86 
87 class CtxProfAnalysis : public AnalysisInfoMixin<CtxProfAnalysis> {
88   StringRef Profile;
89 
90 public:
91   static AnalysisKey Key;
92   explicit CtxProfAnalysis(StringRef Profile = "");
93 
94   using Result = PGOContextualProfile;
95 
96   PGOContextualProfile run(Module &M, ModuleAnalysisManager &MAM);
97 
98   /// Get the instruction instrumenting a callsite, or nullptr if that cannot be
99   /// found.
100   static InstrProfCallsite *getCallsiteInstrumentation(CallBase &CB);
101 
102   /// Get the instruction instrumenting a BB, or nullptr if not present.
103   static InstrProfIncrementInst *getBBInstrumentation(BasicBlock &BB);
104 };
105 
106 class CtxProfAnalysisPrinterPass
107     : public PassInfoMixin<CtxProfAnalysisPrinterPass> {
108   raw_ostream &OS;
109 
110 public:
CtxProfAnalysisPrinterPass(raw_ostream & OS)111   explicit CtxProfAnalysisPrinterPass(raw_ostream &OS) : OS(OS) {}
112 
113   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
isRequired()114   static bool isRequired() { return true; }
115 };
116 
117 /// Assign a GUID to functions as metadata. GUID calculation takes linkage into
118 /// account, which may change especially through and after thinlto. By
119 /// pre-computing and assigning as metadata, this mechanism is resilient to such
120 /// changes (as well as name changes e.g. suffix ".llvm." additions).
121 
122 // FIXME(mtrofin): we can generalize this mechanism to calculate a GUID early in
123 // the pass pipeline, associate it with any Global Value, and then use it for
124 // PGO and ThinLTO.
125 // At that point, this should be moved elsewhere.
126 class AssignGUIDPass : public PassInfoMixin<AssignGUIDPass> {
127 public:
128   explicit AssignGUIDPass() = default;
129 
130   /// Assign a GUID *if* one is not already assign, as a function metadata named
131   /// `GUIDMetadataName`.
132   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
133   static const char *GUIDMetadataName;
134   // This should become GlobalValue::getGUID
135   static uint64_t getGUID(const Function &F);
136 };
137 
138 } // namespace llvm
139 #endif // LLVM_ANALYSIS_CTXPROFANALYSIS_H
140