[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

Nick Lewycky nicholas at mxc.ca
Tue Nov 18 19:38:08 PST 2008


Evan Cheng wrote:
> Hi Nicholas,
> 
> What does "trueWhenEqual" mean? Should it default to true / false?

Like isSigned, it defines whether the comparison is true when equal, 
ie., it's an SLT/ULT vs. SLE/ULE. There is no default, but the old 
version only knew how to handle trueWhenEqual=false (ie., SLT/ULT).

Nick

> 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
> 
> _______________________________________________
> 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