[llvm-commits] [llvm] r59528 - in /llvm/trunk: lib/Analysis/ScalarEvolution.cpp test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
Evan Cheng
evan.cheng at apple.com
Tue Nov 18 10:22:52 PST 2008
Hi Nicholas,
What does "trueWhenEqual" mean? Should it default to true / false?
Thanks,
Evan
On Nov 18, 2008, at 7:10 AM, Nick Lewycky wrote:
> Author: nicholas
> Date: Tue Nov 18 09:10:54 2008
> New Revision: 59528
>
> URL: http://llvm.org/viewvc/llvm-project?rev=59528&view=rev
> Log:
> Add a utility function that detects whether a loop is guaranteed to
> be finite.
>
> Use it to safely handle less-than-or-equals-to exit conditions in
> loops. These
> also occur when the loop exit branch is exit on true because SCEV
> inverses the
> icmp predicate.
>
> Use it again to handle non-zero strides, but only with an unsigned
> comparison
> in the exit condition.
>
> Added:
> llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-
> LessThanOrEqual.ll
> llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll
> llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
> Modified:
> llvm/trunk/lib/Analysis/ScalarEvolution.cpp
>
> Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=59528&r1=59527&r2=59528&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
> +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Tue Nov 18 09:10:54
> 2008
> @@ -1477,7 +1477,7 @@
> /// specified less-than comparison will execute. If not
> computable, return
> /// UnknownValue. isSigned specifies whether the less-than is
> signed.
> SCEVHandle HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L,
> - bool isSigned);
> + bool isSigned, bool trueWhenEqual);
>
> /// getPredecessorWithUniqueSuccessorForBB - Return a
> predecessor of BB
> /// (which may not be an immediate predecessor) which has
> exactly one
> @@ -1487,7 +1487,13 @@
>
> /// executesAtLeastOnce - Test whether entry to the loop is
> protected by
> /// a conditional between LHS and RHS.
> - bool executesAtLeastOnce(const Loop *L, bool isSigned, SCEV
> *LHS, SCEV *RHS);
> + bool executesAtLeastOnce(const Loop *L, bool isSigned, bool
> trueWhenEqual,
> + SCEV *LHS, SCEV *RHS);
> +
> + /// potentialInfiniteLoop - Test whether the loop might jump
> over the exit value
> + /// due to wrapping.
> + bool potentialInfiniteLoop(SCEV *Stride, SCEV *RHS, bool
> isSigned,
> + bool trueWhenEqual);
>
> /// getConstantEvolutionLoopExitValue - If we know that the
> specified Phi is
> /// in the header of its containing loop, we know the loop
> executes a
> @@ -2025,24 +2031,46 @@
> break;
> }
> case ICmpInst::ICMP_SLT: {
> - SCEVHandle TC = HowManyLessThans(LHS, RHS, L, true);
> + SCEVHandle TC = HowManyLessThans(LHS, RHS, L, true, false);
> if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> break;
> }
> case ICmpInst::ICMP_SGT: {
> SCEVHandle TC = HowManyLessThans(SE.getNotSCEV(LHS),
> - SE.getNotSCEV(RHS), L, true);
> + SE.getNotSCEV(RHS), L, true,
> false);
> if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> break;
> }
> case ICmpInst::ICMP_ULT: {
> - SCEVHandle TC = HowManyLessThans(LHS, RHS, L, false);
> + SCEVHandle TC = HowManyLessThans(LHS, RHS, L, false, false);
> if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> break;
> }
> case ICmpInst::ICMP_UGT: {
> SCEVHandle TC = HowManyLessThans(SE.getNotSCEV(LHS),
> - SE.getNotSCEV(RHS), L, false);
> + SE.getNotSCEV(RHS), L, false,
> false);
> + if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> + break;
> + }
> + case ICmpInst::ICMP_SLE: {
> + SCEVHandle TC = HowManyLessThans(LHS, RHS, L, true, true);
> + if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> + break;
> + }
> + case ICmpInst::ICMP_SGE: {
> + SCEVHandle TC = HowManyLessThans(SE.getNotSCEV(LHS),
> + SE.getNotSCEV(RHS), L, true,
> true);
> + if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> + break;
> + }
> + case ICmpInst::ICMP_ULE: {
> + SCEVHandle TC = HowManyLessThans(LHS, RHS, L, false, true);
> + if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> + break;
> + }
> + case ICmpInst::ICMP_UGE: {
> + SCEVHandle TC = HowManyLessThans(SE.getNotSCEV(LHS),
> + SE.getNotSCEV(RHS), L, false,
> true);
> if (!isa<SCEVCouldNotCompute>(TC)) return TC;
> break;
> }
> @@ -2738,6 +2766,7 @@
> /// executesAtLeastOnce - Test whether entry to the loop is
> protected by
> /// a conditional between LHS and RHS.
> bool ScalarEvolutionsImpl::executesAtLeastOnce(const Loop *L, bool
> isSigned,
> + bool trueWhenEqual,
> SCEV *LHS, SCEV *RHS) {
> BasicBlock *Preheader = L->getLoopPreheader();
> BasicBlock *PreheaderDest = L->getHeader();
> @@ -2770,20 +2799,36 @@
>
> switch (Cond) {
> case ICmpInst::ICMP_UGT:
> - if (isSigned) continue;
> + if (isSigned || trueWhenEqual) continue;
> std::swap(PreCondLHS, PreCondRHS);
> Cond = ICmpInst::ICMP_ULT;
> break;
> case ICmpInst::ICMP_SGT:
> - if (!isSigned) continue;
> + if (!isSigned || trueWhenEqual) continue;
> std::swap(PreCondLHS, PreCondRHS);
> Cond = ICmpInst::ICMP_SLT;
> break;
> case ICmpInst::ICMP_ULT:
> - if (isSigned) continue;
> + if (isSigned || trueWhenEqual) continue;
> break;
> case ICmpInst::ICMP_SLT:
> - if (!isSigned) continue;
> + if (!isSigned || trueWhenEqual) continue;
> + break;
> + case ICmpInst::ICMP_UGE:
> + if (isSigned || !trueWhenEqual) continue;
> + std::swap(PreCondLHS, PreCondRHS);
> + Cond = ICmpInst::ICMP_ULE;
> + break;
> + case ICmpInst::ICMP_SGE:
> + if (!isSigned || !trueWhenEqual) continue;
> + std::swap(PreCondLHS, PreCondRHS);
> + Cond = ICmpInst::ICMP_SLE;
> + break;
> + case ICmpInst::ICMP_ULE:
> + if (isSigned || !trueWhenEqual) continue;
> + break;
> + case ICmpInst::ICMP_SLE:
> + if (!isSigned || !trueWhenEqual) continue;
> break;
> default:
> continue;
> @@ -2802,11 +2847,46 @@
> return false;
> }
>
> +/// potentialInfiniteLoop - Test whether the loop might jump over
> the exit value
> +/// due to wrapping around 2^n.
> +bool ScalarEvolutionsImpl::potentialInfiniteLoop(SCEV *Stride, SCEV
> *RHS,
> + bool isSigned,
> bool trueWhenEqual) {
> + // Return true when the distance from RHS to maxint > Stride.
> +
> + if (!isa<SCEVConstant>(Stride))
> + return true;
> + SCEVConstant *SC = cast<SCEVConstant>(Stride);
> +
> + if (SC->getValue()->isZero())
> + return true;
> + if (!trueWhenEqual && SC->getValue()->isOne())
> + return false;
> +
> + if (!isa<SCEVConstant>(RHS))
> + return true;
> + SCEVConstant *R = cast<SCEVConstant>(RHS);
> +
> + if (isSigned)
> + return true; // XXX: because we don't have an sdiv scev.
> +
> + // If negative, it wraps around every iteration, but we don't
> care about that.
> + APInt S = SC->getValue()->getValue().abs();
> +
> + APInt Dist = APInt::getMaxValue(R->getValue()->getBitWidth()) -
> + R->getValue()->getValue();
> +
> + if (trueWhenEqual)
> + return !S.ult(Dist);
> + else
> + return !S.ule(Dist);
> +}
> +
> /// HowManyLessThans - Return the number of times a backedge
> containing the
> /// specified less-than comparison will execute. If not computable,
> return
> /// UnknownValue.
> SCEVHandle ScalarEvolutionsImpl::
> -HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L, bool
> isSigned) {
> +HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L,
> + bool isSigned, bool trueWhenEqual) {
> // Only handle: "ADDREC < LoopInvariant".
> if (!RHS->isLoopInvariant(L)) return UnknownValue;
>
> @@ -2815,34 +2895,50 @@
> return UnknownValue;
>
> if (AddRec->isAffine()) {
> - // FORNOW: We only support unit strides.
> - SCEVHandle One = SE.getIntegerSCEV(1, RHS->getType());
> - if (AddRec->getOperand(1) != One)
> + SCEVHandle Stride = AddRec->getOperand(1);
> + if (potentialInfiniteLoop(Stride, RHS, isSigned, trueWhenEqual))
> return UnknownValue;
>
> - // We know the LHS is of the form {n,+,1} and the RHS is some
> loop-invariant
> - // m. So, we count the number of iterations in which {n,+,1} <
> m is true.
> - // Note that we cannot simply return max(m-n,0) because it's
> not safe to
> + // We know the LHS is of the form {n,+,s} and the RHS is some
> loop-invariant
> + // m. So, we count the number of iterations in which {n,+,s} <
> m is true.
> + // Note that we cannot simply return max(m-n,0)/s because it's
> not safe to
> // treat m-n as signed nor unsigned due to overflow possibility.
>
> // First, we get the value of the LHS in the first iteration: n
> SCEVHandle Start = AddRec->getOperand(0);
>
> - if (executesAtLeastOnce(L, isSigned,
> - SE.getMinusSCEV(AddRec->getOperand(0),
> One), RHS)) {
> - // Since we know that the condition is true in order to enter
> the loop,
> - // we know that it will run exactly m-n times.
> - return SE.getMinusSCEV(RHS, Start);
> - } else {
> - // Then, we get the value of the LHS in the first iteration
> in which the
> - // above condition doesn't hold. This equals to max(m,n).
> - SCEVHandle End = isSigned ? SE.getSMaxExpr(RHS, Start)
> - : SE.getUMaxExpr(RHS, Start);
> -
> - // Finally, we subtract these two values to get the number of
> times the
> - // backedge is executed: max(m,n)-n.
> - return SE.getMinusSCEV(End, Start);
> + SCEVHandle One = SE.getIntegerSCEV(1, RHS->getType());
> +
> + // Assuming that the loop will run at least once, we know that
> it will
> + // run (m-n)/s times.
> + SCEVHandle End = RHS;
> +
> + if (!executesAtLeastOnce(L, isSigned, trueWhenEqual,
> + SE.getMinusSCEV(Start, One), RHS)) {
> + // If not, we get the value of the LHS in the first iteration
> in which
> + // the above condition doesn't hold. This equals to max(m,n).
> + End = isSigned ? SE.getSMaxExpr(RHS, Start)
> + : SE.getUMaxExpr(RHS, Start);
> }
> +
> + // If the expression is less-than-or-equal to, we need to
> extend the
> + // loop by one iteration.
> + //
> + // The loop won't actually run (m-n)/s times because the loop
> iterations
> + // won't divide evenly. For example, if you have {2,+,5} u< 10
> the
> + // division would equal one, but the loop runs twice putting the
> + // induction variable at 12.
> +
> + if (!trueWhenEqual)
> + // (Stride - 1) is correct only because we know it's unsigned.
> + // What we really want is to decrease the magnitude of Stride
> by one.
> + Start = SE.getMinusSCEV(Start, SE.getMinusSCEV(Stride, One));
> + else
> + Start = SE.getMinusSCEV(Start, Stride);
> +
> + // Finally, we subtract these two values to get the number of
> times the
> + // backedge is executed: max(m,n)-n.
> + return SE.getUDivExpr(SE.getMinusSCEV(End, Start), Stride);
> }
>
> return UnknownValue;
>
> Added: llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-
> LessThanOrEqual.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll?rev=59528&view=auto
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-
> LessThanOrEqual.ll (added)
> +++ llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-
> LessThanOrEqual.ll Tue Nov 18 09:10:54 2008
> @@ -0,0 +1,31 @@
> +; RUN: llvm-as < %s | opt -analyze -scalar-evolution |& \
> +; RUN: grep {Loop bb: (7 + (-1 \\* %argc)) iterations!}
> +
> +define i32 @main(i32 %argc, i8** %argv) nounwind {
> +entry:
> + %0 = icmp ugt i32 %argc, 7 ; <i1> [#uses=1]
> + br i1 %0, label %bb2, label %bb.nph
> +
> +bb.nph: ; preds = %entry
> + br label %bb
> +
> +bb: ; preds = %bb.nph, %bb1
> + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; <i32>
> [#uses=2]
> + %argc_addr.04 = add i32 %indvar, %argc ; <i32> [#uses=1]
> + tail call void (...)* @Test() nounwind
> + %1 = add i32 %argc_addr.04, 1 ; <i32> [#uses=1]
> + br label %bb1
> +
> +bb1: ; preds = %bb
> + %phitmp = icmp ugt i32 %1, 7 ; <i1> [#uses=1]
> + %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
> + br i1 %phitmp, label %bb1.bb2_crit_edge, label %bb
> +
> +bb1.bb2_crit_edge: ; preds = %bb1
> + br label %bb2
> +
> +bb2: ; preds = %bb1.bb2_crit_edge, %entry
> + ret i32 0
> +}
> +
> +declare void @Test(...)
>
> Added: llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll?rev=59528&view=auto
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll
> (added)
> +++ llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll
> Tue Nov 18 09:10:54 2008
> @@ -0,0 +1,30 @@
> +; RUN: llvm-as < %s | opt -analyze -scalar-evolution |& grep {/u 3}
> +
> +define i32 @f(i32 %x) nounwind readnone {
> +entry:
> + %0 = icmp ugt i32 %x, 4 ; <i1> [#uses=1]
> + br i1 %0, label %bb.nph, label %bb2
> +
> +bb.nph: ; preds = %entry
> + br label %bb
> +
> +bb: ; preds = %bb.nph, %bb1
> + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; <i32>
> [#uses=2]
> + %tmp = mul i32 %indvar, -3 ; <i32> [#uses=1]
> + %x_addr.04 = add i32 %tmp, %x ; <i32> [#uses=1]
> + %1 = add i32 %x_addr.04, -3 ; <i32> [#uses=2]
> + br label %bb1
> +
> +bb1: ; preds = %bb
> + %2 = icmp ugt i32 %1, 4 ; <i1> [#uses=1]
> + %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
> + br i1 %2, label %bb, label %bb1.bb2_crit_edge
> +
> +bb1.bb2_crit_edge: ; preds = %bb1
> + %.lcssa = phi i32 [ %1, %bb1 ] ; <i32> [#uses=1]
> + br label %bb2
> +
> +bb2: ; preds = %bb1.bb2_crit_edge, %entry
> + %x_addr.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ %x,
> %entry ] ; <i32> [#uses=1]
> + ret i32 %x_addr.0.lcssa
> +}
>
> Added: llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll?rev=59528&view=auto
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
> (added)
> +++ llvm/trunk/test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll
> Tue Nov 18 09:10:54 2008
> @@ -0,0 +1,30 @@
> +; RUN: llvm-as < %s | opt -analyze -scalar-evolution |& grep {/u 3}
> +
> +define i32 @f(i32 %x) nounwind readnone {
> +entry:
> + %0 = icmp ugt i32 %x, 999 ; <i1> [#uses=1]
> + br i1 %0, label %bb2, label %bb.nph
> +
> +bb.nph: ; preds = %entry
> + br label %bb
> +
> +bb: ; preds = %bb.nph, %bb1
> + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; <i32>
> [#uses=2]
> + %tmp = mul i32 %indvar, 3 ; <i32> [#uses=1]
> + %x_addr.04 = add i32 %tmp, %x ; <i32> [#uses=1]
> + %1 = add i32 %x_addr.04, 3 ; <i32> [#uses=2]
> + br label %bb1
> +
> +bb1: ; preds = %bb
> + %2 = icmp ugt i32 %1, 999 ; <i1> [#uses=1]
> + %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=1]
> + br i1 %2, label %bb1.bb2_crit_edge, label %bb
> +
> +bb1.bb2_crit_edge: ; preds = %bb1
> + %.lcssa = phi i32 [ %1, %bb1 ] ; <i32> [#uses=1]
> + br label %bb2
> +
> +bb2: ; preds = %bb1.bb2_crit_edge, %entry
> + %x_addr.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ %x,
> %entry ] ; <i32> [#uses=1]
> + ret i32 %x_addr.0.lcssa
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list