[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu Aug 4 12:08:27 PDT 2005



Changes in directory llvm/lib/Transforms/Scalar:

LoopStrengthReduce.cpp updated: 1.32 -> 1.33
---
Log message:

Teach LSR about loop-variant expressions, such as loops like this:

  for (i = 0; i < N; ++i)
    A[i][foo()] = 0;

here we still want to strength reduce the A[i] part, even though foo() is
l-v.

This also simplifies some of the 'CanReduce' logic.

This implements Transforms/LoopStrengthReduce/ops_after_indvar.ll



---
Diffs of the changes:  (+93 -68)

 LoopStrengthReduce.cpp |  161 ++++++++++++++++++++++++++++---------------------
 1 files changed, 93 insertions(+), 68 deletions(-)


Index: llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
diff -u llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.32 llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.33
--- llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp:1.32	Thu Aug  4 13:13:56 2005
+++ llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp	Thu Aug  4 14:08:16 2005
@@ -166,8 +166,10 @@
     // Do not insert casts into the middle of PHI node blocks.
     while (isa<PHINode>(InsertPt)) ++InsertPt;
   }
-    
-  return New = new CastInst(V, UIntPtrTy, V->getName(), InsertPt);
+  
+  New = new CastInst(V, UIntPtrTy, V->getName(), InsertPt);
+  DeadInsts.insert(cast<Instruction>(New));
+  return New;
 }
 
 
@@ -191,30 +193,6 @@
 }
 
 
-/// CanReduceSCEV - Return true if we can strength reduce this scalar evolution
-/// in the specified loop.
-static bool CanReduceSCEV(const SCEVHandle &SH, Loop *L) {
-  SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(SH);
-  if (!AddRec || AddRec->getLoop() != L) return false;
-
-  // FIXME: Generalize to non-affine IV's.
-  if (!AddRec->isAffine()) return false;
-
-  // FIXME: generalize to IV's with more complex strides (must emit stride
-  // expression outside of loop!)
-  if (isa<SCEVConstant>(AddRec->getOperand(1)))
-    return true;
-
-  // We handle steps by unsigned values, because we know we won't have to insert
-  // a cast for them.
-  if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(AddRec->getOperand(1)))
-    if (SU->getValue()->getType()->isUnsigned())
-      return true;
-
-  // Otherwise, no, we can't handle it yet.
-  return false;
-}
-
 /// GetExpressionSCEV - Compute and return the SCEV for the specified
 /// instruction.
 SCEVHandle LoopStrengthReduce::GetExpressionSCEV(Instruction *Exp, Loop *L) {
@@ -243,7 +221,9 @@
       GEPVal = SCEVAddExpr::get(GEPVal,
                                 SCEVUnknown::getIntegerSCEV(Offset, UIntPtrTy));
     } else {
-      SCEVHandle Idx = SE->getSCEV(getCastedVersionOf(GEP->getOperand(i)));
+      Value *OpVal = getCastedVersionOf(GEP->getOperand(i));
+      SCEVHandle Idx = SE->getSCEV(OpVal);
+
       uint64_t TypeSize = TD->getTypeSize(GTI.getIndexedType());
       if (TypeSize != 1)
         Idx = SCEVMulExpr::get(Idx,
@@ -253,10 +233,58 @@
     }
   }
 
-  //assert(CanReduceSCEV(GEPVal, L) && "Cannot reduce this use of IV?");  
   return GEPVal;
 }
 
