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 @@ -724,7 +724,8 @@ LPM1.addPass(LoopRotatePass(Level != OptimizationLevel::Oz)); // TODO: Investigate promotion cap for O1. LPM1.addPass(LICMPass(PTO.LicmMssaOptCap, PTO.LicmMssaNoAccForPromotionCap)); - LPM1.addPass(SimpleLoopUnswitchPass(/* NonTrivial */ true)); + LPM1.addPass( + SimpleLoopUnswitchPass(/* NonTrivial */ Level == OptimizationLevel::O3)); LPM2.addPass(LoopIdiomRecognizePass()); LPM2.addPass(IndVarSimplifyPass()); 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 @@ -2906,6 +2906,10 @@ if (!NonTrivial && !EnableNonTrivialUnswitch) return false; + // Skip non-trivial unswitching for optsize functions. + if (L.getHeader()->getParent()->hasOptSize()) + return false; + // For non-trivial unswitching, because it often creates new loops, we rely on // the pass manager to iterate on the loops rather than trying to immediately // reach a fixed point. There is no substantial advantage to iterating diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/pipeline.ll b/llvm/test/Transforms/SimpleLoopUnswitch/pipeline.ll --- a/llvm/test/Transforms/SimpleLoopUnswitch/pipeline.ll +++ b/llvm/test/Transforms/SimpleLoopUnswitch/pipeline.ll @@ -1,12 +1,15 @@ -; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefix=O1 -; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefix=O2 +; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefixes=TRIVIAL,CHECK +; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefixes=TRIVIAL,CHECK +; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefixes=NONTRIVIAL,CHECK +; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefixes=TRIVIAL,CHECK +; RUN: opt < %s -S -passes="default" | FileCheck %s -check-prefixes=TRIVIAL,CHECK declare i32 @a() declare i32 @b() declare i32 @c() -; O1-NOT: loop_begin.us: -; O2: loop_begin.us: +; TRIVIAL-NOT: loop_begin.us: +; NONTRIVIAL: loop_begin.us: define i32 @test1(i1* %ptr, i1 %cond1, i1 %cond2) { entry: @@ -37,3 +40,34 @@ loop_exit: ret i32 0 } + +; CHECK-NOT: loop2_begin.us: +define i32 @test2(i1* %ptr, i1 %cond1, i1 %cond2) optsize { +entry: + br label %loop2_begin + +loop2_begin: + br i1 %cond1, label %loop2_a, label %loop2_b + +loop2_a: + call i32 @a() + br label %latch2 + +loop2_b: + br i1 %cond2, label %loop2_b_a, label %loop2_b_b + +loop2_b_a: + call i32 @b() + br label %latch2 + +loop2_b_b: + call i32 @c() + br label %latch2 + +latch2: + %v = load i1, i1* %ptr + br i1 %v, label %loop2_begin, label %loop2_exit + +loop2_exit: + ret i32 0 +}