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 { 31 PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } 32 static StringRef name() { return "NoOpModulePass"; } 33 }; 34 35 /// \brief No-op CGSCC pass which does nothing. 36 struct NoOpCGSCCPass { 37 PreservedAnalyses run(LazyCallGraph::SCC *C) { 38 return PreservedAnalyses::all(); 39 } 40 static StringRef name() { return "NoOpCGSCCPass"; } 41 }; 42 43 /// \brief No-op function pass which does nothing. 44 struct NoOpFunctionPass { 45 PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); } 46 static StringRef name() { return "NoOpFunctionPass"; } 47 }; 48 49 } // End anonymous namespace. 50 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 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 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 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 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 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 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 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 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? 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