From: Chandler Carruth Date: Sun, 12 Jan 2014 09:34:22 +0000 (+0000) Subject: [PM] Add support for parsing function passes and function pass manager X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=e7687650c9ff5e52f572d8e70752f7c808ca707e;p=oota-llvm.git [PM] Add support for parsing function passes and function pass manager nests to the opt commandline support. This also showcases the implicit-initial-manager support which will be most useful for testing. There are several bugs that I spotted by inspection here that I'll fix with test cases in subsequent commits. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199038 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Other/pass-pipeline-parsing.ll b/test/Other/pass-pipeline-parsing.ll index 20d39c78d37..c7fab01d2bf 100644 --- a/test/Other/pass-pipeline-parsing.ll +++ b/test/Other/pass-pipeline-parsing.ll @@ -16,3 +16,45 @@ ; CHECK-NESTED-TWO-NOOP-MP: Running module pass: NoOpModulePass ; CHECK-NESTED-TWO-NOOP-MP: Finished module pass manager ; CHECK-NESTED-TWO-NOOP-MP: Finished module pass manager + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes=no-op-function,no-op-function %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-TWO-NOOP-FP +; CHECK-TWO-NOOP-FP: Starting module pass manager +; CHECK-TWO-NOOP-FP: Running module pass: ModuleToFunctionPassAdaptor +; CHECK-TWO-NOOP-FP: Starting function pass manager +; CHECK-TWO-NOOP-FP: Running function pass: NoOpFunctionPass +; CHECK-TWO-NOOP-FP: Running function pass: NoOpFunctionPass +; CHECK-TWO-NOOP-FP: Finished function pass manager +; CHECK-TWO-NOOP-FP: Finished module pass manager + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='function(no-op-function,no-op-function)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-NESTED-TWO-NOOP-FP +; CHECK-NESTED-TWO-NOOP-FP: Starting module pass manager +; CHECK-NESTED-TWO-NOOP-FP: Running module pass: ModuleToFunctionPassAdaptor +; CHECK-NESTED-TWO-NOOP-FP: Starting function pass manager +; CHECK-NESTED-TWO-NOOP-FP: Running function pass: FunctionPassManager +; CHECK-NESTED-TWO-NOOP-FP: Starting function pass manager +; CHECK-NESTED-TWO-NOOP-FP: Running function pass: NoOpFunctionPass +; CHECK-NESTED-TWO-NOOP-FP: Running function pass: NoOpFunctionPass +; CHECK-NESTED-TWO-NOOP-FP: Finished function pass manager +; CHECK-NESTED-TWO-NOOP-FP: Finished function pass manager +; CHECK-NESTED-TWO-NOOP-FP: Finished module pass manager + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='no-op-module,function(no-op-function,no-op-function),no-op-module' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-MIXED-FP-AND-MP +; CHECK-MIXED-FP-AND-MP: Starting module pass manager +; CHECK-MIXED-FP-AND-MP: Running module pass: NoOpModulePass +; CHECK-MIXED-FP-AND-MP: Running module pass: ModuleToFunctionPassAdaptor +; CHECK-MIXED-FP-AND-MP: Starting function pass manager +; CHECK-MIXED-FP-AND-MP: Running function pass: NoOpFunctionPass +; CHECK-MIXED-FP-AND-MP: Running function pass: NoOpFunctionPass +; CHECK-MIXED-FP-AND-MP: Finished function pass manager +; CHECK-MIXED-FP-AND-MP: Running module pass: NoOpModulePass +; CHECK-MIXED-FP-AND-MP: Finished module pass manager + +define void @f() { + ret void +} diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index 44b3acee593..4a6341d5123 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -21,12 +21,18 @@ using namespace llvm; namespace { - /// \brief No-op module pass which does nothing. +/// \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 function pass which does nothing. +struct NoOpFunctionPass { + PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); } + static StringRef name() { return "NoOpFunctionPass"; } +}; + } // End anonymous namespace. // FIXME: Factor all of the parsing logic into a .def file that we include @@ -37,6 +43,12 @@ static bool isModulePassName(StringRef Name) { return false; } +static bool isFunctionPassName(StringRef Name) { + if (Name == "no-op-function") return true; + + return false; +} + static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { assert(isModulePassName(Name)); if (Name == "no-op-module") { @@ -46,6 +58,48 @@ static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { return false; } +static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { + assert(isFunctionPassName(Name)); + if (Name == "no-op-function") { + FPM.addPass(NoOpFunctionPass()); + return true; + } + return false; +} + +static bool parseFunctionPassPipeline(FunctionPassManager &FPM, + StringRef &PipelineText) { + for (;;) { + // Parse nested pass managers by recursing. + if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM; + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText)) + return false; + assert(!PipelineText.empty() && PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + FPM.addPass(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; + + PipelineText = PipelineText.substr(End); + } + + if (PipelineText.empty() || PipelineText[0] == ')') + return true; + + assert(PipelineText[0] == ','); + PipelineText = PipelineText.substr(1); + } +} + static bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText) { for (;;) { @@ -62,6 +116,18 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, // Now add the nested manager as a module pass. MPM.addPass(NestedMPM); + } else if (PipelineText.startswith("function(")) { + FunctionPassManager NestedFPM; + + // Parse the inner pipeline inte the nested manager. + PipelineText = PipelineText.substr(strlen("function(")); + if (!parseFunctionPassPipeline(NestedFPM, PipelineText)) + return false; + assert(!PipelineText.empty() && PipelineText[0] == ')'); + PipelineText = PipelineText.substr(1); + + // Add the nested pass manager with the appropriate adaptor. + MPM.addPass(createModuleToFunctionPassAdaptor(NestedFPM)); } else { // Otherwise try to parse a pass name. size_t End = PipelineText.find_first_of(",)"); @@ -86,15 +152,26 @@ bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText) { // Look at the first entry to figure out which layer to start parsing at. if (PipelineText.startswith("module(")) return parseModulePassPipeline(MPM, PipelineText); - - // FIXME: Support parsing function pass manager nests. + if (PipelineText.startswith("function(")) { + FunctionPassManager FPM; + if (!parseFunctionPassPipeline(FPM, PipelineText)) + return false; + MPM.addPass(createModuleToFunctionPassAdaptor(FPM)); + return true; + } // This isn't a direct pass manager name, look for the end of a pass name. StringRef FirstName = PipelineText.substr(0, PipelineText.find_first_of(",")); if (isModulePassName(FirstName)) return parseModulePassPipeline(MPM, PipelineText); - // FIXME: Support parsing function pass names. + if (isFunctionPassName(FirstName)) { + FunctionPassManager FPM; + if (!parseFunctionPassPipeline(FPM, PipelineText)) + return false; + MPM.addPass(createModuleToFunctionPassAdaptor(FPM)); + return true; + } return false; }