From 32acc1f62e2758a575e460ae9b2b06b7a33ea4a3 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Sat, 22 Jun 2019 17:54:25 +0000 Subject: [PATCH] Exploit a zero LoopExit count to eliminate loop exits This turned out to be surprisingly effective. I was originally doing this just for completeness sake, but it seems like there are a lot of cases where SCEV's exit count reasoning is stronger than it's isKnownPredicate reasoning. Once this is in, I'm thinking about trying to build on the same infrastructure to eliminate provably untaken checks. There may be something generally interesting here. Differential Revision: https://reviews.llvm.org/D63618 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364135 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/IndVarSimplify.cpp | 16 ++++++++++++++-- .../IndVarSimplify/eliminate-comparison.ll | 3 +-- .../Transforms/IndVarSimplify/eliminate-trunc.ll | 4 ++-- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 69dd973c114..57f246373f0 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -2724,9 +2724,21 @@ bool IndVarSimplify::run(Loop *L) { if (isa(ExitCount)) continue; - // Better to fold to true (TODO: do so!) - if (ExitCount->isZero()) + // If we know we'd exit on the first iteration, rewrite the exit to + // reflect this. This does not imply the loop must exit through this + // exit; there may be an earlier one taken on the first iteration. + // TODO: Given we know the backedge can't be taken, we should go ahead + // and break it. Or at least, kill all the header phis and simplify. + if (ExitCount->isZero()) { + auto *BI = cast(ExitingBB->getTerminator()); + bool ExitIfTrue = !L->contains(*succ_begin(ExitingBB)); + auto *NewCond = ExitIfTrue ? + ConstantInt::getTrue(BI->getCondition()->getType()) : + ConstantInt::getFalse(BI->getCondition()->getType()); + BI->setCondition(NewCond); + Changed = true; continue; + } PHINode *IndVar = FindLoopCounter(L, ExitingBB, ExitCount, SE, DT); if (!IndVar) diff --git a/test/Transforms/IndVarSimplify/eliminate-comparison.ll b/test/Transforms/IndVarSimplify/eliminate-comparison.ll index cd639f8d731..49088601125 100644 --- a/test/Transforms/IndVarSimplify/eliminate-comparison.ll +++ b/test/Transforms/IndVarSimplify/eliminate-comparison.ll @@ -284,7 +284,7 @@ define i32 @func_12() nounwind uwtable { ; CHECK-NEXT: [[SEXT21:%.*]] = shl i32 [[TMP57]], 16 ; CHECK-NEXT: [[TMP76:%.*]] = icmp ne i32 [[SEXT34]], [[SEXT21]] ; CHECK-NEXT: [[TMP81]] = add nuw nsw i32 [[__KEY8_0]], 1 -; CHECK-NEXT: br i1 [[TMP76]], label [[FORCOND38]], label [[ASSERT77:%.*]] +; CHECK-NEXT: br i1 false, label [[FORCOND38]], label [[ASSERT77:%.*]] ; CHECK: assert77: ; CHECK-NEXT: tail call void @llvm.trap() ; CHECK-NEXT: unreachable @@ -897,5 +897,4 @@ leave: ret void } - !0 = !{i32 0, i32 2147483647} diff --git a/test/Transforms/IndVarSimplify/eliminate-trunc.ll b/test/Transforms/IndVarSimplify/eliminate-trunc.ll index f152c236859..eaa20b5bf6d 100644 --- a/test/Transforms/IndVarSimplify/eliminate-trunc.ll +++ b/test/Transforms/IndVarSimplify/eliminate-trunc.ll @@ -174,7 +174,7 @@ define void @test_06(i32 %n) { ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 ; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[NARROW_IV]], [[N:%.*]] -; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void ; @@ -354,7 +354,7 @@ define void @test_06_unsigned(i32 %n) { ; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 ; CHECK-NEXT: [[NARROW_IV:%.*]] = trunc i64 [[IV]] to i32 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[NARROW_IV]], [[N:%.*]] -; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] +; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void ; -- 2.40.0