llvm.org GIT mirror llvm / 34239a9
[NewPM] -print-module-scope -print-after now prints module even after invalidated Loop/SCC -print-after IR printing generally can not print the IR unit (Loop or SCC) which has just been invalidated by the pass. However, when working in -print-module-scope mode even if Loop was invalidated there is still a valid module that we can print. Since we can not access invalidated IR unit from AfterPassInvalidated instrumentation point we can remember the module to be printed *before* pass. This change introduces BeforePass instrumentation that stores all the information required for module printing into the stack and then after pass (in AfterPassInvalidated) just print whatever has been placed on stack. Reviewed By: philip.pfaffe Differential Revision: https://reviews.llvm.org/D55278 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349896 91177308-0d34-0410-b5e6-96231b3b80d8 Fedor Sergeev 7 months ago
4 changed file(s) with 225 addition(s) and 83 deletion(s). Raw diff Collapse all Expand all
1515 #ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
1616 #define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H
1717
18 #include "llvm/ADT/SmallVector.h"
1819 #include "llvm/IR/PassInstrumentation.h"
1920 #include "llvm/IR/PassTimingInfo.h"
2021
22 #include
23 #include
24
2125 namespace llvm {
26
27 class Module;
28
29 /// Instrumentation to print IR before/after passes.
30 ///
31 /// Needs state to be able to print module after pass that invalidates IR unit
32 /// (typically Loop or SCC).
33 class PrintIRInstrumentation {
34 public:
35 PrintIRInstrumentation() = default;
36 ~PrintIRInstrumentation();
37
38 void registerCallbacks(PassInstrumentationCallbacks &PIC);
39
40 private:
41 bool printBeforePass(StringRef PassID, Any IR);
42 void printAfterPass(StringRef PassID, Any IR);
43 void printAfterPassInvalidated(StringRef PassID);
44
45 using PrintModuleDesc = std::tuple;
46
47 void pushModuleDesc(StringRef PassID, Any IR);
48 PrintModuleDesc popModuleDesc(StringRef PassID);
49
50 /// Stack of Module description, enough to print the module after a given
51 /// pass.
52 SmallVector ModuleDescStack;
53 bool StoreModuleDesc = false;
54 };
2255
2356 /// This class provides an interface to register all the standard pass
2457 /// instrumentations and manages their state (if any).
2558 class StandardInstrumentations {
59 PrintIRInstrumentation PrintIR;
2660 TimePassesHandler TimePasses;
2761
2862 public:
1313 //===----------------------------------------------------------------------===//
1414
1515 #include "llvm/Passes/StandardInstrumentations.h"
16 #include "llvm/ADT/Optional.h"
1617 #include "llvm/Analysis/CallGraphSCCPass.h"
1718 #include "llvm/Analysis/LazyCallGraph.h"
1819 #include "llvm/Analysis/LoopInfo.h"
2728 using namespace llvm;
2829
2930 namespace {
30 namespace PrintIR {
31
32 //===----------------------------------------------------------------------===//
33 // IR-printing instrumentation
34 //===----------------------------------------------------------------------===//
35
36 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
37 /// llvm::Any and does actual print job.
38 void unwrapAndPrint(StringRef Banner, Any IR) {
39 SmallString<40> Extra{"\n"};
40 const Module *M = nullptr;
41 if (any_isa(IR)) {
42 M = any_cast(IR);
43 } else if (any_isa(IR)) {
31
32 /// Extracting Module out of \p IR unit. Also fills a textual description
33 /// of \p IR for use in header when printing.
34 Optional> unwrapModule(Any IR) {
35 if (any_isa(IR))
36 return std::make_pair(any_cast(IR), std::string());
37
38 if (any_isa(IR)) {
4439 const Function *F = any_cast(IR);
4540 if (!llvm::isFunctionInPrintList(F->getName()))
46 return;
47 if (!llvm::forcePrintModuleIR()) {
48 dbgs() << Banner << Extra << static_cast(*F);
49 return;
50 }
51 M = F->getParent();
52 Extra = formatv(" (function: {0})\n", F->getName());
53 } else if (any_isa(IR)) {
41 return None;
42 const Module *M = F->getParent();
43 return std::make_pair(M, formatv(" (function: {0})", F->getName()).str());
44 }
45
46 if (any_isa(IR)) {
5447 const LazyCallGraph::SCC *C = any_cast(IR);
55 if (!llvm::forcePrintModuleIR()) {
56 Extra = formatv(" (scc: {0})\n", C->getName());
57 bool BannerPrinted = false;
58 for (const LazyCallGraph::Node &N : *C) {
59 const Function &F = N.getFunction();
60 if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
61 if (!BannerPrinted) {
62 dbgs() << Banner << Extra;
63 BannerPrinted = true;
64 }
65 F.print(dbgs());
66 }
67 }
68 return;
69 }
7048 for (const LazyCallGraph::Node &N : *C) {
7149 const Function &F = N.getFunction();
7250 if (!F.isDeclaration() && isFunctionInPrintList(F.getName())) {
73 M = F.getParent();
74 break;
51 const Module *M = F.getParent();
52 return std::make_pair(M, formatv(" (scc: {0})", C->getName()).str());
7553 }
7654 }
77 if (!M)
78 return;
79 Extra = formatv(" (for scc: {0})\n", C->getName());
80 } else if (any_isa(IR)) {
55 return None;
56 }
57
58 if (any_isa(IR)) {
8159 const Loop *L = any_cast(IR);
8260 const Function *F = L->getHeader()->getParent();
8361 if (!isFunctionInPrintList(F->getName()))
84 return;
85 if (!llvm::forcePrintModuleIR()) {
86 llvm::printLoop(const_cast(*L), dbgs(), Banner);
87 return;
62 return None;
63 const Module *M = F->getParent();
64 std::string LoopName;
65 raw_string_ostream ss(LoopName);
66 L->getHeader()->printAsOperand(ss, false);
67 return std::make_pair(M, formatv(" (loop: {0})", ss.str()).str());
68 }
69
70 llvm_unreachable("Unknown IR unit");
71 }
72
73 void printIR(const Module *M, StringRef Banner, StringRef Extra = StringRef()) {
74 dbgs() << Banner << Extra << "\n";
75 M->print(dbgs(), nullptr, false);
76 }
77 void printIR(const Function *F, StringRef Banner,
78 StringRef Extra = StringRef()) {
79 if (!llvm::isFunctionInPrintList(F->getName()))
80 return;
81 dbgs() << Banner << Extra << "\n" << static_cast(*F);
82 }
83 void printIR(const LazyCallGraph::SCC *C, StringRef Banner,
84 StringRef Extra = StringRef()) {
85 bool BannerPrinted = false;
86 for (const LazyCallGraph::Node &N : *C) {
87 const Function &F = N.getFunction();
88 if (!F.isDeclaration() && llvm::isFunctionInPrintList(F.getName())) {
89 if (!BannerPrinted) {
90 dbgs() << Banner << Extra << "\n";
91 BannerPrinted = true;
92 }
93 F.print(dbgs());
8894 }
89 M = F->getParent();
90 {
91 std::string LoopName;
92 raw_string_ostream ss(LoopName);
93 L->getHeader()->printAsOperand(ss, false);
94 Extra = formatv(" (loop: {0})\n", ss.str());
95 }
96 }
97 if (M) {
98 dbgs() << Banner << Extra;
99 M->print(dbgs(), nullptr, false);
100 } else {
101 llvm_unreachable("Unknown wrapped IR type");
102 }
103 }
104
105 bool printBeforePass(StringRef PassID, Any IR) {
95 }
96 }
97 void printIR(const Loop *L, StringRef Banner) {
98 const Function *F = L->getHeader()->getParent();
99 if (!llvm::isFunctionInPrintList(F->getName()))
100 return;
101 llvm::printLoop(const_cast(*L), dbgs(), Banner);
102 }
103
104 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into
105 /// llvm::Any and does actual print job.
106 void unwrapAndPrint(Any IR, StringRef Banner, bool ForceModule = false) {
107 if (ForceModule) {
108 if (auto UnwrappedModule = unwrapModule(IR))
109 printIR(UnwrappedModule->first, Banner, UnwrappedModule->second);
110 return;
111 }
112
113 if (any_isa(IR)) {
114 const Module *M = any_cast(IR);
115 assert(M && "module should be valid for printing");
116 printIR(M, Banner);
117 return;
118 }
119
120 if (any_isa(IR)) {
121 const Function *F = any_cast(IR);
122 assert(F && "function should be valid for printing");
123 printIR(F, Banner);
124 return;
125 }
126
127 if (any_isa(IR)) {
128 const LazyCallGraph::SCC *C = any_cast(IR);
129 assert(C && "scc should be valid for printing");
130 std::string Extra = formatv(" (scc: {0})", C->getName());
131 printIR(C, Banner, Extra);
132 return;
133 }
134
135 if (any_isa(IR)) {
136 const Loop *L = any_cast(IR);
137 assert(L && "Loop should be valid for printing");
138 printIR(L, Banner);
139 return;
140 }
141 llvm_unreachable("Unknown wrapped IR type");
142 }
143
144 } // namespace
145
146 PrintIRInstrumentation::~PrintIRInstrumentation() {
147 assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
148 }
149
150 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
151 assert(StoreModuleDesc);
152 const Module *M = nullptr;
153 std::string Extra;
154 if (auto UnwrappedModule = unwrapModule(IR))
155 std::tie(M, Extra) = UnwrappedModule.getValue();
156 ModuleDescStack.emplace_back(M, Extra, PassID);
157 }
158
159 PrintIRInstrumentation::PrintModuleDesc
160 PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
161 assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
162 PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
163 assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
164 return ModuleDesc;
165 }
166
167 bool PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
168 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
169 return true;
170
171 // Saving Module for AfterPassInvalidated operations.
172 // Note: here we rely on a fact that we do not change modules while
173 // traversing the pipeline, so the latest captured module is good
174 // for all print operations that has not happen yet.
175 if (StoreModuleDesc && llvm::shouldPrintAfterPass(PassID))
176 pushModuleDesc(PassID, IR);
177
106178 if (!llvm::shouldPrintBeforePass(PassID))
107179 return true;
108180
181 SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
182 unwrapAndPrint(IR, Banner, llvm::forcePrintModuleIR());
183 return true;
184 }
185
186 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
109187 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
110 return true;
111
112 SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID);
113 unwrapAndPrint(Banner, IR);
114 return true;
115 }
116
117 void printAfterPass(StringRef PassID, Any IR) {
188 return;
189
118190 if (!llvm::shouldPrintAfterPass(PassID))
119191 return;
120192
193 if (StoreModuleDesc)
194 popModuleDesc(PassID);
195
196 SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
197 unwrapAndPrint(IR, Banner, llvm::forcePrintModuleIR());
198 }
199
200 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
201 if (!StoreModuleDesc || !llvm::shouldPrintAfterPass(PassID))
202 return;
203
121204 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<"))
122205 return;
123206
124 SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
125 unwrapAndPrint(Banner, IR);
126 return;
127 }
128 } // namespace PrintIR
129 } // namespace
207 const Module *M;
208 std::string Extra;
209 StringRef StoredPassID;
210 std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID);
211 // Additional filtering (e.g. -filter-print-func) can lead to module
212 // printing being skipped.
213 if (!M)
214 return;
215
216 SmallString<20> Banner =
217 formatv("*** IR Dump After {0} *** invalidated: ", PassID);
218 printIR(M, Banner, Extra);
219 }
220
221 void PrintIRInstrumentation::registerCallbacks(
222 PassInstrumentationCallbacks &PIC) {
223 // BeforePass callback is not just for printing, it also saves a Module
224 // for later use in AfterPassInvalidated.
225 StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass();
226 if (llvm::shouldPrintBeforePass() || StoreModuleDesc)
227 PIC.registerBeforePassCallback(
228 [this](StringRef P, Any IR) { return this->printBeforePass(P, IR); });
229
230 if (llvm::shouldPrintAfterPass()) {
231 PIC.registerAfterPassCallback(
232 [this](StringRef P, Any IR) { this->printAfterPass(P, IR); });
233 PIC.registerAfterPassInvalidatedCallback(
234 [this](StringRef P) { this->printAfterPassInvalidated(P); });
235 }
236 }
130237
131238 void StandardInstrumentations::registerCallbacks(
132239 PassInstrumentationCallbacks &PIC) {
133 if (llvm::shouldPrintBeforePass())
134 PIC.registerBeforePassCallback(PrintIR::printBeforePass);
135 if (llvm::shouldPrintAfterPass())
136 PIC.registerAfterPassCallback(PrintIR::printAfterPass);
240 PrintIR.registerCallbacks(PIC);
137241 TimePasses.registerCallbacks(PIC);
138242 }
44 ; RUN: -passes=loop-instsimplify -print-after-all 2>&1 | FileCheck %s -check-prefix=SIMPLIFY
55 ; RUN: opt < %s -disable-output \
66 ; RUN: -passes=loop-deletion,loop-instsimplify -print-after-all 2>&1 | FileCheck %s -check-prefix=DELETED
7 ; RUN: opt < %s -disable-output \
8 ; RUN: -passes=loop-deletion,loop-instsimplify -print-after-all -print-module-scope 2>&1 | FileCheck %s -check-prefix=DELETED-BUT-PRINTED
79 ;
810 ; SIMPLIFY: IR Dump {{.*}} LoopInstSimplifyPass
911 ; DELETED-NOT: IR Dump {{.*}}LoopInstSimplifyPass
1012 ; DELETED-NOT: IR Dump {{.*}}LoopDeletionPass
13 ; DELETED-BUT-PRINTED: IR Dump {{.*}}LoopDeletionPass {{.*invalidated:}}
14 ; DELETED-BUT-PRINTED-NOT: IR Dump {{.*}}LoopInstSimplifyPass
1115
1216 define void @deleteme() {
1317 entry:
88 ; INL: IR Dump After {{InlinerPass .*scc: .tester}}
99
1010 ; INL-MOD: IR Dump Before {{InlinerPass .*scc: .tester, foo}}
11 ; INL-MOD-NOT: IR Dump After {{InlinerPass}}
11 ; INL-MOD: IR Dump After {{InlinerPass .*invalidated: .*scc: .tester, foo}}
1212 ; INL-MOD: IR Dump Before {{InlinerPass .*scc: .tester}}
1313 ; INL-MOD: IR Dump After {{InlinerPass .*scc: .tester}}
1414