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

Chris Lattner lattner at cs.uiuc.edu
Sat Apr 17 18:41:38 PDT 2004


Changes in directory llvm/lib/Analysis:

ScalarEvolution.cpp updated: 1.13 -> 1.14

---
Log message:

Add the ability to compute exit values for complex loop using unanalyzable 
operations.  This allows us to compile this testcase:

int main() {
        int h = 1;
         do h = 3 * h + 1; while (h <= 256);
        printf("%d\n", h);
        return 0;
}

into this:

int %main() {
entry:
        call void %__main( )
        %tmp.6 = call int (sbyte*, ...)* %printf( sbyte* getelementptr ([4 x sbyte]*  %.str_1, long 0, long 0), int 364 )        ; <int> [#uses=0]
        ret int 0
}

This testcase was taken directly from 256.bzip2, believe it or not.

This code is not as general as I would like.  Next up is to refactor it
a bit to handle more cases.




---
Diffs of the changes:  (+189 -52)

Index: llvm/lib/Analysis/ScalarEvolution.cpp
diff -u llvm/lib/Analysis/ScalarEvolution.cpp:1.13 llvm/lib/Analysis/ScalarEvolution.cpp:1.14
--- llvm/lib/Analysis/ScalarEvolution.cpp:1.13	Sat Apr 17 13:36:24 2004
+++ llvm/lib/Analysis/ScalarEvolution.cpp	Sat Apr 17 17:58:41 2004
@@ -1136,6 +1136,13 @@
     /// function as they are computed.
     std::map<const Loop*, SCEVHandle> IterationCounts;
 
+    /// ConstantEvolutionLoopExitValue - This map contains entries for all of
+    /// the PHI instructions that we attempt to compute constant evolutions for.
+    /// This allows us to avoid potentially expensive recomputation of these
+    /// properties.  An instruction maps to null if we are unable to compute its
+    /// exit value.
+    std::map<PHINode*, Constant*> ConstantEvolutionLoopExitValue;
+    
   public:
     ScalarEvolutionsImpl(Function &f, LoopInfo &li)
       : F(f), LI(li), UnknownValue(new SCEVCouldNotCompute()) {}
@@ -1197,6 +1204,13 @@
     /// specified value for nonzero will execute.  If not computable, return
     /// UnknownValue
     SCEVHandle HowFarToNonZero(SCEV *V, 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
+    /// involving constants, fold it.
+    Constant *getConstantEvolutionLoopExitValue(PHINode *PN, uint64_t Its,
+                                                const Loop *L);
   };
 }
 
@@ -1209,6 +1223,8 @@
 /// that no dangling references are left around.
 void ScalarEvolutionsImpl::deleteInstructionFromRecords(Instruction *I) {
   Scalars.erase(I);
+  if (PHINode *PN = dyn_cast<PHINode>(I))
+    ConstantEvolutionLoopExitValue.erase(PN);
 }
 
 
@@ -1552,6 +1568,46 @@
                                          ExitBr->getSuccessor(0) == ExitBlock);
 }
 
