diff --git a/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h --- a/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h +++ b/llvm/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h @@ -61,9 +61,11 @@ /// not currently implement that in any mode. class SimpleLoopUnswitchPass : public PassInfoMixin { bool NonTrivial; + bool Trivial; public: - SimpleLoopUnswitchPass(bool NonTrivial = false) : NonTrivial(NonTrivial) {} + SimpleLoopUnswitchPass(bool NonTrivial = false, bool Trivial = true) + : NonTrivial(NonTrivial), Trivial(Trivial) {} PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U); 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 @@ -2091,9 +2091,8 @@ assert(false && "unable to strip pass name from parametrized pass specification"); } - if (Params.empty()) - return ParametersT{}; - if (!Params.consume_front("<") || !Params.consume_back(">")) { + if (!Params.empty() && + (!Params.consume_front("<") || !Params.consume_back(">"))) { assert(false && "invalid format for parametrized pass name"); } @@ -2234,15 +2233,17 @@ return Opts; } -Expected parseLoopUnswitchOptions(StringRef Params) { - bool Result = false; +Expected> parseLoopUnswitchOptions(StringRef Params) { + std::pair Result = {false, true}; while (!Params.empty()) { StringRef ParamName; std::tie(ParamName, Params) = Params.split(';'); bool Enable = !ParamName.consume_front("no-"); if (ParamName == "nontrivial") { - Result = Enable; + Result.first = Enable; + } else if (ParamName == "trivial") { + Result.second = Enable; } else { return make_error( formatv("invalid LoopUnswitch pass parameter '{0}' ", ParamName) diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -445,9 +445,9 @@ #endif LOOP_PASS_WITH_PARAMS("simple-loop-unswitch", "SimpleLoopUnswitchPass", - [](bool NonTrivial) { - return SimpleLoopUnswitchPass(NonTrivial); + [](std::pair Params) { + return SimpleLoopUnswitchPass(Params.first, Params.second); }, parseLoopUnswitchOptions, - "no-nontrivial;nontrivial") + "nontrivial;no-nontrivial;trivial;no-trivial") #undef LOOP_PASS_WITH_PARAMS diff --git a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp --- a/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -2984,7 +2984,8 @@ /// done. static bool unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC, - AAResults &AA, TargetTransformInfo &TTI, bool NonTrivial, + AAResults &AA, TargetTransformInfo &TTI, bool Trivial, + bool NonTrivial, function_ref)> UnswitchCB, ScalarEvolution *SE, MemorySSAUpdater *MSSAU) { assert(L.isRecursivelyLCSSAForm(DT, LI) && @@ -2995,7 +2996,7 @@ return false; // Try trivial unswitch first before loop over other basic blocks in the loop. - if (unswitchAllTrivialConditions(L, DT, LI, SE, MSSAU)) { + if (Trivial && unswitchAllTrivialConditions(L, DT, LI, SE, MSSAU)) { // If we unswitched successfully we will want to clean up the loop before // processing it further so just mark it as unswitched and return. UnswitchCB(/*CurrentLoopValid*/ true, false, {}); @@ -3087,7 +3088,7 @@ if (VerifyMemorySSA) AR.MSSA->verifyMemorySSA(); } - if (!unswitchLoop(L, AR.DT, AR.LI, AR.AC, AR.AA, AR.TTI, NonTrivial, + if (!unswitchLoop(L, AR.DT, AR.LI, AR.AC, AR.AA, AR.TTI, Trivial, NonTrivial, UnswitchCB, &AR.SE, MSSAU.hasValue() ? MSSAU.getPointer() : nullptr)) return PreservedAnalyses::all(); @@ -3181,7 +3182,7 @@ MSSA->verifyMemorySSA(); bool Changed = - unswitchLoop(*L, DT, LI, AC, AA, TTI, NonTrivial, UnswitchCB, SE, + unswitchLoop(*L, DT, LI, AC, AA, TTI, true, NonTrivial, UnswitchCB, SE, MSSAU.hasValue() ? MSSAU.getPointer() : nullptr); if (MSSA && VerifyMemorySSA) diff --git a/llvm/test/Other/print-passes.ll b/llvm/test/Other/print-passes.ll --- a/llvm/test/Other/print-passes.ll +++ b/llvm/test/Other/print-passes.ll @@ -21,6 +21,6 @@ ; CHECK: Loop passes: ; CHECK: no-op-loop ; CHECK: Loop passes with params: -; CHECK: simple-loop-unswitch +; CHECK: simple-loop-unswitch ; CHECK: Loop analyses: ; CHECK: no-op-loop diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/options.ll b/llvm/test/Transforms/SimpleLoopUnswitch/options.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/SimpleLoopUnswitch/options.ll @@ -0,0 +1,26 @@ +; RUN: opt -passes='simple-loop-unswitch' -S < %s | FileCheck %s --check-prefix=NOTRIVIAL +; RUN: opt -passes='simple-loop-unswitch' -S < %s | FileCheck %s --check-prefix=TRIVIAL +; RUN: opt -passes='simple-loop-unswitch' -S < %s | FileCheck %s --check-prefix=TRIVIAL + +declare void @some_func() noreturn + +; NOTRIVIAL-NOT: split +; TRIVIAL: split +define i32 @test1(i32* %var, i1 %cond1, i1 %cond2) { +entry: + br label %loop_begin + +loop_begin: + br i1 %cond1, label %continue, label %loop_exit ; first trivial condition + +continue: + %var_val = load i32, i32* %var + br i1 %cond2, label %do_something, label %loop_exit ; second trivial condition + +do_something: + call void @some_func() noreturn nounwind + br label %loop_begin + +loop_exit: + ret i32 0 +} \ No newline at end of file