diff --git a/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h b/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h index 33c1faaeee0..c1a9ab475ea 100644 --- a/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h +++ b/include/llvm/Transforms/Scalar/SimpleLoopUnswitch.h @@ -61,9 +61,11 @@ namespace llvm { /// 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/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp index 145ecffeb3a..1f756e74b9f 100644 --- a/lib/Passes/PassBuilder.cpp +++ b/lib/Passes/PassBuilder.cpp @@ -2091,9 +2091,8 @@ auto parsePassParameters(ParametersParseCallableT &&Parser, StringRef Name, 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 @@ Expected parseLoopVectorizeOptions(StringRef Params) { 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/lib/Passes/PassRegistry.def b/lib/Passes/PassRegistry.def index 21a3c196b4d..6316765b6f1 100644 --- a/lib/Passes/PassRegistry.def +++ b/lib/Passes/PassRegistry.def @@ -445,9 +445,9 @@ LOOP_PASS("loop-versioning-licm", LoopVersioningLICMPass()) #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/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index e219c3970bb..78b97aebe9a 100644 --- a/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -2984,7 +2984,8 @@ static bool unswitchBestCondition( /// 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 @@ unswitchLoop(Loop &L, DominatorTree &DT, LoopInfo &LI, AssumptionCache &AC, 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 @@ PreservedAnalyses SimpleLoopUnswitchPass::run(Loop &L, LoopAnalysisManager &AM, 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 @@ bool SimpleLoopUnswitchLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) { 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/test/Other/print-passes.ll b/test/Other/print-passes.ll index acaa65f01fd..09db6e96783 100644 --- a/test/Other/print-passes.ll +++ b/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/test/Transforms/SimpleLoopUnswitch/options.ll b/test/Transforms/SimpleLoopUnswitch/options.ll new file mode 100644 index 00000000000..754bd7e9224 --- /dev/null +++ b/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