+/// CanConstantFold - Return true if we can constant fold an instruction of the
+/// specified type, assuming that all operands were constants.
+static bool CanConstantFold(const Instruction *I) {
+  if (isa<BinaryOperator>(I) || isa<ShiftInst>(I) ||
+      isa<SelectInst>(I) || isa<CastInst>(I) || isa<GetElementPtrInst>(I))
+    return true;
+  
+  if (const CallInst *CI = dyn_cast<CallInst>(I))
+    if (const Function *F = CI->getCalledFunction())
+      return canConstantFoldCallTo((Function*)F);  // FIXME: elim cast
+  return false;
+}
+
+/// ConstantFold - Constant fold an instruction of the specified type with the
+/// specified constant operands.  This function may modify the operands vector.
+static Constant *ConstantFold(const Instruction *I,
+                              std::vector<Constant*> &Operands) {
+  if (isa<BinaryOperator>(I) || isa<ShiftInst>(I))
+    return ConstantExpr::get(I->getOpcode(), Operands[0], Operands[1]);
+
+  switch (I->getOpcode()) {
+  case Instruction::Cast:
+    return ConstantExpr::getCast(Operands[0], I->getType());
+  case Instruction::Select:
+    return ConstantExpr::getSelect(Operands[0], Operands[1], Operands[2]);
+  case Instruction::Call:
+    if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(Operands[0])) {
+      Operands.erase(Operands.begin());
+      return ConstantFoldCall(cast<Function>(CPR->getValue()), Operands);
+    }
+
+    return 0;
+  case Instruction::GetElementPtr:
+    Constant *Base = Operands[0];
+    Operands.erase(Operands.begin());
+    return ConstantExpr::getGetElementPtr(Base, Operands);
+  }
+  return 0;
+}
+
 
 /// getConstantEvolvingPHI - Given an LLVM value and a loop, return a PHI node
 /// in the loop that V is derived from.  We allow arbitrary operations along the
@@ -1572,36 +1628,26 @@
       // PHIs, so we cannot handle PHIs inside of loops.
       return 0;
 
-  // If this is a call, and we have no hope of constant folding, bail early.
-  if (CallInst *CI = dyn_cast<CallInst>(I)) {
-    if (!CI->getCalledFunction() ||
-        !canConstantFoldCallTo(CI->getCalledFunction()))
-      return 0;
-  } else if (InvokeInst *II = dyn_cast<InvokeInst>(I))
-    return 0;
+  // If we won't be able to constant fold this expression even if the operands
+  // are constants, return early.
+  if (!CanConstantFold(I)) return 0;
   
-  // Otherwise, we can evaluate this instruction if all of its operands but one
-  // are constant, and if the remaining one is derived from a constant evolving
-  // PHI.
-  unsigned Op = 0, e = I->getNumOperands();
-  while (Op != e && (isa<Constant>(I->getOperand(Op)) ||
-                     isa<GlobalValue>(I->getOperand(Op))))
-    ++Op;          // Skip over all constant operands
-  
-  if (Op == e) return 0;  // No non-constants? Should be folded!
-  
-  // Found the first non-constant operand.
-  unsigned NonConstantOp = Op;
-
-  // Okay, all of the rest must be constants now.
-  for (++Op; Op != e; ++Op)
+  // Otherwise, we can evaluate this instruction if all of its operands are
+  // constant or derived from a PHI node themselves.
+  PHINode *PHI = 0;
+  for (unsigned Op = 0, e = I->getNumOperands(); Op != e; ++Op)
     if (!(isa<Constant>(I->getOperand(Op)) ||
-          isa<GlobalValue>(I->getOperand(Op))))
-      return 0;  // Too many non-constant operands!
+          isa<GlobalValue>(I->getOperand(Op)))) {
+      PHINode *P = getConstantEvolvingPHI(I->getOperand(Op), L);
+      if (P == 0) return 0;  // Not evolving from PHI
+      if (PHI == 0)
+        PHI = P;
+      else if (PHI != P)
+        return 0;  // Evolving from multiple different PHIs.
+    }
 
-  // This is a expression evolving from a constant PHI if the non-constant
-  // portion is!
-  return getConstantEvolvingPHI(I->getOperand(NonConstantOp), L);
+  // This is a expression evolving from a constant PHI!
+  return PHI;
 }
 
 /// EvaluateExpression - Given an expression that passes the
@@ -1623,30 +1669,59 @@
     if (Operands[i] == 0) return 0;
   }
 
-  if (isa<BinaryOperator>(I) || isa<ShiftInst>(I))
-    return ConstantExpr::get(I->getOpcode(), Operands[0], Operands[1]);
+  return ConstantFold(I, Operands);
+}
 
