From: Eli Friedman Date: Wed, 11 Jan 2017 20:55:48 +0000 (+0000) Subject: [SCEV] Make howFarToZero use a simpler formula for max backedge-taken count. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=08108a29e340ada9b9a5098ba80aec9df669591a;p=llvm [SCEV] Make howFarToZero use a simpler formula for max backedge-taken count. This is both easier to understand, and produces a tighter bound in certain cases. Differential Revision: https://reviews.llvm.org/D28393 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291701 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 44f1a6dde0d..bd7e0e832f6 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -7206,17 +7206,8 @@ ScalarEvolution::howFarToZero(const SCEV *V, const Loop *L, bool ControlsExit, // 1*N = -Start; -1*N = Start (mod 2^BW), so: // N = Distance (as unsigned) if (StepC->getValue()->equalsInt(1) || StepC->getValue()->isAllOnesValue()) { - ConstantRange CR = getUnsignedRange(Start); - const SCEV *MaxBECount; - if (!CountDown && CR.getUnsignedMin().isMinValue()) - // When counting up, the worst starting value is 1, not 0. - MaxBECount = CR.getUnsignedMax().isMinValue() - ? getConstant(APInt::getMinValue(CR.getBitWidth())) - : getConstant(APInt::getMaxValue(CR.getBitWidth())); - else - MaxBECount = getConstant(CountDown ? CR.getUnsignedMax() - : -CR.getUnsignedMin()); - return ExitLimit(Distance, MaxBECount, false, Predicates); + APInt MaxBECount = getUnsignedRange(Distance).getUnsignedMax(); + return ExitLimit(Distance, getConstant(MaxBECount), false, Predicates); } // As a special case, handle the instance where Step is a positive power of diff --git a/test/Analysis/ScalarEvolution/max-trip-count.ll b/test/Analysis/ScalarEvolution/max-trip-count.ll index 614e9b265ab..bee0ac90f05 100644 --- a/test/Analysis/ScalarEvolution/max-trip-count.ll +++ b/test/Analysis/ScalarEvolution/max-trip-count.ll @@ -207,3 +207,86 @@ for.cond.i: ; preds = %for.body.i bar.exit: ; preds = %for.cond.i, %for.body.i ret i32 0 } + +; CHECK-LABEL: @ne_max_trip_count_1 +; CHECK: Loop %for.body: max backedge-taken count is 7 +define i32 @ne_max_trip_count_1(i32 %n) { +entry: + %masked = and i32 %n, 7 + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %add, %for.body ] + %add = add nsw i32 %i, 1 + %cmp = icmp ne i32 %i, %masked + br i1 %cmp, label %for.body, label %bar.exit + +bar.exit: + ret i32 0 +} + +; CHECK-LABEL: @ne_max_trip_count_2 +; CHECK: Loop %for.body: max backedge-taken count is -1 +define i32 @ne_max_trip_count_2(i32 %n) { +entry: + %masked = and i32 %n, 7 + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %add, %for.body ] + %add = add nsw i32 %i, 1 + %cmp = icmp ne i32 %add, %masked + br i1 %cmp, label %for.body, label %bar.exit + +bar.exit: + ret i32 0 +} + +; TODO: Improve count based on guard. +; CHECK-LABEL: @ne_max_trip_count_3 +; CHECK: Loop %for.body: max backedge-taken count is -1 +define i32 @ne_max_trip_count_3(i32 %n) { +entry: + %masked = and i32 %n, 7 + %guard = icmp eq i32 %masked, 0 + br i1 %guard, label %exit, label %for.preheader + +for.preheader: + br label %for.body + +for.body: + %i = phi i32 [ 0, %for.preheader ], [ %add, %for.body ] + %add = add nsw i32 %i, 1 + %cmp = icmp ne i32 %add, %masked + br i1 %cmp, label %for.body, label %loop.exit + +loop.exit: + br label %exit + +exit: + ret i32 0 +} + +; TODO: Improve count based on guard. +; CHECK-LABEL: @ne_max_trip_count_4 +; CHECK: Loop %for.body: max backedge-taken count is -1 +define i32 @ne_max_trip_count_4(i32 %n) { +entry: + %guard = icmp eq i32 %n, 0 + br i1 %guard, label %exit, label %for.preheader + +for.preheader: + br label %for.body + +for.body: + %i = phi i32 [ 0, %for.preheader ], [ %add, %for.body ] + %add = add nsw i32 %i, 1 + %cmp = icmp ne i32 %add, %n + br i1 %cmp, label %for.body, label %loop.exit + +loop.exit: + br label %exit + +exit: + ret i32 0 +}