diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -472,10 +472,21 @@ /// 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. + /// combinations. + /// + /// The sequence of passes aren't necessarily the exact same kind of pass. + /// You can mix different levels implicitly if adaptor passes are defined to + /// make them work. For example, + /// + /// mpass1,fpass1,fpass2,mpass2,lpass1 + /// + /// This pipeline uses only one pass manager: the top-level module manager. + /// fpass1,fpass2 and lpass1 are added into the the top-level module manager + /// using only adaptor passes. No nested function/loop pass managers are added. + /// The purpose is to allow easy pass testing when the user specifically + /// want the pass to run under a adaptor directly. This is preferred when + /// a pipeline is largely of one type, but one or just a few passes are of + /// different types(See PassBuilder.cpp for examples). Error parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, bool VerifyEachPass = true, bool DebugLogging = false); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -2198,6 +2198,40 @@ std::remove_reference::type>()); \ return Error::success(); \ } +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \ + return Error::success(); \ + } +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToFunctionPassAdaptor( \ + createFunctionToLoopPassAdaptor(CREATE_PASS, false, DebugLogging))); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass( \ + createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS(Params.get()), false, DebugLogging))); \ + return Error::success(); \ + } +#define CGSCC_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : ModulePipelineParsingCallbacks) @@ -2281,6 +2315,35 @@ std::remove_reference::type>()); \ return Error::success(); \ } +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \ + return Error::success(); \ + } +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor( \ + createFunctionToLoopPassAdaptor(CREATE_PASS, false, DebugLogging))); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + CGPM.addPass( \ + createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS(Params.get()), false, DebugLogging))); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : CGSCCPipelineParsingCallbacks) @@ -2364,6 +2427,25 @@ std::remove_reference::type>()); \ return Error::success(); \ } +// FIXME: UseMemorySSA is set to false. Maybe we could do things like: +// bool UseMemorySSA = !("canon-freeze" || "loop-predication" || +// "guard-widening") +// The risk is that it may become obsolete if we're not careful. +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + FPM.addPass( \ + createFunctionToLoopPassAdaptor(CREATE_PASS, false, DebugLogging)); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), \ + false, DebugLogging)); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : FunctionPipelineParsingCallbacks) diff --git a/llvm/test/Analysis/GlobalsModRef/aliastest.ll b/llvm/test/Analysis/GlobalsModRef/aliastest.ll --- a/llvm/test/Analysis/GlobalsModRef/aliastest.ll +++ b/llvm/test/Analysis/GlobalsModRef/aliastest.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -basicaa -globals-aa -gvn -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes="require,function(gvn)" -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -passes="require,gvn" -S -enable-unsafe-globalsmodref-alias-results | FileCheck %s ; ; Note that this test relies on an unsafe feature of GlobalsModRef. While this ; test is correct and safe, GMR's technique for handling this isn't generally. diff --git a/llvm/test/Other/cgscc-disconnected-invalidation.ll b/llvm/test/Other/cgscc-disconnected-invalidation.ll --- a/llvm/test/Other/cgscc-disconnected-invalidation.ll +++ b/llvm/test/Other/cgscc-disconnected-invalidation.ll @@ -1,7 +1,7 @@ ; Test that patterns of transformations which disconnect a region of the call ; graph mid-traversal and then invalidate it function correctly. ; -; RUN: opt -S -passes='cgscc(inline,function(simplify-cfg))' < %s | FileCheck %s +; RUN: opt -S -passes='cgscc(inline,simplify-cfg)' < %s | FileCheck %s define internal void @test_scc_internal(i1 %flag) { ; CHECK-NOT: @test_scc_internal diff --git a/llvm/test/Other/pass-pipeline-parsing.ll b/llvm/test/Other/pass-pipeline-parsing.ll --- a/llvm/test/Other/pass-pipeline-parsing.ll +++ b/llvm/test/Other/pass-pipeline-parsing.ll @@ -51,6 +51,15 @@ ; CHECK-MIXED-FP-AND-MP: Running pass: NoOpModulePass ; CHECK-MIXED-FP-AND-MP: Finished llvm::Module pass manager run +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='no-op-module,no-op-function,no-op-module' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-MIXED-FP-AND-MP2 +; CHECK-MIXED-FP-AND-MP2: Starting llvm::Module pass manager run +; CHECK-MIXED-FP-AND-MP2: Running pass: NoOpModulePass +; CHECK-MIXED-FP-AND-MP2: Running pass: ModuleToFunctionPassAdaptor{{.*}}NoOpFunctionPass +; CHECK-MIXED-FP-AND-MP2: Running pass: NoOpModulePass +; CHECK-MIXED-FP-AND-MP2: Finished llvm::Module pass manager run + ; RUN: not opt -disable-output -debug-pass-manager \ ; RUN: -passes='no-op-module)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED1 diff --git a/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll b/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll --- a/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll +++ b/llvm/test/Transforms/Inline/2007-04-15-InlineEH.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -inline -S | FileCheck %s -; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s +; RUN: opt < %s -passes='inline' -S | FileCheck %s ; PR1335 target triple = "i686-pc-linux-gnu"