-  switch (I->getOpcode()) {
-  case Instruction::Cast:
-    return ConstantExpr::getCast(Operands[0], I->getType());
-  case Instruction::Select:
-    return ConstantExpr::getSelect(Operands[0], Operands[1], Operands[2]);
-  case Instruction::Call:
-    if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(Operands[0])) {
-      Operands.erase(Operands.begin());
-      return ConstantFoldCall(cast<Function>(CPR->getValue()), Operands);
-    }
+/// 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
+/// involving constants, fold it.
+Constant *ScalarEvolutionsImpl::
+getConstantEvolutionLoopExitValue(PHINode *PN, uint64_t Its, const Loop *L) {
+  std::map<PHINode*, Constant*>::iterator I =
+    ConstantEvolutionLoopExitValue.find(PN);
+  if (I != ConstantEvolutionLoopExitValue.end())
+    return I->second;
 
-    return 0;
-  case Instruction::GetElementPtr:
-    Constant *Base = Operands[0];
-    Operands.erase(Operands.begin());
-    return ConstantExpr::getGetElementPtr(Base, Operands);
+  if (Its > MaxBruteForceIterations) 
+    return ConstantEvolutionLoopExitValue[PN] = 0;  // Not going to evaluate it.
+
+  Constant *&RetVal = ConstantEvolutionLoopExitValue[PN];
+
+  // Since the loop is canonicalized, the PHI node must have two entries.  One
+  // entry must be a constant (coming in from outside of the loop), and the
+  // second must be derived from the same PHI.
+  bool SecondIsBackedge = L->contains(PN->getIncomingBlock(1));
+  Constant *StartCST =
+    dyn_cast<Constant>(PN->getIncomingValue(!SecondIsBackedge));
+  if (StartCST == 0)
+    return RetVal = 0;  // Must be a constant.
+
+  Value *BEValue = PN->getIncomingValue(SecondIsBackedge);
+  PHINode *PN2 = getConstantEvolvingPHI(BEValue, L);
+  if (PN2 != PN)
+    return RetVal = 0;  // Not derived from same PHI.
+
+  // Execute the loop symbolically to determine the exit value.
+  unsigned IterationNum = 0;
+  unsigned NumIterations = Its;
+  if (NumIterations != Its)
+    return RetVal = 0;  // More than 2^32 iterations??
+
+  for (Constant *PHIVal = StartCST; ; ++IterationNum) {
+    if (IterationNum == NumIterations)
+      return RetVal = PHIVal;  // Got exit value!
+
+    // Compute the value of the PHI node for the next iteration.
+    Constant *NextPHI = EvaluateExpression(BEValue, PHIVal);
+    if (NextPHI == PHIVal)
+      return RetVal = NextPHI;  // Stopped evolving!
+    if (NextPHI == 0)
+      return 0;        // Couldn't evaluate!
+    PHIVal = NextPHI;
   }
-  return 0;
 }
 
-
 /// ComputeIterationCountExhaustively - If the trip is known to execute a
 /// constant number of times (the condition evolves only from constants),
 /// try to evaluate a few iterations of the loop until we get the exit
@@ -1679,16 +1754,18 @@
     ConstantBool *CondVal =
       dyn_cast_or_null<ConstantBool>(EvaluateExpression(Cond, PHIVal));
     if (!CondVal) return UnknownValue;     // Couldn't symbolically evaluate.
+
     if (CondVal->getValue() == ExitWhen) {
+      ConstantEvolutionLoopExitValue[PN] = PHIVal;
       ++NumBruteForceTripCountsComputed;
       return SCEVConstant::get(ConstantUInt::get(Type::UIntTy, IterationNum));
     }
     
-    // Otherwise, compute the value of the PHI node for the next iteration.
-    Constant *Next = EvaluateExpression(BEValue, PHIVal);
-    if (Next == 0 || Next == PHIVal)
+    // Compute the value of the PHI node for the next iteration.
+    Constant *NextPHI = EvaluateExpression(BEValue, PHIVal);
+    if (NextPHI == 0 || NextPHI == PHIVal)
       return UnknownValue;  // Couldn't evaluate or not making progress...
