[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