+/// getSCEVStartAndStride - Compute the start and stride of this expression,
+/// returning false if the expression is not a start/stride pair, or true if it
+/// is.  The stride must be a loop invariant expression, but the start may be
+/// a mix of loop invariant and loop variant expressions.
+static bool getSCEVStartAndStride(const SCEVHandle &SH, Loop *L,
+                                  SCEVHandle &Start, Value *&Stride) {
+  SCEVHandle TheAddRec = Start;   // Initialize to zero.
+
+  // If the outer level is an AddExpr, the operands are all start values except
+  // for a nested AddRecExpr.
+  if (SCEVAddExpr *AE = dyn_cast<SCEVAddExpr>(SH)) {
+    for (unsigned i = 0, e = AE->getNumOperands(); i != e; ++i)
+      if (SCEVAddRecExpr *AddRec =
+             dyn_cast<SCEVAddRecExpr>(AE->getOperand(i))) {
+        if (AddRec->getLoop() == L)
+          TheAddRec = SCEVAddExpr::get(AddRec, TheAddRec);
+        else
+          return false;  // Nested IV of some sort?
+      } else {
+        Start = SCEVAddExpr::get(Start, AE->getOperand(i));
+      }
+        
+  } else if (SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(SH)) {
+    TheAddRec = SH;
+  } else {
+    return false;  // not analyzable.
+  }
+  
+  SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(TheAddRec);
+  if (!AddRec || AddRec->getLoop() != L) return false;
+  
+  // FIXME: Generalize to non-affine IV's.
+  if (!AddRec->isAffine()) return false;
+
+  Start = SCEVAddExpr::get(Start, AddRec->getOperand(0));
+  
+  // FIXME: generalize to IV's with more complex strides (must emit stride
+  // expression outside of loop!)
+  if (!isa<SCEVConstant>(AddRec->getOperand(1)))
+    return false;
+  
+  SCEVConstant *StrideC = cast<SCEVConstant>(AddRec->getOperand(1));
+  Stride = StrideC->getValue();
+
+  assert(Stride->getType()->isUnsigned() &&
+         "Constants should be canonicalized to unsigned!");
+  return true;
+}
+
 /// AddUsersIfInteresting - Inspect the specified instruction.  If it is a
 /// reducible SCEV, recursively add its users to the IVUsesByStride set and
 /// return true.  Otherwise, return false.
@@ -266,25 +294,16 @@
   if (!Processed.insert(I).second)
     return true;    // Instruction already handled.
   
+  // Get the symbolic expression for this instruction.
   SCEVHandle ISE = GetExpressionSCEV(I, L);
-  if (!CanReduceSCEV(ISE, L))
-    return false;  // Non-analyzable expression, e.g. a rem instr.
+  if (isa<SCEVCouldNotCompute>(ISE)) return false;
+  
+  // Get the start and stride for this expression.
+  SCEVHandle Start = SCEVUnknown::getIntegerSCEV(0, ISE->getType());
+  Value *Stride = 0;
+  if (!getSCEVStartAndStride(ISE, L, Start, Stride))
+    return false;  // Non-reducible symbolic expression, bail out.
   
-  // NOT SAFE with generalized EXPRS
-  SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(ISE);
-  SCEVHandle Start = AR->getStart();
-
-  // Get the step value, canonicalizing to an unsigned integer type so that
-  // lookups in the map will match.
-  Value *Step = 0;   // Step of ISE.
-  if (SCEVConstant *SC = dyn_cast<SCEVConstant>(AR->getOperand(1)))
-    /// Always get the step value as an unsigned value.
-    Step = ConstantExpr::getCast(SC->getValue(),
-                               SC->getValue()->getType()->getUnsignedVersion());
-  else
-    Step = cast<SCEVUnknown>(AR->getOperand(1))->getValue();
-  assert(Step->getType()->isUnsigned() && "Bad step value!");
-
   for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E;++UI){
     Instruction *User = cast<Instruction>(*UI);
 
@@ -294,20 +313,21 @@
 
     // If this is an instruction defined in a nested loop, or outside this loop,
     // don't recurse into it.
+    bool AddUserToIVUsers = false;
     if (LI->getLoopFor(User->getParent()) != L) {
       DEBUG(std::cerr << "FOUND USER in nested loop: " << *User
             << "   OF SCEV: " << *ISE << "\n");
-      
-      // Okay, we found a user that we cannot reduce.  Analyze the instruction
-      // and decide what to do with it.
-      IVUsesByStride[Step].addUser(Start, User, I);
+      AddUserToIVUsers = true;
     } else if (!AddUsersIfInteresting(User, L, Processed)) {
       DEBUG(std::cerr << "FOUND USER: " << *User
             << "   OF SCEV: " << *ISE << "\n");
+      AddUserToIVUsers = true;
+    }
 
+    if (AddUserToIVUsers) {
       // Okay, we found a user that we cannot reduce.  Analyze the instruction
       // and decide what to do with it.
-      IVUsesByStride[Step].addUser(Start, User, I);
+      IVUsesByStride[Stride].addUser(Start, User, I);
     }
   }
   return true;
