Index: llvm/trunk/include/llvm/Passes/PassBuilder.h =================================================================== --- llvm/trunk/include/llvm/Passes/PassBuilder.h +++ llvm/trunk/include/llvm/Passes/PassBuilder.h @@ -0,0 +1,105 @@ +//===- Parsing, selection, and construction of pass pipelines --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Interfaces for registering analysis passes, producing common pass manager +/// configurations, and parsing of pass pipelines. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_PASSBUILDER_H +#define LLVM_PASSES_PASSBUILDER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { +class TargetMachine; + +/// \brief This class provides access to building LLVM's passes. +/// +/// It's members provide the baseline state available to passes during their +/// construction. The \c PassRegistry.def file specifies how to construct all +/// of the built-in passes, and those may reference these members during +/// construction. +class PassBuilder { + TargetMachine *TM; + +public: + explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {} + + /// \brief Registers all available module analysis passes. + /// + /// This is an interface that can be used to populate a \c + /// ModuleAnalysisManager with all registered module analyses. Callers can + /// still manually register any additional analyses. + void registerModuleAnalyses(ModuleAnalysisManager &MAM); + + /// \brief Registers all available CGSCC analysis passes. + /// + /// This is an interface that can be used to populate a \c CGSCCAnalysisManager + /// with all registered CGSCC analyses. Callers can still manually register any + /// additional analyses. + void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); + + /// \brief Registers all available function analysis passes. + /// + /// This is an interface that can be used to populate a \c + /// FunctionAnalysisManager with all registered function analyses. Callers can + /// still manually register any additional analyses. + void registerFunctionAnalyses(FunctionAnalysisManager &FAM); + + /// \brief Parse a textual pass pipeline description into a \c ModulePassManager. + /// + /// The format of the textual pass pipeline description looks something like: + /// + /// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...) + /// + /// Pass managers have ()s describing the nest structure of passes. All passes + /// are comma separated. As a special shortcut, if the very first pass is not + /// a module pass (as a module pass manager is), this will automatically form + /// the shortest stack of pass managers that allow inserting that first pass. + /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes + /// 'lpassN', all of these are valid: + /// + /// fpass1,fpass2,fpass3 + /// cgpass1,cgpass2,cgpass3 + /// lpass1,lpass2,lpass3 + /// + /// And they are equivalent to the following (resp.): + /// + /// module(function(fpass1,fpass2,fpass3)) + /// module(cgscc(cgpass1,cgpass2,cgpass3)) + /// module(function(loop(lpass1,lpass2,lpass3))) + /// + /// This shortcut is especially useful for debugging and testing small pass + /// combinations. Note that these shortcuts don't introduce any other magic. If + /// the sequence of passes aren't all the exact same kind of pass, it will be + /// an error. You cannot mix different levels implicitly, you must explicitly + /// form a pass manager in which to nest passes. + bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, + bool VerifyEachPass = true, bool DebugLogging = false); + +private: + bool parseModulePassName(ModulePassManager &MPM, StringRef Name); + bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name); + bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name); + bool parseFunctionPassPipeline(FunctionPassManager &FPM, + StringRef &PipelineText, bool VerifyEachPass, + bool DebugLogging); + bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, StringRef &PipelineText, + bool VerifyEachPass, bool DebugLogging); + bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText, + bool VerifyEachPass, bool DebugLogging); +}; + +} + +#endif Index: llvm/trunk/lib/CMakeLists.txt =================================================================== --- llvm/trunk/lib/CMakeLists.txt +++ llvm/trunk/lib/CMakeLists.txt @@ -18,3 +18,4 @@ add_subdirectory(LineEditor) add_subdirectory(ProfileData) add_subdirectory(Fuzzer) +add_subdirectory(Passes) Index: llvm/trunk/lib/LLVMBuild.txt =================================================================== --- llvm/trunk/lib/LLVMBuild.txt +++ llvm/trunk/lib/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option ProfileData Support TableGen Target Transforms +subdirectories = Analysis AsmParser Bitcode CodeGen DebugInfo ExecutionEngine LineEditor Linker IR IRReader LTO MC Object Option Passes ProfileData Support TableGen Target Transforms [component_0] type = Group Index: llvm/trunk/lib/Makefile =================================================================== --- llvm/trunk/lib/Makefile +++ llvm/trunk/lib/Makefile @@ -12,6 +12,6 @@ PARALLEL_DIRS := IR AsmParser Bitcode Analysis Transforms CodeGen Target \ ExecutionEngine Linker LTO MC Object Option DebugInfo \ - IRReader LineEditor ProfileData + IRReader LineEditor ProfileData Passes include $(LEVEL)/Makefile.common Index: llvm/trunk/lib/Passes/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Passes/CMakeLists.txt +++ llvm/trunk/lib/Passes/CMakeLists.txt @@ -0,0 +1,6 @@ +add_llvm_library(LLVMPasses + PassBuilder.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Passes + ) Index: llvm/trunk/lib/Passes/LLVMBuild.txt =================================================================== --- llvm/trunk/lib/Passes/LLVMBuild.txt +++ llvm/trunk/lib/Passes/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./lib/Passes/LLVMBuild.txt -------------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = Passes +parent = Libraries +required_libraries = Analysis Core IPA IPO InstCombine Scalar Support TransformUtils Vectorize Index: llvm/trunk/lib/Passes/Makefile =================================================================== --- llvm/trunk/lib/Passes/Makefile +++ llvm/trunk/lib/Passes/Makefile @@ -0,0 +1,14 @@ +##===- lib/Passes/Makefile ---------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +LIBRARYNAME = LLVMPasses +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common Index: llvm/trunk/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/trunk/lib/Passes/PassBuilder.cpp +++ llvm/trunk/lib/Passes/PassBuilder.cpp @@ -0,0 +1,412 @@ +//===- Parsing, selection, and construction of pass pipelines -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides the implementation of the PassBuilder based on our +/// static pass registry as well as related functionality. It also provides +/// helpers to aid in analyzing, debugging, and testing passes and pass +/// pipelines. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Scalar/EarlyCSE.h" +#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" +#include "llvm/Transforms/Scalar/SimplifyCFG.h" + +using namespace llvm; + +namespace { + +/// \brief No-op module pass which does nothing. +struct NoOpModulePass { + PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } + static StringRef name() { return "NoOpModulePass"; } +}; + +/// \brief No-op module analysis. +struct NoOpModuleAnalysis { + struct Result {}; + Result run(Module &) { return Result(); } + static StringRef name() { return "NoOpModuleAnalysis"; } + static void *ID() { return (void *)&PassID; } +private: + static char PassID; +}; + +char NoOpModuleAnalysis::PassID; + +/// \brief No-op CGSCC pass which does nothing. +struct NoOpCGSCCPass { + PreservedAnalyses run(LazyCallGraph::SCC &C) { + return PreservedAnalyses::all(); + } + static StringRef name() { return "NoOpCGSCCPass"; } +}; + +/// \brief No-op CGSCC analysis. +struct NoOpCGSCCAnalysis { + struct Result {}; + Result run(LazyCallGraph::SCC &) { return Result(); } + static StringRef name() { return "NoOpCGSCCAnalysis"; } + static void *ID() { return (void *)&PassID; } +private: + static char PassID; +}; + +char NoOpCGSCCAnalysis::PassID; + +/// \brief No-op function pass which does nothing. +struct NoOpFunctionPass { + PreservedAnalyses run(Function &F) { return PreservedAnalyses::all(); } + static StringRef name() { return "NoOpFunctionPass"; } +}; + +/// \brief No-op function analysis. +struct NoOpFunctionAnalysis { + struct Result {}; + Result run(Function &) { return Result(); } + static StringRef name() { return "NoOpFunctionAnalysis"; } + static void *ID() { return (void *)&PassID; } +private: + static char PassID; +}; + +char NoOpFunctionAnalysis::PassID; + +} // End anonymous namespace. + +void PassBuilder::registerModuleAnalyses(ModuleAnalysisManager &MAM) { +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + MAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" +} + +void PassBuilder::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) { +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + CGAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" +} + +void PassBuilder::registerFunctionAnalyses(FunctionAnalysisManager &FAM) { +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + FAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" +} + +#ifndef NDEBUG +static bool isModulePassName(StringRef Name) { +#define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ + return true; +#include "PassRegistry.def" + + return false; +} +#endif + +static bool isCGSCCPassName(StringRef Name) { +#define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ + return true; +#include "PassRegistry.def" + + return false; +} + +static bool isFunctionPassName(StringRef Name) { +#define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ + return true; +#include "PassRegistry.def" + + return false; +} + +bool PassBuilder::parseModulePassName(ModulePassManager &MPM, StringRef Name) { +#define MODULE_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(CREATE_PASS); \ + return true; \ + } +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">") { \ + MPM.addPass(RequireAnalysisPass()); \ + return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + MPM.addPass(InvalidateAnalysisPass()); \ + return true; \ + } +#include "PassRegistry.def" + + return false; +} + +bool PassBuilder::parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) { +#define CGSCC_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(CREATE_PASS); \ + return true; \ + } +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">") { \ + CGPM.addPass(RequireAnalysisPass()); \ + return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + CGPM.addPass(InvalidateAnalysisPass()); \ + return true; \ + } +#include "PassRegistry.def" + + return false; +} + +bool PassBuilder::parseFunctionPassName(FunctionPassManager &FPM, + StringRef Name) { +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + FPM.addPass(CREATE_PASS); \ + return true; \ + } +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">") { \ + FPM.addPass(RequireAnalysisPass()); \ + return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + FPM.addPass(InvalidateAnalysisPass()); \ + return true; \ + } +#include "PassRegistry.def" + + return false; +} + +bool PassBuilder::parseFunctionPassPipeline(FunctionPassManager &FPM, + StringRef &PipelineText, + bool VerifyEachPass, + bool DebugLogging) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM(DebugLogging); + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + FPM.addPass(std::move(NestedFPM)); + } else { + // Otherwise try to parse a pass name. + size_t End = PipelineText.find_first_of(",)"); + if (!parseFunctionPassName(FPM, PipelineText.substr(0, End))) + return false; + if (VerifyEachPass) + FPM.addPass(VerifierPass()); + + PipelineText = PipelineText.substr(End); + } + + if (PipelineText.empty() || PipelineText[0] == ')') + return true; + + assert(PipelineText[0] == ','); + PipelineText = PipelineText.substr(1); + } +} + +bool PassBuilder::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, + StringRef &PipelineText, + bool VerifyEachPass, + bool DebugLogging) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("cgscc(")) { + CGSCCPassManager NestedCGPM(DebugLogging); + + // Parse the inner pipeline into the nested manager. + PipelineText = PipelineText.substr(strlen("cgscc(")); + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, + DebugLogging) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + CGPM.addPass(std::move(NestedCGPM)); + } else if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM(DebugLogging); + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM))); + } else { + // Otherwise try to parse a pass name. + size_t End = PipelineText.find_first_of(",)"); + if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End))) + return false; + // FIXME: No verifier support for CGSCC passes! + + PipelineText = PipelineText.substr(End); + } + + if (PipelineText.empty() || PipelineText[0] == ')') + return true; + + assert(PipelineText[0] == ','); + PipelineText = PipelineText.substr(1); + } +} + +bool PassBuilder::parseModulePassPipeline(ModulePassManager &MPM, + StringRef &PipelineText, + bool VerifyEachPass, + bool DebugLogging) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("module(")) { + ModulePassManager NestedMPM(DebugLogging); + + // Parse the inner pipeline into the nested manager. + PipelineText = PipelineText.substr(strlen("module(")); + if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass, + DebugLogging) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Now add the nested manager as a module pass. + MPM.addPass(std::move(NestedMPM)); + } else if (PipelineText.startswith("cgscc(")) { + CGSCCPassManager NestedCGPM(DebugLogging); + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("cgscc(")); + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, + DebugLogging) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + MPM.addPass( + createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM))); + } else if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM(DebugLogging); + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || + PipelineText.empty()) + return false; + assert(PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM))); + } else { + // Otherwise try to parse a pass name. + size_t End = PipelineText.find_first_of(",)"); + if (!parseModulePassName(MPM, PipelineText.substr(0, End))) + return false; + if (VerifyEachPass) + MPM.addPass(VerifierPass()); + + PipelineText = PipelineText.substr(End); + } + + if (PipelineText.empty() || PipelineText[0] == ')') + return true; + + assert(PipelineText[0] == ','); + PipelineText = PipelineText.substr(1); + } +} + +// Primary pass pipeline description parsing routine. +// FIXME: Should this routine accept a TargetMachine or require the caller to +// pre-populate the analysis managers with target-specific stuff? +bool PassBuilder::parsePassPipeline(ModulePassManager &MPM, + StringRef PipelineText, bool VerifyEachPass, + bool DebugLogging) { + // By default, try to parse the pipeline as-if it were within an implicit + // 'module(...)' pass pipeline. If this will parse at all, it needs to + // consume the entire string. + if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging)) + return PipelineText.empty(); + + // This isn't parsable as a module pipeline, look for the end of a pass name + // and directly drop down to that layer. + StringRef FirstName = + PipelineText.substr(0, PipelineText.find_first_of(",)")); + assert(!isModulePassName(FirstName) && + "Already handled all module pipeline options."); + + // If this looks like a CGSCC pass, parse the whole thing as a CGSCC + // pipeline. + if (isCGSCCPassName(FirstName)) { + CGSCCPassManager CGPM(DebugLogging); + if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass, + DebugLogging) || + !PipelineText.empty()) + return false; + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); + return true; + } + + // Similarly, if this looks like a Function pass, parse the whole thing as + // a Function pipelien. + if (isFunctionPassName(FirstName)) { + FunctionPassManager FPM(DebugLogging); + if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass, + DebugLogging) || + !PipelineText.empty()) + return false; + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + return true; + } + + return false; +} Index: llvm/trunk/lib/Passes/PassRegistry.def =================================================================== --- llvm/trunk/lib/Passes/PassRegistry.def +++ llvm/trunk/lib/Passes/PassRegistry.def @@ -0,0 +1,77 @@ +//===- PassRegistry.def - Registry of passes --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is used as the registry of passes that are part of the core LLVM +// libraries. This file describes both transformation passes and analyses +// Analyses are registered while transformation passes have names registered +// that can be used when providing a textual pass pipeline. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +#ifndef MODULE_ANALYSIS +#define MODULE_ANALYSIS(NAME, CREATE_PASS) +#endif +MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis()) +MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis()) +MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) +#undef MODULE_ANALYSIS + +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, CREATE_PASS) +#endif +MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) +MODULE_PASS("no-op-module", NoOpModulePass()) +MODULE_PASS("print", PrintModulePass(dbgs())) +MODULE_PASS("print-cg", LazyCallGraphPrinterPass(dbgs())) +MODULE_PASS("verify", VerifierPass()) +#undef MODULE_PASS + +#ifndef CGSCC_ANALYSIS +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) +#endif +CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) +#undef CGSCC_ANALYSIS + +#ifndef CGSCC_PASS +#define CGSCC_PASS(NAME, CREATE_PASS) +#endif +CGSCC_PASS("invalidate", InvalidateAllAnalysesPass()) +CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass()) +#undef CGSCC_PASS + +#ifndef FUNCTION_ANALYSIS +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) +#endif +FUNCTION_ANALYSIS("assumptions", AssumptionAnalysis()) +FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis()) +FUNCTION_ANALYSIS("loops", LoopAnalysis()) +FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) +FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) +FUNCTION_ANALYSIS("targetir", + TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()) +#undef FUNCTION_ANALYSIS + +#ifndef FUNCTION_PASS +#define FUNCTION_PASS(NAME, CREATE_PASS) +#endif +FUNCTION_PASS("early-cse", EarlyCSEPass()) +FUNCTION_PASS("instcombine", InstCombinePass()) +FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) +FUNCTION_PASS("no-op-function", NoOpFunctionPass()) +FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass()) +FUNCTION_PASS("print", PrintFunctionPass(dbgs())) +FUNCTION_PASS("print", AssumptionPrinterPass(dbgs())) +FUNCTION_PASS("print", DominatorTreePrinterPass(dbgs())) +FUNCTION_PASS("print", LoopPrinterPass(dbgs())) +FUNCTION_PASS("simplify-cfg", SimplifyCFGPass()) +FUNCTION_PASS("verify", VerifierPass()) +FUNCTION_PASS("verify", DominatorTreeVerifierPass()) +#undef FUNCTION_PASS Index: llvm/trunk/tools/opt/CMakeLists.txt =================================================================== --- llvm/trunk/tools/opt/CMakeLists.txt +++ llvm/trunk/tools/opt/CMakeLists.txt @@ -16,6 +16,7 @@ Target TransformUtils Vectorize + Passes ) # Support plugins. @@ -26,7 +27,6 @@ BreakpointPrinter.cpp GraphPrinters.cpp NewPMDriver.cpp - Passes.cpp PassPrinters.cpp PrintSCC.cpp opt.cpp Index: llvm/trunk/tools/opt/LLVMBuild.txt =================================================================== --- llvm/trunk/tools/opt/LLVMBuild.txt +++ llvm/trunk/tools/opt/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = opt parent = Tools -required_libraries = AsmParser BitReader BitWriter CodeGen IRReader IPO Instrumentation Scalar ObjCARC all-targets +required_libraries = AsmParser BitReader BitWriter CodeGen IRReader IPO Instrumentation Scalar ObjCARC Passes all-targets Index: llvm/trunk/tools/opt/Makefile =================================================================== --- llvm/trunk/tools/opt/Makefile +++ llvm/trunk/tools/opt/Makefile @@ -9,7 +9,7 @@ LEVEL := ../.. TOOLNAME := opt -LINK_COMPONENTS := bitreader bitwriter asmparser irreader instrumentation scalaropts objcarcopts ipo vectorize all-targets codegen +LINK_COMPONENTS := bitreader bitwriter asmparser irreader instrumentation scalaropts objcarcopts ipo vectorize all-targets codegen passes # Support plugins. NO_DEAD_STRIP := 1 Index: llvm/trunk/tools/opt/NewPMDriver.cpp =================================================================== --- llvm/trunk/tools/opt/NewPMDriver.cpp +++ llvm/trunk/tools/opt/NewPMDriver.cpp @@ -14,7 +14,6 @@ //===----------------------------------------------------------------------===// #include "NewPMDriver.h" -#include "Passes.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Bitcode/BitcodeWriterPass.h" @@ -24,6 +23,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" +#include "llvm/Passes/PassBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ToolOutputFile.h" @@ -40,16 +40,16 @@ TargetMachine *TM, tool_output_file *Out, StringRef PassPipeline, OutputKind OK, VerifierKind VK) { - Passes P(TM); + PassBuilder PB(TM); FunctionAnalysisManager FAM(DebugPM); CGSCCAnalysisManager CGAM(DebugPM); ModuleAnalysisManager MAM(DebugPM); // Register all the basic analyses with the managers. - P.registerModuleAnalyses(MAM); - P.registerCGSCCAnalyses(CGAM); - P.registerFunctionAnalyses(FAM); + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); // Cross register the analysis managers through their proxies. MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); @@ -63,8 +63,8 @@ if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); - if (!P.parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass, - DebugPM)) { + if (!PB.parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass, + DebugPM)) { errs() << Arg0 << ": unable to parse pass pipeline description.\n"; return false; } Index: llvm/trunk/tools/opt/PassRegistry.def =================================================================== --- llvm/trunk/tools/opt/PassRegistry.def +++ llvm/trunk/tools/opt/PassRegistry.def @@ -1,77 +0,0 @@ -//===- PassRegistry.def - Registry of passes --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is used as the registry of passes that are part of the core LLVM -// libraries. This file describes both transformation passes and analyses -// Analyses are registered while transformation passes have names registered -// that can be used when providing a textual pass pipeline. -// -//===----------------------------------------------------------------------===// - -// NOTE: NO INCLUDE GUARD DESIRED! - -#ifndef MODULE_ANALYSIS -#define MODULE_ANALYSIS(NAME, CREATE_PASS) -#endif -MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis()) -MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis()) -MODULE_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) -#undef MODULE_ANALYSIS - -#ifndef MODULE_PASS -#define MODULE_PASS(NAME, CREATE_PASS) -#endif -MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) -MODULE_PASS("no-op-module", NoOpModulePass()) -MODULE_PASS("print", PrintModulePass(dbgs())) -MODULE_PASS("print-cg", LazyCallGraphPrinterPass(dbgs())) -MODULE_PASS("verify", VerifierPass()) -#undef MODULE_PASS - -#ifndef CGSCC_ANALYSIS -#define CGSCC_ANALYSIS(NAME, CREATE_PASS) -#endif -CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) -#undef CGSCC_ANALYSIS - -#ifndef CGSCC_PASS -#define CGSCC_PASS(NAME, CREATE_PASS) -#endif -CGSCC_PASS("invalidate", InvalidateAllAnalysesPass()) -CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass()) -#undef CGSCC_PASS - -#ifndef FUNCTION_ANALYSIS -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) -#endif -FUNCTION_ANALYSIS("assumptions", AssumptionAnalysis()) -FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis()) -FUNCTION_ANALYSIS("loops", LoopAnalysis()) -FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) -FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) -FUNCTION_ANALYSIS("targetir", - TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()) -#undef FUNCTION_ANALYSIS - -#ifndef FUNCTION_PASS -#define FUNCTION_PASS(NAME, CREATE_PASS) -#endif -FUNCTION_PASS("early-cse", EarlyCSEPass()) -FUNCTION_PASS("instcombine", InstCombinePass()) -FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) -FUNCTION_PASS("no-op-function", NoOpFunctionPass()) -FUNCTION_PASS("lower-expect", LowerExpectIntrinsicPass()) -FUNCTION_PASS("print", PrintFunctionPass(dbgs())) -FUNCTION_PASS("print", AssumptionPrinterPass(dbgs())) -FUNCTION_PASS("print", DominatorTreePrinterPass(dbgs())) -FUNCTION_PASS("print", LoopPrinterPass(dbgs())) -FUNCTION_PASS("simplify-cfg", SimplifyCFGPass()) -FUNCTION_PASS("verify", VerifierPass()) -FUNCTION_PASS("verify", DominatorTreeVerifierPass()) -#undef FUNCTION_PASS Index: llvm/trunk/tools/opt/Passes.h =================================================================== --- llvm/trunk/tools/opt/Passes.h +++ llvm/trunk/tools/opt/Passes.h @@ -1,105 +0,0 @@ -//===- Passes.h - Utilities for manipulating all passes ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// Interfaces for registering passes, producing common pass manager -/// configurations, and parsing of pass pipelines. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_OPT_PASSES_H -#define LLVM_TOOLS_OPT_PASSES_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/CGSCCPassManager.h" -#include "llvm/IR/PassManager.h" - -namespace llvm { -class TargetMachine; - -/// \brief This class provides access to all of LLVM's passes. -/// -/// It's members provide the baseline state available to passes during their -/// construction. The \c PassRegistry.def file specifies how to construct all -/// of the built-in passes, and those may reference these members during -/// construction. -class Passes { - TargetMachine *TM; - -public: - explicit Passes(TargetMachine *TM = nullptr) : TM(TM) {} - - /// \brief Registers all available module analysis passes. - /// - /// This is an interface that can be used to populate a \c - /// ModuleAnalysisManager with all registered module analyses. Callers can - /// still manually register any additional analyses. - void registerModuleAnalyses(ModuleAnalysisManager &MAM); - - /// \brief Registers all available CGSCC analysis passes. - /// - /// This is an interface that can be used to populate a \c CGSCCAnalysisManager - /// with all registered CGSCC analyses. Callers can still manually register any - /// additional analyses. - void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); - - /// \brief Registers all available function analysis passes. - /// - /// This is an interface that can be used to populate a \c - /// FunctionAnalysisManager with all registered function analyses. Callers can - /// still manually register any additional analyses. - void registerFunctionAnalyses(FunctionAnalysisManager &FAM); - - /// \brief Parse a textual pass pipeline description into a \c ModulePassManager. - /// - /// The format of the textual pass pipeline description looks something like: - /// - /// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...) - /// - /// Pass managers have ()s describing the nest structure of passes. All passes - /// are comma separated. As a special shortcut, if the very first pass is not - /// a module pass (as a module pass manager is), this will automatically form - /// the shortest stack of pass managers that allow inserting that first pass. - /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes - /// 'lpassN', all of these are valid: - /// - /// fpass1,fpass2,fpass3 - /// cgpass1,cgpass2,cgpass3 - /// lpass1,lpass2,lpass3 - /// - /// And they are equivalent to the following (resp.): - /// - /// module(function(fpass1,fpass2,fpass3)) - /// module(cgscc(cgpass1,cgpass2,cgpass3)) - /// module(function(loop(lpass1,lpass2,lpass3))) - /// - /// This shortcut is especially useful for debugging and testing small pass - /// combinations. Note that these shortcuts don't introduce any other magic. If - /// the sequence of passes aren't all the exact same kind of pass, it will be - /// an error. You cannot mix different levels implicitly, you must explicitly - /// form a pass manager in which to nest passes. - bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass = true, bool DebugLogging = false); - -private: - bool parseModulePassName(ModulePassManager &MPM, StringRef Name); - bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name); - bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name); - bool parseFunctionPassPipeline(FunctionPassManager &FPM, - StringRef &PipelineText, bool VerifyEachPass, - bool DebugLogging); - bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, StringRef &PipelineText, - bool VerifyEachPass, bool DebugLogging); - bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText, - bool VerifyEachPass, bool DebugLogging); -}; - -} - -#endif Index: llvm/trunk/tools/opt/Passes.cpp =================================================================== --- llvm/trunk/tools/opt/Passes.cpp +++ llvm/trunk/tools/opt/Passes.cpp @@ -1,406 +0,0 @@ -//===- Passes.cpp - Parsing, selection, and running of passes -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// \file -/// -/// This file provides the infrastructure to parse and build a custom pass -/// manager based on a commandline flag. It also provides helpers to aid in -/// analyzing, debugging, and testing pass structures. -/// -//===----------------------------------------------------------------------===// - -#include "Passes.h" -#include "llvm/Analysis/AssumptionCache.h" -#include "llvm/Analysis/CGSCCPassManager.h" -#include "llvm/Analysis/LazyCallGraph.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/IRPrintingPasses.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/Verifier.h" -#include "llvm/Support/Debug.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/InstCombine/InstCombine.h" -#include "llvm/Transforms/Scalar/EarlyCSE.h" -#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" -#include "llvm/Transforms/Scalar/SimplifyCFG.h" - -using namespace llvm; - -namespace { - -/// \brief No-op module pass which does nothing. -struct NoOpModulePass { - PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } - static StringRef name() { return "NoOpModulePass"; } -}; - -/// \brief No-op module analysis. -struct NoOpModuleAnalysis { - struct Result {}; - Result run(Module &) { return Result(); } - static StringRef name() { return "NoOpModuleAnalysis"; } - static void *ID() { return (void *)&PassID; } -private: - static char PassID; -}; - -char NoOpModuleAnalysis::PassID; - -/// \brief No-op CGSCC pass which does nothing. -struct NoOpCGSCCPass { - PreservedAnalyses run(LazyCallGraph::SCC &C) { - return PreservedAnalyses::all(); - } - static StringRef name() { return "NoOpCGSCCPass"; } -}; - -/// \brief No-op CGSCC analysis. -struct NoOpCGSCCAnalysis { - struct Result {}; - Result run(LazyCallGraph::SCC &) { return Result(); } - static StringRef name() { return "NoOpCGSCCAnalysis"; } - static void *ID() { return (void *)&PassID; } -private: - static char PassID; -}; - -char NoOpCGSCCAnalysis::PassID; - -/// \brief No-op function pass which does nothing. -struct NoOpFunctionPass { - PreservedAnalyses run(Function &F) { return PreservedAnalyses::all(); } - static StringRef name() { return "NoOpFunctionPass"; } -}; - -/// \brief No-op function analysis. -struct NoOpFunctionAnalysis { - struct Result {}; - Result run(Function &) { return Result(); } - static StringRef name() { return "NoOpFunctionAnalysis"; } - static void *ID() { return (void *)&PassID; } -private: - static char PassID; -}; - -char NoOpFunctionAnalysis::PassID; - -} // End anonymous namespace. - -void Passes::registerModuleAnalyses(ModuleAnalysisManager &MAM) { -#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ - MAM.registerPass(CREATE_PASS); -#include "PassRegistry.def" -} - -void Passes::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) { -#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ - CGAM.registerPass(CREATE_PASS); -#include "PassRegistry.def" -} - -void Passes::registerFunctionAnalyses(FunctionAnalysisManager &FAM) { -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - FAM.registerPass(CREATE_PASS); -#include "PassRegistry.def" -} - -#ifndef NDEBUG -static bool isModulePassName(StringRef Name) { -#define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; -#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ - return true; -#include "PassRegistry.def" - - return false; -} -#endif - -static bool isCGSCCPassName(StringRef Name) { -#define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; -#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ - return true; -#include "PassRegistry.def" - - return false; -} - -static bool isFunctionPassName(StringRef Name) { -#define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ - return true; -#include "PassRegistry.def" - - return false; -} - -bool Passes::parseModulePassName(ModulePassManager &MPM, StringRef Name) { -#define MODULE_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) { \ - MPM.addPass(CREATE_PASS); \ - return true; \ - } -#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") { \ - MPM.addPass(RequireAnalysisPass()); \ - return true; \ - } \ - if (Name == "invalidate<" NAME ">") { \ - MPM.addPass(InvalidateAnalysisPass()); \ - return true; \ - } -#include "PassRegistry.def" - - return false; -} - -bool Passes::parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) { -#define CGSCC_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) { \ - CGPM.addPass(CREATE_PASS); \ - return true; \ - } -#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") { \ - CGPM.addPass(RequireAnalysisPass()); \ - return true; \ - } \ - if (Name == "invalidate<" NAME ">") { \ - CGPM.addPass(InvalidateAnalysisPass()); \ - return true; \ - } -#include "PassRegistry.def" - - return false; -} - -bool Passes::parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { -#define FUNCTION_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) { \ - FPM.addPass(CREATE_PASS); \ - return true; \ - } -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") { \ - FPM.addPass(RequireAnalysisPass()); \ - return true; \ - } \ - if (Name == "invalidate<" NAME ">") { \ - FPM.addPass(InvalidateAnalysisPass()); \ - return true; \ - } -#include "PassRegistry.def" - - return false; -} - -bool Passes::parseFunctionPassPipeline(FunctionPassManager &FPM, - StringRef &PipelineText, - bool VerifyEachPass, bool DebugLogging) { - for (;;) { - // Parse nested pass managers by recursing. - if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM(DebugLogging); - - // Parse the inner pipeline inte the nested manager. - PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, - DebugLogging) || - PipelineText.empty()) - return false; - assert(PipelineText[0] == ')'); - PipelineText = PipelineText.substr(1); - - // Add the nested pass manager with the appropriate adaptor. - FPM.addPass(std::move(NestedFPM)); - } else { - // Otherwise try to parse a pass name. - size_t End = PipelineText.find_first_of(",)"); - if (!parseFunctionPassName(FPM, PipelineText.substr(0, End))) - return false; - if (VerifyEachPass) - FPM.addPass(VerifierPass()); - - PipelineText = PipelineText.substr(End); - } - - if (PipelineText.empty() || PipelineText[0] == ')') - return true; - - assert(PipelineText[0] == ','); - PipelineText = PipelineText.substr(1); - } -} - -bool Passes::parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - StringRef &PipelineText, - bool VerifyEachPass, bool DebugLogging) { - for (;;) { - // Parse nested pass managers by recursing. - if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager NestedCGPM(DebugLogging); - - // Parse the inner pipeline into the nested manager. - PipelineText = PipelineText.substr(strlen("cgscc(")); - if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, - DebugLogging) || - PipelineText.empty()) - return false; - assert(PipelineText[0] == ')'); - PipelineText = PipelineText.substr(1); - - // Add the nested pass manager with the appropriate adaptor. - CGPM.addPass(std::move(NestedCGPM)); - } else if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM(DebugLogging); - - // Parse the inner pipeline inte the nested manager. - PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, - DebugLogging) || - PipelineText.empty()) - return false; - assert(PipelineText[0] == ')'); - PipelineText = PipelineText.substr(1); - - // Add the nested pass manager with the appropriate adaptor. - CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM))); - } else { - // Otherwise try to parse a pass name. - size_t End = PipelineText.find_first_of(",)"); - if (!parseCGSCCPassName(CGPM, PipelineText.substr(0, End))) - return false; - // FIXME: No verifier support for CGSCC passes! - - PipelineText = PipelineText.substr(End); - } - - if (PipelineText.empty() || PipelineText[0] == ')') - return true; - - assert(PipelineText[0] == ','); - PipelineText = PipelineText.substr(1); - } -} - -bool Passes::parseModulePassPipeline(ModulePassManager &MPM, - StringRef &PipelineText, - bool VerifyEachPass, bool DebugLogging) { - for (;;) { - // Parse nested pass managers by recursing. - if (PipelineText.startswith("module(")) { - ModulePassManager NestedMPM(DebugLogging); - - // Parse the inner pipeline into the nested manager. - PipelineText = PipelineText.substr(strlen("module(")); - if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass, - DebugLogging) || - PipelineText.empty()) - return false; - assert(PipelineText[0] == ')'); - PipelineText = PipelineText.substr(1); - - // Now add the nested manager as a module pass. - MPM.addPass(std::move(NestedMPM)); - } else if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager NestedCGPM(DebugLogging); - - // Parse the inner pipeline inte the nested manager. - PipelineText = PipelineText.substr(strlen("cgscc(")); - if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, - DebugLogging) || - PipelineText.empty()) - return false; - assert(PipelineText[0] == ')'); - PipelineText = PipelineText.substr(1); - - // Add the nested pass manager with the appropriate adaptor. - MPM.addPass( - createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM))); - } else if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM(DebugLogging); - - // Parse the inner pipeline inte the nested manager. - PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, - DebugLogging) || - PipelineText.empty()) - return false; - assert(PipelineText[0] == ')'); - PipelineText = PipelineText.substr(1); - - // Add the nested pass manager with the appropriate adaptor. - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(NestedFPM))); - } else { - // Otherwise try to parse a pass name. - size_t End = PipelineText.find_first_of(",)"); - if (!parseModulePassName(MPM, PipelineText.substr(0, End))) - return false; - if (VerifyEachPass) - MPM.addPass(VerifierPass()); - - PipelineText = PipelineText.substr(End); - } - - if (PipelineText.empty() || PipelineText[0] == ')') - return true; - - assert(PipelineText[0] == ','); - PipelineText = PipelineText.substr(1); - } -} - -// Primary pass pipeline description parsing routine. -// FIXME: Should this routine accept a TargetMachine or require the caller to -// pre-populate the analysis managers with target-specific stuff? -bool Passes::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass, bool DebugLogging) { - // By default, try to parse the pipeline as-if it were within an implicit - // 'module(...)' pass pipeline. If this will parse at all, it needs to - // consume the entire string. - if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging)) - return PipelineText.empty(); - - // This isn't parsable as a module pipeline, look for the end of a pass name - // and directly drop down to that layer. - StringRef FirstName = - PipelineText.substr(0, PipelineText.find_first_of(",)")); - assert(!isModulePassName(FirstName) && - "Already handled all module pipeline options."); - - // If this looks like a CGSCC pass, parse the whole thing as a CGSCC - // pipeline. - if (isCGSCCPassName(FirstName)) { - CGSCCPassManager CGPM(DebugLogging); - if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass, - DebugLogging) || - !PipelineText.empty()) - return false; - MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); - return true; - } - - // Similarly, if this looks like a Function pass, parse the whole thing as - // a Function pipelien. - if (isFunctionPassName(FirstName)) { - FunctionPassManager FPM(DebugLogging); - if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass, - DebugLogging) || - !PipelineText.empty()) - return false; - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - return true; - } - - return false; -}