Home | History | Annotate | Download | only in opt
      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