1 //===- StandardInstrumentations.h ------------------------------*- 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 /// \file 9 /// 10 /// This header defines a class that provides bookkeeping for all standard 11 /// (i.e in-tree) pass instrumentations. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H 16 #define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H 17 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/IR/BasicBlock.h" 21 #include "llvm/IR/OptBisect.h" 22 #include "llvm/IR/PassTimingInfo.h" 23 #include "llvm/IR/ValueHandle.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Transforms/IPO/SampleProfileProbe.h" 26 27 #include <string> 28 #include <utility> 29 30 namespace llvm { 31 32 class Module; 33 class Function; 34 class PassInstrumentationCallbacks; 35 36 /// Instrumentation to print IR before/after passes. 37 /// 38 /// Needs state to be able to print module after pass that invalidates IR unit 39 /// (typically Loop or SCC). 40 class PrintIRInstrumentation { 41 public: 42 ~PrintIRInstrumentation(); 43 44 void registerCallbacks(PassInstrumentationCallbacks &PIC); 45 46 private: 47 void printBeforePass(StringRef PassID, Any IR); 48 void printAfterPass(StringRef PassID, Any IR); 49 void printAfterPassInvalidated(StringRef PassID); 50 51 bool shouldPrintBeforePass(StringRef PassID); 52 bool shouldPrintAfterPass(StringRef PassID); 53 54 using PrintModuleDesc = std::tuple<const Module *, std::string, StringRef>; 55 56 void pushModuleDesc(StringRef PassID, Any IR); 57 PrintModuleDesc popModuleDesc(StringRef PassID); 58 59 PassInstrumentationCallbacks *PIC; 60 /// Stack of Module description, enough to print the module after a given 61 /// pass. 62 SmallVector<PrintModuleDesc, 2> ModuleDescStack; 63 bool StoreModuleDesc = false; 64 }; 65 66 class OptNoneInstrumentation { 67 public: 68 OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} 69 void registerCallbacks(PassInstrumentationCallbacks &PIC); 70 71 private: 72 bool DebugLogging; 73 bool shouldRun(StringRef PassID, Any IR); 74 }; 75 76 class OptBisectInstrumentation { 77 public: 78 OptBisectInstrumentation() {} 79 void registerCallbacks(PassInstrumentationCallbacks &PIC); 80 }; 81 82 // Debug logging for transformation and analysis passes. 83 class PrintPassInstrumentation { 84 public: 85 PrintPassInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} 86 void registerCallbacks(PassInstrumentationCallbacks &PIC); 87 88 private: 89 bool DebugLogging; 90 }; 91 92 class PreservedCFGCheckerInstrumentation { 93 private: 94 // CFG is a map BB -> {(Succ, Multiplicity)}, where BB is a non-leaf basic 95 // block, {(Succ, Multiplicity)} set of all pairs of the block's successors 96 // and the multiplicity of the edge (BB->Succ). As the mapped sets are 97 // unordered the order of successors is not tracked by the CFG. In other words 98 // this allows basic block successors to be swapped by a pass without 99 // reporting a CFG change. CFG can be guarded by basic block tracking pointers 100 // in the Graph (BBGuard). That is if any of the block is deleted or RAUWed 101 // then the CFG is treated poisoned and no block pointer of the Graph is used. 102 struct CFG { 103 struct BBGuard final : public CallbackVH { 104 BBGuard(const BasicBlock *BB) : CallbackVH(BB) {} 105 void deleted() override { CallbackVH::deleted(); } 106 void allUsesReplacedWith(Value *) override { CallbackVH::deleted(); } 107 bool isPoisoned() const { return !getValPtr(); } 108 }; 109 110 Optional<DenseMap<intptr_t, BBGuard>> BBGuards; 111 DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph; 112 113 CFG(const Function *F, bool TrackBBLifetime = false); 114 115 bool operator==(const CFG &G) const { 116 return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph; 117 } 118 119 bool isPoisoned() const { 120 if (BBGuards) 121 for (auto &BB : *BBGuards) { 122 if (BB.second.isPoisoned()) 123 return true; 124 } 125 return false; 126 } 127 128 static void printDiff(raw_ostream &out, const CFG &Before, 129 const CFG &After); 130 }; 131 132 SmallVector<std::pair<StringRef, Optional<CFG>>, 8> GraphStackBefore; 133 134 public: 135 static cl::opt<bool> VerifyPreservedCFG; 136 void registerCallbacks(PassInstrumentationCallbacks &PIC); 137 }; 138 139 // Base class for classes that report changes to the IR. 140 // It presents an interface for such classes and provides calls 141 // on various events as the new pass manager transforms the IR. 142 // It also provides filtering of information based on hidden options 143 // specifying which functions are interesting. 144 // Calls are made for the following events/queries: 145 // 1. The initial IR processed. 146 // 2. To get the representation of the IR (of type \p T). 147 // 3. When a pass does not change the IR. 148 // 4. When a pass changes the IR (given both before and after representations 149 // of type \p T). 150 // 5. When an IR is invalidated. 151 // 6. When a pass is run on an IR that is not interesting (based on options). 152 // 7. When a pass is ignored (pass manager or adapter pass). 153 // 8. To compare two IR representations (of type \p T). 154 template <typename IRUnitT> class ChangeReporter { 155 protected: 156 ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {} 157 158 public: 159 virtual ~ChangeReporter(); 160 161 // Determine if this pass/IR is interesting and if so, save the IR 162 // otherwise it is left on the stack without data. 163 void saveIRBeforePass(Any IR, StringRef PassID); 164 // Compare the IR from before the pass after the pass. 165 void handleIRAfterPass(Any IR, StringRef PassID); 166 // Handle the situation where a pass is invalidated. 167 void handleInvalidatedPass(StringRef PassID); 168 169 protected: 170 // Register required callbacks. 171 void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC); 172 173 // Return true when this is a defined function for which printing 174 // of changes is desired. 175 bool isInterestingFunction(const Function &F); 176 177 // Return true when this is a pass for which printing of changes is desired. 178 bool isInterestingPass(StringRef PassID); 179 180 // Return true when this is a pass on IR for which printing 181 // of changes is desired. 182 bool isInteresting(Any IR, StringRef PassID); 183 184 // Called on the first IR processed. 185 virtual void handleInitialIR(Any IR) = 0; 186 // Called before and after a pass to get the representation of the IR. 187 virtual void generateIRRepresentation(Any IR, StringRef PassID, 188 IRUnitT &Output) = 0; 189 // Called when the pass is not iteresting. 190 virtual void omitAfter(StringRef PassID, std::string &Name) = 0; 191 // Called when an interesting IR has changed. 192 virtual void handleAfter(StringRef PassID, std::string &Name, 193 const IRUnitT &Before, const IRUnitT &After, 194 Any) = 0; 195 // Called when an interesting pass is invalidated. 196 virtual void handleInvalidated(StringRef PassID) = 0; 197 // Called when the IR or pass is not interesting. 198 virtual void handleFiltered(StringRef PassID, std::string &Name) = 0; 199 // Called when an ignored pass is encountered. 200 virtual void handleIgnored(StringRef PassID, std::string &Name) = 0; 201 // Called to compare the before and after representations of the IR. 202 virtual bool same(const IRUnitT &Before, const IRUnitT &After) = 0; 203 204 // Stack of IRs before passes. 205 std::vector<IRUnitT> BeforeStack; 206 // Is this the first IR seen? 207 bool InitialIR = true; 208 209 // Run in verbose mode, printing everything? 210 const bool VerboseMode; 211 }; 212 213 // An abstract template base class that handles printing banners and 214 // reporting when things have not changed or are filtered out. 215 template <typename IRUnitT> 216 class TextChangeReporter : public ChangeReporter<IRUnitT> { 217 protected: 218 TextChangeReporter(bool Verbose); 219 220 // Print a module dump of the first IR that is changed. 221 void handleInitialIR(Any IR) override; 222 // Report that the IR was omitted because it did not change. 223 void omitAfter(StringRef PassID, std::string &Name) override; 224 // Report that the pass was invalidated. 225 void handleInvalidated(StringRef PassID) override; 226 // Report that the IR was filtered out. 227 void handleFiltered(StringRef PassID, std::string &Name) override; 228 // Report that the pass was ignored. 229 void handleIgnored(StringRef PassID, std::string &Name) override; 230 // Make substitutions in \p S suitable for reporting changes 231 // after the pass and then print it. 232 233 raw_ostream &Out; 234 }; 235 236 // A change printer based on the string representation of the IR as created 237 // by unwrapAndPrint. The string representation is stored in a std::string 238 // to preserve it as the IR changes in each pass. Note that the banner is 239 // included in this representation but it is massaged before reporting. 240 class IRChangedPrinter : public TextChangeReporter<std::string> { 241 public: 242 IRChangedPrinter(bool VerboseMode) 243 : TextChangeReporter<std::string>(VerboseMode) {} 244 ~IRChangedPrinter() override; 245 void registerCallbacks(PassInstrumentationCallbacks &PIC); 246 247 protected: 248 // Called before and after a pass to get the representation of the IR. 249 void generateIRRepresentation(Any IR, StringRef PassID, 250 std::string &Output) override; 251 // Called when an interesting IR has changed. 252 void handleAfter(StringRef PassID, std::string &Name, 253 const std::string &Before, const std::string &After, 254 Any) override; 255 // Called to compare the before and after representations of the IR. 256 bool same(const std::string &Before, const std::string &After) override; 257 }; 258 259 class VerifyInstrumentation { 260 bool DebugLogging; 261 262 public: 263 VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} 264 void registerCallbacks(PassInstrumentationCallbacks &PIC); 265 }; 266 267 /// This class provides an interface to register all the standard pass 268 /// instrumentations and manages their state (if any). 269 class StandardInstrumentations { 270 PrintIRInstrumentation PrintIR; 271 PrintPassInstrumentation PrintPass; 272 TimePassesHandler TimePasses; 273 OptNoneInstrumentation OptNone; 274 OptBisectInstrumentation OptBisect; 275 PreservedCFGCheckerInstrumentation PreservedCFGChecker; 276 IRChangedPrinter PrintChangedIR; 277 PseudoProbeVerifier PseudoProbeVerification; 278 VerifyInstrumentation Verify; 279 280 bool VerifyEach; 281 282 public: 283 StandardInstrumentations(bool DebugLogging, bool VerifyEach = false); 284 285 void registerCallbacks(PassInstrumentationCallbacks &PIC); 286 287 TimePassesHandler &getTimePasses() { return TimePasses; } 288 }; 289 290 extern template class ChangeReporter<std::string>; 291 extern template class TextChangeReporter<std::string>; 292 293 } // namespace llvm 294 295 #endif 296