[llvm-commits] CVS: llvm/lib/Analysis/ScalarEvolution.cpp

Chris Lattner lattner at cs.uiuc.edu
Mon Aug 15 16:34:03 PDT 2005



Changes in directory llvm/lib/Analysis:

ScalarEvolution.cpp updated: 1.40 -> 1.41
---
Log message:

Teach LLVM to know how many times a loop executes when constructed with
a < expression, e.g.: for (i = m; i < n; ++i)



---
Diffs of the changes:  (+110 -2)

 ScalarEvolution.cpp |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 110 insertions(+), 2 deletions(-)


Index: llvm/lib/Analysis/ScalarEvolution.cpp
diff -u llvm/lib/Analysis/ScalarEvolution.cpp:1.40 llvm/lib/Analysis/ScalarEvolution.cpp:1.41
--- llvm/lib/Analysis/ScalarEvolution.cpp:1.40	Tue Aug  9 19:59:40 2005
+++ llvm/lib/Analysis/ScalarEvolution.cpp	Mon Aug 15 18:33:51 2005
@@ -1168,14 +1168,19 @@
 
     /// HowFarToZero - Return the number of times a backedge comparing the
     /// specified value to zero will execute.  If not computable, return
-    /// UnknownValue
+    /// UnknownValue.
     SCEVHandle HowFarToZero(SCEV *V, const Loop *L);
 
     /// HowFarToNonZero - Return the number of times a backedge checking the
     /// specified value for nonzero will execute.  If not computable, return
-    /// UnknownValue
+    /// UnknownValue.
     SCEVHandle HowFarToNonZero(SCEV *V, const Loop *L);
 
+    /// HowManyLessThans - Return the number of times a backedge containing the
+    /// specified less-than comparison will execute.  If not computable, return
+    /// UnknownValue.
+    SCEVHandle HowManyLessThans(SCEV *LHS, SCEV *RHS, const Loop *L);
+
     /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
     /// in the header of its containing loop, we know the loop executes a
     /// constant number of times, and the PHI node is just a recurrence
@@ -1530,6 +1535,20 @@
       if (!isa<SCEVCouldNotCompute>(TC)) return TC;
     }
     break;
+  case Instruction::SetLT:
+    if (LHS->getType()->isInteger() && 
+        ExitCond->getOperand(0)->getType()->isSigned()) {
+      SCEVHandle TC = HowManyLessThans(LHS, RHS, L);
+      if (!isa<SCEVCouldNotCompute>(TC)) return TC;
+    }
+    break;
+  case Instruction::SetGT:
+    if (LHS->getType()->isInteger() &&
+        ExitCond->getOperand(0)->getType()->isSigned()) {
+      SCEVHandle TC = HowManyLessThans(RHS, LHS, L);
+      if (!isa<SCEVCouldNotCompute>(TC)) return TC;
+    }
+    break;
   default:
 #if 0
     std::cerr << "ComputeIterationCount ";
@@ -2169,6 +2188,95 @@
   return UnknownValue;
 }
 
+/// 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) {
+  // Only handle:  "ADDREC < LoopInvariant".
+  if (!RHS->isLoopInvariant(L)) return UnknownValue;
+
+  SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(LHS);
+  if (!AddRec || AddRec->getLoop() != L)
+    return UnknownValue;
+
+  if (AddRec->isAffine()) {
+    // FORNOW: We only support unit strides.
+    SCEVHandle One = SCEVUnknown::getIntegerSCEV(1, RHS->getType());
+    if (AddRec->getOperand(1) != One)
+      return UnknownValue;
+
+    // The number of iterations for "[n,+,1] < m", is m-n.  However, we don't
+    // know that m is >= n on input to the loop.  If it is, the condition return
+    // true zero times.  What we really should return, for full generality, is
+    // SMAX(0, m-n).  Since we cannot check this, we will instead check for a
+    // canonical loop form: most do-loops will have a check that dominates the
+    // loop, that only enters the loop if [n-1]<m.  If we can find this check,
+    // we know that the SMAX will evaluate to m-n, because we know that m >= n.
+
+    // Search for the check.
+    BasicBlock *Preheader = L->getLoopPreheader();
+    BasicBlock *PreheaderDest = L->getHeader();
+    if (Preheader == 0) return UnknownValue;
+
+    BranchInst *LoopEntryPredicate =
+      dyn_cast<BranchInst>(Preheader->getTerminator());
+    if (!LoopEntryPredicate) return UnknownValue;
+
+    // This might be a critical edge broken out.  If the loop preheader ends in
+    // an unconditional branch to the loop, check to see if the preheader has a
+    // single predecessor, and if so, look for its terminator.
+    while (LoopEntryPredicate->isUnconditional()) {
+      PreheaderDest = Preheader;
+      Preheader = Preheader->getSinglePredecessor();
+      if (!Preheader) return UnknownValue;  // Multiple preds.
+      
+      LoopEntryPredicate =
+        dyn_cast<BranchInst>(Preheader->getTerminator());
+      if (!LoopEntryPredicate) return UnknownValue;
+    }
+
+    // Now that we found a conditional branch that dominates the loop, check to
+    // see if it is the comparison we are looking for.
+    SetCondInst *SCI =dyn_cast<SetCondInst>(LoopEntryPredicate->getCondition());
+    if (!SCI) return UnknownValue;
+    Value *PreCondLHS = SCI->getOperand(0);
+    Value *PreCondRHS = SCI->getOperand(1);
+    Instruction::BinaryOps Cond;
+    if (LoopEntryPredicate->getSuccessor(0) == PreheaderDest)
+      Cond = SCI->getOpcode();
+    else
+      Cond = SCI->getInverseCondition();
+    
+    switch (Cond) {
+    case Instruction::SetGT:
+      std::swap(PreCondLHS, PreCondRHS);
+      Cond = Instruction::SetLT;
+      // Fall Through.
+    case Instruction::SetLT:
+      if (PreCondLHS->getType()->isInteger() &&
+          PreCondLHS->getType()->isSigned()) { 
+        if (RHS != getSCEV(PreCondRHS))
+          return UnknownValue;  // Not a comparison against 'm'.
+
+        if (SCEV::getMinusSCEV(AddRec->getOperand(0), One)
+                    != getSCEV(PreCondLHS))
+          return UnknownValue;  // Not a comparison against 'n-1'.
+        break;
+      } else {
+        return UnknownValue;
+      }
+    default: break;
+    }
+
+    //std::cerr << "Computed Loop Trip Count as: " <<
+    //  *SCEV::getMinusSCEV(RHS, AddRec->getOperand(0)) << "\n";
+    return SCEV::getMinusSCEV(RHS, AddRec->getOperand(0));
+  }
+
+  return UnknownValue;
+}
+
 /// getNumIterationsInRange - Return the number of iterations of this loop that
 /// produce values in the specified constant range.  Another way of looking at
 /// this is that it returns the first iteration number where the value is not in






More information about the llvm-commits mailing list