-    PHIVal = Next;
+    PHIVal = NextPHI;
   }
 
   // Too many iterations were needed to evaluate.
@@ -1701,7 +1778,67 @@
 SCEVHandle ScalarEvolutionsImpl::getSCEVAtScope(SCEV *V, const Loop *L) {
   // FIXME: this should be turned into a virtual method on SCEV!
 
-  if (isa<SCEVConstant>(V) || isa<SCEVUnknown>(V)) return V;
+  if (isa<SCEVConstant>(V)) return V;
+  
+  // If this instruction is evolves from a constant-evolving PHI, compute the
+  // exit value from the loop without using SCEVs.
+  if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(V)) {
+    if (Instruction *I = dyn_cast<Instruction>(SU->getValue())) {
+      const Loop *LI = this->LI[I->getParent()];
+      if (LI && LI->getParentLoop() == L)  // Looking for loop exit value.
+        if (PHINode *PN = dyn_cast<PHINode>(I))
+          if (PN->getParent() == LI->getHeader()) {
+            // Okay, there is no closed form solution for the PHI node.  Check
+            // to see if the loop that contains it has a known iteration count.
+            // If so, we may be able to force computation of the exit value.
+            SCEVHandle IterationCount = getIterationCount(LI);
+            if (SCEVConstant *ICC = dyn_cast<SCEVConstant>(IterationCount)) {
+              // Okay, we know how many times the containing loop executes.  If
+              // this is a constant evolving PHI node, get the final value at
+              // the specified iteration number.
+              Constant *RV = getConstantEvolutionLoopExitValue(PN,
+                                               ICC->getValue()->getRawValue(),
+                                                               LI);
+              if (RV) return SCEVUnknown::get(RV);
+            }
+          }
+
+      // Okay, this is a some expression that we cannot symbolically evaluate
+      // into a SCEV.  Check to see if it's possible to symbolically evaluate
+      // the arguments into constants, and if see, try to constant propagate the
+      // result.  This is particularly useful for computing loop exit values.
+      if (CanConstantFold(I)) {
+        std::vector<Constant*> Operands;
+        Operands.reserve(I->getNumOperands());
+        for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
+          Value *Op = I->getOperand(i);
+          if (Constant *C = dyn_cast<Constant>(Op)) {
+            Operands.push_back(C);
+          } else if (GlobalValue *GV = dyn_cast<GlobalValue>(Op)) {
+            Operands.push_back(ConstantPointerRef::get(GV));
+          } else {
+            SCEVHandle OpV = getSCEVAtScope(getSCEV(Op), L);
+            if (SCEVConstant *SC = dyn_cast<SCEVConstant>(OpV))
+              Operands.push_back(ConstantExpr::getCast(SC->getValue(),
+                                                       Op->getType()));
+            else if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(OpV)) {
+              if (Constant *C = dyn_cast<Constant>(SU->getValue()))
+                Operands.push_back(ConstantExpr::getCast(C, Op->getType()));
+              else
+                return V;
+            } else {
+              return V;
+            }
+          }
+        }
+        return SCEVUnknown::get(ConstantFold(I, Operands));
+      }
+    }
+
+    // This is some other type of SCEVUnknown, just return it.
+    return V;
+  }
+
   if (SCEVCommutativeExpr *Comm = dyn_cast<SCEVCommutativeExpr>(V)) {
     // Avoid performing the look-up in the common case where the specified
     // expression has no loop-variant portions.
@@ -1711,7 +1848,7 @@
         if (OpAtScope == UnknownValue) return UnknownValue;
         // Okay, at least one of these operands is loop variant but might be
         // foldable.  Build a new instance of the folded commutative expression.
-        std::vector<SCEVHandle> NewOps(Comm->op_begin(), Comm->op_begin()+i-1);
+        std::vector<SCEVHandle> NewOps(Comm->op_begin(), Comm->op_begin()+i);
         NewOps.push_back(OpAtScope);
 
         for (++i; i != e; ++i) {





More information about the llvm-commits mailing list