@@ -372,28 +392,27 @@
 
 /// GetImmediateValues - Look at Val, and pull out any additions of constants
 /// that can fit into the immediate field of instructions in the target.
-static SCEVHandle GetImmediateValues(SCEVHandle Val, bool isAddress) {
-  if (!isAddress)
-    return SCEVUnknown::getIntegerSCEV(0, Val->getType());
-  if (isTargetConstant(Val))
+static SCEVHandle GetImmediateValues(SCEVHandle Val, bool isAddress, Loop *L) {
+  if (isAddress && isTargetConstant(Val))
     return Val;
 
   if (SCEVAddExpr *SAE = dyn_cast<SCEVAddExpr>(Val)) {
     unsigned i = 0;
-    for (; i != SAE->getNumOperands(); ++i)
-      if (isTargetConstant(SAE->getOperand(i))) {
-        SCEVHandle ImmVal = SAE->getOperand(i);
+    SCEVHandle Imm = SCEVUnknown::getIntegerSCEV(0, Val->getType());
 
-        // If there are any other immediates that we can handle here, pull them
-        // out too.
-        for (++i; i != SAE->getNumOperands(); ++i)
-          if (isTargetConstant(SAE->getOperand(i)))
-            ImmVal = SCEVAddExpr::get(ImmVal, SAE->getOperand(i));
-        return ImmVal;
+    for (; i != SAE->getNumOperands(); ++i)
+      if (isAddress && isTargetConstant(SAE->getOperand(i))) {
+        Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
+      } else if (!SAE->getOperand(i)->isLoopInvariant(L)) {
+        // If this is a loop-variant expression, it must stay in the immediate
+        // field of the expression.
+        Imm = SCEVAddExpr::get(Imm, SAE->getOperand(i));
       }
+        
+    return Imm;
   } else if (SCEVAddRecExpr *SARE = dyn_cast<SCEVAddRecExpr>(Val)) {
     // Try to pull immediates out of the start value of nested addrec's.
-    return GetImmediateValues(SARE->getStart(), isAddress);
+    return GetImmediateValues(SARE->getStart(), isAddress, L);
   }
 
   return SCEVUnknown::getIntegerSCEV(0, Val->getType());
@@ -427,10 +446,16 @@
   // instructions.  If we can represent anything there, move it to the imm
   // fields of the BasedUsers.
   for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) {
-    bool isAddress = isa<LoadInst>(UsersToProcess[i].second.Inst) ||
-                     isa<StoreInst>(UsersToProcess[i].second.Inst);
-    UsersToProcess[i].second.Imm = GetImmediateValues(UsersToProcess[i].first,
-                                                      isAddress);
+    // Addressing modes can be folded into loads and stores.  Be careful that
+    // the store is through the expression, not of the expression though.
+    bool isAddress = isa<LoadInst>(UsersToProcess[i].second.Inst);
+    if (StoreInst *SI = dyn_cast<StoreInst>(UsersToProcess[i].second.Inst))
+      if (SI->getOperand(1) == UsersToProcess[i].second.OperandValToReplace)
+        isAddress = true;
+          
+    UsersToProcess[i].second.Imm =
+          GetImmediateValues(UsersToProcess[i].first, isAddress, L);
+                                                        
     UsersToProcess[i].first = SCEV::getMinusSCEV(UsersToProcess[i].first,
                                                  UsersToProcess[i].second.Imm);
 






More information about the llvm-commits mailing list