• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- Passes.cpp - Parsing, selection, and running of passes -------------===//
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 provides the infrastructure to parse and build a custom pass
12 /// manager based on a commandline flag. It also provides helpers to aid in
13 /// analyzing, debugging, and testing pass structures.
14 ///
15 //===----------------------------------------------------------------------===//
16 
17 #include "Passes.h"
18 #include "llvm/Analysis/CGSCCPassManager.h"
19 #include "llvm/Analysis/LazyCallGraph.h"
20 #include "llvm/IR/IRPrintingPasses.h"
21 #include "llvm/IR/PassManager.h"
22 #include "llvm/IR/Verifier.h"
23 #include "llvm/Support/Debug.h"
24 
25 using namespace llvm;
26 
27 namespace {
28 
29 /// \brief No-op module pass which does nothing.
30 struct NoOpModulePass {
run__anon9b8659210111::NoOpModulePass31   PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); }
name__anon9b8659210111::NoOpModulePass32   static StringRef name() { return "NoOpModulePass"; }
33 };
34 
35 /// \brief No-op CGSCC pass which does nothing.
36 struct NoOpCGSCCPass {
run__anon9b8659210111::NoOpCGSCCPass37   PreservedAnalyses run(LazyCallGraph::SCC *C) {
38     return PreservedAnalyses::all();
39   }
name__anon9b8659210111::NoOpCGSCCPass40   static StringRef name() { return "NoOpCGSCCPass"; }
41 };
42 
43 /// \brief No-op function pass which does nothing.
44 struct NoOpFunctionPass {
run__anon9b8659210111::NoOpFunctionPass45   PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); }
name__anon9b8659210111::NoOpFunctionPass46   static StringRef name() { return "NoOpFunctionPass"; }
47 };
48 
49 } // End anonymous namespace.
50 
isModulePassName(StringRef Name)51 static bool isModulePassName(StringRef Name) {
52   if (Name == "no-op-module") return true;
53 
54 #define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
55 #include "PassRegistry.def"
56 
57   return false;
58 }
59 
isCGSCCPassName(StringRef Name)60 static bool isCGSCCPassName(StringRef Name) {
61   if (Name == "no-op-cgscc") return true;
62 
63 #define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
64 #include "PassRegistry.def"
65 
66   return false;
67 }
68 
isFunctionPassName(StringRef Name)69 static bool isFunctionPassName(StringRef Name) {
70   if (Name == "no-op-function") return true;
71 
72 #define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
73 #include "PassRegistry.def"
74 
75   return false;
76 }
77 
parseModulePassName(ModulePassManager & MPM,StringRef Name)78 static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) {
79   if (Name == "no-op-module") {
80     MPM.addPass(NoOpModulePass());
81     return true;
82   }
83 
84 #define MODULE_PASS(NAME, CREATE_PASS)                                         \
85   if (Name == NAME) {                                                          \
86     MPM.addPass(CREATE_PASS);                                                  \
87     return true;                                                               \
88   }
89 #include "PassRegistry.def"
90 
91   return false;
92 }
93 
parseCGSCCPassName(CGSCCPassManager & CGPM,StringRef Name)94 static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) {
95   if (Name == "no-op-cgscc") {
96     CGPM.addPass(NoOpCGSCCPass());
97     return true;
98   }
99 
100 #define CGSCC_PASS(NAME, CREATE_PASS)                                          \
101   if (Name == NAME) {                                                          \
102     CGPM.addPass(CREATE_PASS);                                                 \
103     return true;                                                               \
104   }
105 #include "PassRegistry.def"
106 
107   return false;
108 }
109 
parseFunctionPassName(FunctionPassManager & FPM,StringRef Name)110 static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) {
111   if (Name == "no-op-function") {
112     FPM.addPass(NoOpFunctionPass());
113     return true;
114   }
115 
116 #define FUNCTION_PASS(NAME, CREATE_PASS)                                       \
117   if (Name == NAME) {                                                          \
118     FPM.addPass(CREATE_PASS);                                                  \
119     return true;                                                               \
120   }
121 #include "PassRegistry.def"
122 
123   return false;
124 }
125 
parseFunctionPassPipeline(FunctionPassManager & FPM,StringRef & PipelineText,bool VerifyEachPass)126 static bool parseFunctionPassPipeline(FunctionPassManager &FPM,
127                                       StringRef &PipelineText,
128                                       bool VerifyEachPass) {
129   for (;;) {
130     // Parse nested pass managers by recursing.
131     if (PipelineText.startswith("function(")) {
132       FunctionPassManager NestedFPM;
133 
134       // Parse the inner pipeline inte the nested manager.
135       PipelineText = PipelineText.substr(strlen("function("));
136       if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
137           PipelineText.empty())
138         return false;
139       assert(PipelineText[0] == ')');
140       PipelineText = PipelineText.substr(1);
141 
142       // Add the nested pass manager with the appropriate adaptor.
143       FPM.addPass(std::move(NestedFPM));
144     } else {
145       // Otherwise try to parse a pass name.
146       size_t End = PipelineText.find_first_of(",)");
147       if (!parseFunctionPassName(FPM, PipelineText.substr(0, End)))
148         return false;
149       if (VerifyEachPass)
150         FPM.addPass(VerifierPass());
151 
152       PipelineText = PipelineText.substr(End);
153     }
154 
155     if (PipelineText.empty() || PipelineText[0] == ')')
156       return true;
157 
158     assert(PipelineText[0] == ',');
159     PipelineText = PipelineText.substr(1);
160   }
161 }
162 
parseCGSCCPassPipeline(CGSCCPassManager & CGPM,StringRef & PipelineText,bool VerifyEachPass)163 static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM,
164                                       StringRef &PipelineText,
165                                       bool VerifyEachPass) {
166   for (;;) {
167     // Parse nested pass managers by recursing.
168     if (PipelineText.startswith("cgscc(")) {
169       CGSCCPassManager NestedCGPM;
170 
171       // Parse the inner pipeline into the nested manager.
172       PipelineText = PipelineText.substr(strlen("cgscc("));
173       if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) ||
174           PipelineText.empty())
175         return false;
176       assert(PipelineText[0] == ')');
177       PipelineText = PipelineText.substr(1);
178 
179       // Add the nested pass manager with the appropriate adaptor.
180       CGPM.addPass(std::move(NestedCGPM));
181     } else if (PipelineText.startswith("function(")) {
182       FunctionPassManager NestedFPM;
183 
184       // Parse the inner pipeline inte the nested manager.
185       PipelineText = PipelineText.substr(strlen("function("));
186       if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
187           PipelineText.empty())
188         return false;
189       assert(PipelineText[0] == ')');
190       PipelineText = PipelineText.substr(1);
191 
192       // Add the nested pass manager with the appropriate adaptor.
193       CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
194     } else {
195       // Otherwise try to parse a pass name.
196       size_t End = PipelineText.find_first_of(",)");
197       if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End)))
198         return false;
199       // FIXME: No verifier support for CGSCC passes!
200 
201       PipelineText = PipelineText.substr(End);
202     }
203 
204     if (PipelineText.empty() || PipelineText[0] == ')')
205       return true;
206 
207     assert(PipelineText[0] == ',');
208     PipelineText = PipelineText.substr(1);
209   }
210 }
211 
parseModulePassPipeline(ModulePassManager & MPM,StringRef & PipelineText,bool VerifyEachPass)212 static bool parseModulePassPipeline(ModulePassManager &MPM,
213                                     StringRef &PipelineText,
214                                     bool VerifyEachPass) {
215   for (;;) {
216     // Parse nested pass managers by recursing.
217     if (PipelineText.startswith("module(")) {
218       ModulePassManager NestedMPM;
219 
220       // Parse the inner pipeline into the nested manager.
221       PipelineText = PipelineText.substr(strlen("module("));
222       if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) ||
223           PipelineText.empty())
224         return false;
225       assert(PipelineText[0] == ')');
226       PipelineText = PipelineText.substr(1);
227 
228       // Now add the nested manager as a module pass.
229       MPM.addPass(std::move(NestedMPM));
230     } else if (PipelineText.startswith("cgscc(")) {
231       CGSCCPassManager NestedCGPM;
232 
233       // Parse the inner pipeline inte the nested manager.
234       PipelineText = PipelineText.substr(strlen("cgscc("));
235       if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) ||
236           PipelineText.empty())
237         return false;
238       assert(PipelineText[0] == ')');
239       PipelineText = PipelineText.substr(1);
240 
241       // Add the nested pass manager with the appropriate adaptor.
242       MPM.addPass(
243           createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
244     } else if (PipelineText.startswith("function(")) {
245       FunctionPassManager NestedFPM;
246 
247       // Parse the inner pipeline inte the nested manager.
248       PipelineText = PipelineText.substr(strlen("function("));
249       if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) ||
250           PipelineText.empty())
251         return false;
252       assert(PipelineText[0] == ')');
253       PipelineText = PipelineText.substr(1);
254 
255       // Add the nested pass manager with the appropriate adaptor.
256       MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM)));
257     } else {
258       // Otherwise try to parse a pass name.
259       size_t End = PipelineText.find_first_of(",)");
260       if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
261         return false;
262       if (VerifyEachPass)
263         MPM.addPass(VerifierPass());
264 
265       PipelineText = PipelineText.substr(End);
266     }
267 
268     if (PipelineText.empty() || PipelineText[0] == ')')
269       return true;
270 
271     assert(PipelineText[0] == ',');
272     PipelineText = PipelineText.substr(1);
273   }
274 }
275 
276 // Primary pass pipeline description parsing routine.
277 // FIXME: Should this routine accept a TargetMachine or require the caller to
278 // pre-populate the analysis managers with target-specific stuff?
parsePassPipeline(ModulePassManager & MPM,StringRef PipelineText,bool VerifyEachPass)279 bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText,
280                              bool VerifyEachPass) {
281   // Look at the first entry to figure out which layer to start parsing at.
282   if (PipelineText.startswith("module("))
283     return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
284            PipelineText.empty();
285   if (PipelineText.startswith("cgscc(")) {
286     CGSCCPassManager CGPM;
287     if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) ||
288         !PipelineText.empty())
289       return false;
290     MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
291     return true;
292   }
293   if (PipelineText.startswith("function(")) {
294     FunctionPassManager FPM;
295     if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
296         !PipelineText.empty())
297       return false;
298     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
299     return true;
300   }
301 
302   // This isn't a direct pass manager name, look for the end of a pass name.
303   StringRef FirstName =
304       PipelineText.substr(0, PipelineText.find_first_of(",)"));
305   if (isModulePassName(FirstName))
306     return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) &&
307            PipelineText.empty();
308 
309   if (isCGSCCPassName(FirstName)) {
310     CGSCCPassManager CGPM;
311     if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) ||
312         !PipelineText.empty())
313       return false;
314     MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
315     return true;
316   }
317 
318   if (isFunctionPassName(FirstName)) {
319     FunctionPassManager FPM;
320     if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) ||
321         !PipelineText.empty())
322       return false;
323     MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
324     return true;
325   }
326 
327   return false;
328 }
329