1 //===- Standard pass instrumentations handling ----------------*- C++ -*--===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// \file 10 /// 11 /// This file defines IR-printing pass instrumentation callbacks as well as 12 /// StandardInstrumentations class that manages standard pass instrumentations. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #include "llvm/Passes/StandardInstrumentations.h" 17 #include "llvm/Analysis/CallGraphSCCPass.h" 18 #include "llvm/Analysis/LazyCallGraph.h" 19 #include "llvm/Analysis/LoopInfo.h" 20 #include "llvm/IR/Function.h" 21 #include "llvm/IR/IRPrintingPasses.h" 22 #include "llvm/IR/Module.h" 23 #include "llvm/IR/PassInstrumentation.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/FormatVariadic.h" 26 #include "llvm/Support/raw_ostream.h" 27 28 using namespace llvm; 29 30 namespace { 31 namespace PrintIR { 32 33 //===----------------------------------------------------------------------===// 34 // IR-printing instrumentation 35 //===----------------------------------------------------------------------===// 36 37 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into 38 /// llvm::Any and does actual print job. 39 void unwrapAndPrint(StringRef Banner, Any IR) { 40 SmallString<40> Extra{"\n"}; 41 const Module *M = nullptr; 42 if (any_isa<const Module *>(IR)) { 43 M = any_cast<const Module *>(IR); 44 } else if (any_isa<const Function *>(IR)) { 45 const Function *F = any_cast<const Function *>(IR); 46 if (!llvm::isFunctionInPrintList(F->getName())) 47 return; 48 if (!llvm::forcePrintModuleIR()) { 49 dbgs() << Banner << Extra << static_cast<const Value &>(*F); 50 return; 51 } 52 M = F->getParent(); 53 Extra = formatv(" (function: {0})\n", F->getName()); 54 } else if (any_isa<const LazyCallGraph::SCC *>(IR)) { 55 const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR); 56 if (!llvm::forcePrintModuleIR()) { 57 Extra = formatv(" (scc: {0})\n", C->getName()); 58 bool BannerPrinted = false; 59 for (const LazyCallGraph::Node &N : *C) { 60 const Function &F = N.getFunction(); 61 if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { 62 if (!BannerPrinted) { 63 dbgs() << Banner << Extra; 64 BannerPrinted = true; 65 } 66 F.print(dbgs()); 67 } 68 } 69 return; 70 } 71 for (const LazyCallGraph::Node &N : *C) { 72 const Function &F = N.getFunction(); 73 if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) { 74 M = F.getParent(); 75 break; 76 } 77 } 78 if (!M) 79 return; 80 Extra = formatv(" (for scc: {0})\n", C->getName()); 81 } else if (any_isa<const Loop *>(IR)) { 82 const Loop *L = any_cast<const Loop *>(IR); 83 const Function *F = L->getHeader()->getParent(); 84 if (!isFunctionInPrintList(F->getName())) 85 return; 86 if (!llvm::forcePrintModuleIR()) { 87 llvm::printLoop(const_cast<Loop &>(*L), dbgs(), Banner); 88 return; 89 } 90 M = F->getParent(); 91 { 92 std::string LoopName; 93 raw_string_ostream ss(LoopName); 94 L->getHeader()->printAsOperand(ss, false); 95 Extra = formatv(" (loop: {0})\n", ss.str()); 96 } 97 } 98 if (M) { 99 dbgs() << Banner << Extra; 100 M->print(dbgs(), nullptr, false); 101 } else { 102 llvm_unreachable("Unknown wrapped IR type"); 103 } 104 } 105 106 bool printBeforePass(StringRef PassID, Any IR) { 107 if (!llvm::shouldPrintBeforePass(PassID)) 108 return true; 109 110 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) 111 return true; 112 113 SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID); 114 unwrapAndPrint(Banner, IR); 115 return true; 116 } 117 118 void printAfterPass(StringRef PassID, Any IR) { 119 if (!llvm::shouldPrintAfterPass(PassID)) 120 return; 121 122 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) 123 return; 124 125 SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); 126 unwrapAndPrint(Banner, IR); 127 return; 128 } 129 } // namespace PrintIR 130 } // namespace 131 132 void StandardInstrumentations::registerCallbacks( 133 PassInstrumentationCallbacks &PIC) { 134 if (llvm::shouldPrintBeforePass()) 135 PIC.registerBeforePassCallback(PrintIR::printBeforePass); 136 if (llvm::shouldPrintAfterPass()) 137 PIC.registerAfterPassCallback(PrintIR::printAfterPass); 138 TimePasses.registerCallbacks(PIC); 139 } 140