From 1404fc08fc1494dbb05d98dad7fc448f25b59dff Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 11 Jan 2017 21:07:15 +0000 Subject: [PATCH] [SCEV] Make howFarToZero max backedge-taken count check for precondition. Refines max backedge-taken count if a loop like "for (int i = 0; i != n; ++i) { /* body */ }" is rotated. Differential Revision: https://reviews.llvm.org/D28536 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291704 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ScalarEvolution.cpp | 17 +++++++++++++++++ test/Analysis/ScalarEvolution/max-trip-count.ll | 6 ++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index bd7e0e832f6..791042c61fb 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -7207,6 +7207,23 @@ ScalarEvolution::howFarToZero(const SCEV *V, const Loop *L, bool ControlsExit, // N = Distance (as unsigned) if (StepC->getValue()->equalsInt(1) || StepC->getValue()->isAllOnesValue()) { APInt MaxBECount = getUnsignedRange(Distance).getUnsignedMax(); + + // When a loop like "for (int i = 0; i != n; ++i) { /* body */ }" is rotated, + // we end up with a loop whose backedge-taken count is n - 1. Detect this + // case, and see if we can improve the bound. + // + // Explicitly handling this here is necessary because getUnsignedRange + // isn't context-sensitive; it doesn't know that we only care about the + // range inside the loop. + const SCEV *Zero = getZero(Distance->getType()); + const SCEV *One = getOne(Distance->getType()); + const SCEV *DistancePlusOne = getAddExpr(Distance, One); + if (isLoopEntryGuardedByCond(L, ICmpInst::ICMP_NE, DistancePlusOne, Zero)) { + // If Distance + 1 doesn't overflow, we can compute the maximum distance + // as "unsigned_max(Distance + 1) - 1". + ConstantRange CR = getUnsignedRange(DistancePlusOne); + MaxBECount = APIntOps::umin(MaxBECount, CR.getUnsignedMax() - 1); + } return ExitLimit(Distance, getConstant(MaxBECount), false, Predicates); } diff --git a/test/Analysis/ScalarEvolution/max-trip-count.ll b/test/Analysis/ScalarEvolution/max-trip-count.ll index bee0ac90f05..d87e7d033a1 100644 --- a/test/Analysis/ScalarEvolution/max-trip-count.ll +++ b/test/Analysis/ScalarEvolution/max-trip-count.ll @@ -242,9 +242,8 @@ 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 +; CHECK: Loop %for.body: max backedge-taken count is 6 define i32 @ne_max_trip_count_3(i32 %n) { entry: %masked = and i32 %n, 7 @@ -267,9 +266,8 @@ 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 +; CHECK: Loop %for.body: max backedge-taken count is -2 define i32 @ne_max_trip_count_4(i32 %n) { entry: %guard = icmp eq i32 %n, 0