[llvm-commits] [llvm] r72093 - in /llvm/trunk: include/llvm/Analysis/ScalarEvolution.h include/llvm/Analysis/ScalarEvolutionExpander.h lib/Analysis/ScalarEvolution.cpp lib/Analysis/ScalarEvolutionExpander.cpp lib/Transforms/Scalar/IndVarSimplify.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp lib/Transforms/Utils/AddrModeMatcher.cpp test/Transforms/IndVarSimplify/preserve-gep.ll test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll

Dan Gohman gohman at apple.com
Mon May 18 19:15:55 PDT 2009


Author: djg
Date: Mon May 18 21:15:55 2009
New Revision: 72093

URL: http://llvm.org/viewvc/llvm-project?rev=72093&view=rev
Log:
Teach SCEVExpander to expand arithmetic involving pointers into GEP
instructions. It attempts to create high-level multi-operand GEPs,
though in cases where this isn't possible it falls back to casting
the pointer to i8* and emitting a GEP with that. Using GEP instructions
instead of ptrtoint+arithmetic+inttoptr helps pointer analyses that
don't use ScalarEvolution, such as BasicAliasAnalysis.

Also, make the AddrModeMatcher more aggressive in handling GEPs.
Previously it assumed that operand 0 of a GEP would require a register
in almost all cases. It now does extra checking and can do more
matching if operand 0 of the GEP is foldable. This fixes a problem
that was exposed by SCEVExpander using GEPs.

Added:
    llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep.ll
Modified:
    llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
    llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
    llvm/trunk/lib/Transforms/Utils/AddrModeMatcher.cpp
    llvm/trunk/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Mon May 18 21:15:55 2009
@@ -213,6 +213,7 @@
   ///
   class ScalarEvolution : public FunctionPass {
     friend class SCEVCallbackVH;
+    friend class SCEVExpander;
 
     /// F - The function we are analyzing.
     ///

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolutionExpander.h Mon May 18 21:15:55 2009
@@ -28,7 +28,6 @@
   /// memory.
   struct SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> {
     ScalarEvolution &SE;
-    LoopInfo &LI;
     std::map<SCEVHandle, Value*> InsertedExpressions;
     std::set<Value*> InsertedValues;
 
@@ -36,10 +35,8 @@
 
     friend struct SCEVVisitor<SCEVExpander, Value*>;
   public:
-    SCEVExpander(ScalarEvolution &se, LoopInfo &li)
-      : SE(se), LI(li) {}
-
-    LoopInfo &getLoopInfo() const { return LI; }
+    explicit SCEVExpander(ScalarEvolution &se)
+      : SE(se) {}
 
     /// clear - Erase the contents of the InsertedExpressions map so that users
     /// trying to expand the same expression into multiple BasicBlocks or
@@ -83,8 +80,9 @@
 
     /// expandCodeFor - Insert code to directly compute the specified SCEV
     /// expression into the program.  The inserted code is inserted into the
-    /// SCEVExpander's current insertion point.
-    Value *expandCodeFor(SCEVHandle SH, const Type *Ty);
+    /// SCEVExpander's current insertion point. If a type is specified, the
+    /// result will be expanded to have that type, with a cast if necessary.
+    Value *expandCodeFor(SCEVHandle SH, const Type *Ty = 0);
 
     /// expandCodeFor - Insert code to directly compute the specified SCEV
     /// expression into the program.  The inserted code is inserted into the
@@ -110,6 +108,11 @@
                        Value *RHS, BasicBlock::iterator InsertPt);
 
   private:
+    /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP
+    /// instead of using ptrtoint+arithmetic+inttoptr.
+    Value *expandAddToGEP(const SCEVAddExpr *S, const PointerType *PTy,
+                          const Type *Ty, Value *V);
+
     Value *expand(const SCEV *S);
 
     Value *visitConstant(const SCEVConstant *S) {

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon May 18 21:15:55 2009
@@ -456,6 +456,13 @@
       if (const SCEVUnknown *LU = dyn_cast<SCEVUnknown>(LHS)) {
         const SCEVUnknown *RU = cast<SCEVUnknown>(RHS);
 
+        // Order pointer values after integer values. This helps SCEVExpander
+        // form GEPs.
+        if (isa<PointerType>(LU->getType()) && !isa<PointerType>(RU->getType()))
+          return false;
+        if (isa<PointerType>(RU->getType()) && !isa<PointerType>(LU->getType()))
+          return true;
+
         // Compare getValueID values.
         if (LU->getValue()->getValueID() != RU->getValue()->getValueID())
           return LU->getValue()->getValueID() < RU->getValue()->getValueID();

Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Mon May 18 21:15:55 2009
@@ -15,6 +15,7 @@
 
 #include "llvm/Analysis/ScalarEvolutionExpander.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Target/TargetData.h"
 using namespace llvm;
 
 /// InsertCastOfTo - Insert a cast of V to the specified type, doing what
@@ -130,10 +131,9 @@
     BasicBlock::iterator IP = InsertPt;
     --IP;
     for (; ScanLimit; --IP, --ScanLimit) {
-      if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(IP))
-        if (BinOp->getOpcode() == Opcode && BinOp->getOperand(0) == LHS &&
-            BinOp->getOperand(1) == RHS)
-          return BinOp;
+      if (IP->getOpcode() == (unsigned)Opcode && IP->getOperand(0) == LHS &&
+          IP->getOperand(1) == RHS)
+        return IP;
       if (IP == BlockBegin) break;
     }
   }
@@ -144,9 +144,156 @@
   return BO;
 }
 
+/// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP
+/// instead of using ptrtoint+arithmetic+inttoptr.
+Value *SCEVExpander::expandAddToGEP(const SCEVAddExpr *S,
+                                    const PointerType *PTy,
+                                    const Type *Ty,
+                                    Value *V) {
+  const Type *ElTy = PTy->getElementType();
+  SmallVector<Value *, 4> GepIndices;
+  std::vector<SCEVHandle> Ops = S->getOperands();
+  bool AnyNonZeroIndices = false;
+  Ops.pop_back();
+
+  // Decend down the pointer's type and attempt to convert the other
+  // operands into GEP indices, at each level. The first index in a GEP
+  // indexes into the array implied by the pointer operand; the rest of
+  // the indices index into the element or field type selected by the
+  // preceding index.
+  for (;;) {
+    APInt ElSize = APInt(SE.getTypeSizeInBits(Ty),
+                         ElTy->isSized() ?  SE.TD->getTypeAllocSize(ElTy) : 0);
+    std::vector<SCEVHandle> NewOps;
+    std::vector<SCEVHandle> ScaledOps;
+    for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
+      if (ElSize != 0) {
+        if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Ops[i]))
+          if (!C->getValue()->getValue().srem(ElSize)) {
+            ConstantInt *CI =
+              ConstantInt::get(C->getValue()->getValue().sdiv(ElSize));
+            SCEVHandle Div = SE.getConstant(CI);
+            ScaledOps.push_back(Div);
+            continue;
+          }
+        if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Ops[i]))
+          if (const SCEVConstant *C = dyn_cast<SCEVConstant>(M->getOperand(0)))
+            if (C->getValue()->getValue() == ElSize) {
+              for (unsigned j = 1, f = M->getNumOperands(); j != f; ++j)
+                ScaledOps.push_back(M->getOperand(j));
+              continue;
+            }
+        if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(Ops[i]))
+          if (BinaryOperator *BO = dyn_cast<BinaryOperator>(U->getValue()))
+            if (BO->getOpcode() == Instruction::Mul)
+              if (ConstantInt *CI = dyn_cast<ConstantInt>(BO->getOperand(1)))
+                if (CI->getValue() == ElSize) {
+                  ScaledOps.push_back(SE.getUnknown(BO->getOperand(0)));
+                  continue;
+                }
+        if (ElSize == 1) {
+          ScaledOps.push_back(Ops[i]);
+          continue;
+        }
+      }
+      NewOps.push_back(Ops[i]);
+    }
+    Ops = NewOps;
+    AnyNonZeroIndices |= !ScaledOps.empty();
+    Value *Scaled = ScaledOps.empty() ?
+                    Constant::getNullValue(Ty) :
+                    expandCodeFor(SE.getAddExpr(ScaledOps), Ty);
+    GepIndices.push_back(Scaled);
+
+    // Collect struct field index operands.
+    if (!Ops.empty())
+      while (const StructType *STy = dyn_cast<StructType>(ElTy)) {
+        if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Ops[0]))
+          if (SE.getTypeSizeInBits(C->getType()) <= 64) {
+            const StructLayout &SL = *SE.TD->getStructLayout(STy);
+            uint64_t FullOffset = C->getValue()->getZExtValue();
+            if (FullOffset < SL.getSizeInBytes()) {
+              unsigned ElIdx = SL.getElementContainingOffset(FullOffset);
+              GepIndices.push_back(ConstantInt::get(Type::Int32Ty, ElIdx));
+              ElTy = STy->getTypeAtIndex(ElIdx);
+              Ops[0] =
+                SE.getConstant(ConstantInt::get(Ty,
+                                                FullOffset -
+                                                  SL.getElementOffset(ElIdx)));
+              AnyNonZeroIndices = true;
+              continue;
+            }
+          }
+        break;
+      }
+
+    if (const ArrayType *ATy = dyn_cast<ArrayType>(ElTy)) {
+      ElTy = ATy->getElementType();
+      continue;
+    }
+    break;
+  }
+
+  // If none of the operands were convertable to proper GEP indices, cast
+  // the base to i8* and do an ugly getelementptr with that. It's still
+  // better than ptrtoint+arithmetic+inttoptr at least.
+  if (!AnyNonZeroIndices) {
+    V = InsertNoopCastOfTo(V,
+                           Type::Int8Ty->getPointerTo(PTy->getAddressSpace()));
+    Value *Idx = expand(SE.getAddExpr(Ops));
+    Idx = InsertNoopCastOfTo(Idx, Ty);
+
+    // Fold a GEP with constant operands.
+    if (Constant *CLHS = dyn_cast<Constant>(V))
+      if (Constant *CRHS = dyn_cast<Constant>(Idx))
+        return ConstantExpr::get(Instruction::GetElementPtr, CLHS, CRHS);
+
+    // Do a quick scan to see if we have this GEP nearby.  If so, reuse it.
+    unsigned ScanLimit = 6;
+    BasicBlock::iterator BlockBegin = InsertPt->getParent()->begin();
+    if (InsertPt != BlockBegin) {
+      // Scanning starts from the last instruction before InsertPt.
+      BasicBlock::iterator IP = InsertPt;
+      --IP;
+      for (; ScanLimit; --IP, --ScanLimit) {
+        if (IP->getOpcode() == Instruction::GetElementPtr &&
+            IP->getOperand(0) == V && IP->getOperand(1) == Idx)
+          return IP;
+        if (IP == BlockBegin) break;
+      }
+    }
+
+    Value *GEP = GetElementPtrInst::Create(V, Idx, "scevgep", InsertPt);
+    InsertedValues.insert(GEP);
+    return GEP;
+  }
+
+  // Insert a pretty getelementptr.
+  Value *GEP = GetElementPtrInst::Create(V,
+                                         GepIndices.begin(),
+                                         GepIndices.end(),
+                                         "scevgep", InsertPt);
+  Ops.push_back(SE.getUnknown(GEP));
+  InsertedValues.insert(GEP);
+  return expand(SE.getAddExpr(Ops));
+}
+
 Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
   const Type *Ty = SE.getEffectiveSCEVType(S->getType());
   Value *V = expand(S->getOperand(S->getNumOperands()-1));
+
+  // Turn things like ptrtoint+arithmetic+inttoptr into GEP. This helps
+  // BasicAliasAnalysis analyze the result. However, it suffers from the
+  // underlying bug described in PR2831. Addition in LLVM currently always
+  // has two's complement wrapping guaranteed. However, the semantics for
+  // getelementptr overflow are ambiguous. In the common case though, this
+  // expansion gets used when a GEP in the original code has been converted
+  // into integer arithmetic, in which case the resulting code will be no
+  // more undefined than it was originally.
+  if (SE.TD)
+    if (const PointerType *PTy = dyn_cast<PointerType>(V->getType()))
+      return expandAddToGEP(S, PTy, Ty, V);
+
   V = InsertNoopCastOfTo(V, Ty);
 
   // Emit a bunch of add instructions
@@ -157,7 +304,7 @@
   }
   return V;
 }
-    
+
 Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) {
   const Type *Ty = SE.getEffectiveSCEVType(S->getType());
   int FirstOp = 0;  // Set if we should emit a subtract.
@@ -206,15 +353,10 @@
 
   // {X,+,F} --> X + {0,+,F}
   if (!S->getStart()->isZero()) {
-    Value *Start = expand(S->getStart());
-    Start = InsertNoopCastOfTo(Start, Ty);
-    std::vector<SCEVHandle> NewOps(S->op_begin(), S->op_end());
+    std::vector<SCEVHandle> NewOps(S->getOperands());
     NewOps[0] = SE.getIntegerSCEV(0, Ty);
     Value *Rest = expand(SE.getAddRecExpr(NewOps, L));
-    Rest = InsertNoopCastOfTo(Rest, Ty);
-
-    // FIXME: look for an existing add to use.
-    return InsertBinop(Instruction::Add, Rest, Start, InsertPt);
+    return expand(SE.getAddExpr(S->getStart(), SE.getUnknown(Rest)));
   }
 
   // {0,+,1} --> Insert a canonical induction variable into the loop!
@@ -265,7 +407,7 @@
     // point loop.  If we can, move the multiply to the outer most loop that it
     // is safe to be in.
     BasicBlock::iterator MulInsertPt = getInsertionPoint();
-    Loop *InsertPtLoop = LI.getLoopFor(MulInsertPt->getParent());
+    Loop *InsertPtLoop = SE.LI->getLoopFor(MulInsertPt->getParent());
     if (InsertPtLoop != L && InsertPtLoop &&
         L->contains(InsertPtLoop->getHeader())) {
       do {
@@ -363,10 +505,13 @@
 
 Value *SCEVExpander::expandCodeFor(SCEVHandle SH, const Type *Ty) {
   // Expand the code for this SCEV.
-  assert(SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(SH->getType()) &&
-         "non-trivial casts should be done with the SCEVs directly!");
   Value *V = expand(SH);
-  return InsertNoopCastOfTo(V, Ty);
+  if (Ty) {
+    assert(SE.getTypeSizeInBits(Ty) == SE.getTypeSizeInBits(SH->getType()) &&
+           "non-trivial casts should be done with the SCEVs directly!");
+    V = InsertNoopCastOfTo(V, Ty);
+  }
+  return V;
 }
 
 Value *SCEVExpander::expand(const SCEV *S) {

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Mon May 18 21:15:55 2009
@@ -172,7 +172,7 @@
 
   // Expand the code for the iteration count into the preheader of the loop.
   BasicBlock *Preheader = L->getLoopPreheader();
-  Value *ExitCnt = Rewriter.expandCodeFor(RHS, IndVar->getType(),
+  Value *ExitCnt = Rewriter.expandCodeFor(RHS, CmpIndVar->getType(),
                                           Preheader->getTerminator());
 
   // Insert a new icmp_ne or icmp_eq instruction before the branch.
@@ -218,7 +218,7 @@
 
   // Scan all of the instructions in the loop, looking at those that have
   // extra-loop users and which are recurrences.
-  SCEVExpander Rewriter(*SE, *LI);
+  SCEVExpander Rewriter(*SE);
 
   // We insert the code into the preheader of the loop if the loop contains
   // multiple exit blocks, or in the exit block if there is exactly one.
@@ -386,7 +386,7 @@
   }
 
   // Create a rewriter object which we'll use to transform the code with.
-  SCEVExpander Rewriter(*SE, *LI);
+  SCEVExpander Rewriter(*SE);
 
   // Now that we know the largest of of the induction variable expressions
   // in this loop, insert a canonical induction variable of the largest size.
@@ -478,7 +478,7 @@
         BasicBlock::iterator I = Rewriter.getInsertionPoint();
         // Expand loop-invariant values in the loop preheader. They will
         // be sunk to the exit block later, if possible.
-          NewVal =
+        NewVal =
           Rewriter.expandCodeFor(AR, LargestType,
                                  L->getLoopPreheader()->getTerminator());
         Rewriter.setInsertionPoint(I);
@@ -523,7 +523,7 @@
         NewAR = SE->getAddExpr(NewAR, PromotedOffset);
 
         // Expand the addrec into instructions.
-        Value *V = Rewriter.expandCodeFor(NewAR, LargestType);
+        Value *V = Rewriter.expandCodeFor(NewAR);
 
         // Insert an explicit cast if necessary to truncate the value
         // down to the original stride type. This is done outside of
@@ -533,7 +533,7 @@
           if (SE->getTypeSizeInBits(IVTy) != SE->getTypeSizeInBits(LargestType))
             NewAR = SE->getTruncateExpr(NewAR, IVTy);
           if (Rewriter.isInsertedExpression(NewAR))
-            V = Rewriter.expandCodeFor(NewAR, IVTy);
+            V = Rewriter.expandCodeFor(NewAR);
           else {
             V = Rewriter.InsertCastOfTo(CastInst::getCastOpcode(V, false,
                                                                 IVTy, false),

Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Mon May 18 21:15:55 2009
@@ -367,12 +367,14 @@
     void RewriteInstructionToUseNewBase(const SCEVHandle &NewBase,
                                         Instruction *InsertPt,
                                        SCEVExpander &Rewriter, Loop *L, Pass *P,
+                                        LoopInfo &LI,
                                         SmallVectorImpl<WeakVH> &DeadInsts);
     
     Value *InsertCodeForBaseAtPosition(const SCEVHandle &NewBase, 
                                        const Type *Ty,
                                        SCEVExpander &Rewriter,
-                                       Instruction *IP, Loop *L);
+                                       Instruction *IP, Loop *L,
+                                       LoopInfo &LI);
     void dump() const;
   };
 }
@@ -386,12 +388,12 @@
 Value *BasedUser::InsertCodeForBaseAtPosition(const SCEVHandle &NewBase, 
                                               const Type *Ty,
                                               SCEVExpander &Rewriter,
-                                              Instruction *IP, Loop *L) {
+                                              Instruction *IP, Loop *L,
+                                              LoopInfo &LI) {
   // Figure out where we *really* want to insert this code.  In particular, if
   // the user is inside of a loop that is nested inside of L, we really don't
   // want to insert this expression before the user, we'd rather pull it out as
   // many loops as possible.
-  LoopInfo &LI = Rewriter.getLoopInfo();
   Instruction *BaseInsertPt = IP;
   
   // Figure out the most-nested loop that IP is in.
@@ -405,8 +407,7 @@
       InsertLoop = InsertLoop->getParentLoop();
     }
   
-  Value *Base = Rewriter.expandCodeFor(NewBase, NewBase->getType(),
-                                       BaseInsertPt);
+  Value *Base = Rewriter.expandCodeFor(NewBase, 0, BaseInsertPt);
 
   SCEVHandle NewValSCEV = SE->getUnknown(Base);
 
@@ -439,6 +440,7 @@
 void BasedUser::RewriteInstructionToUseNewBase(const SCEVHandle &NewBase,
                                                Instruction *NewBasePt,
                                       SCEVExpander &Rewriter, Loop *L, Pass *P,
+                                      LoopInfo &LI,
                                       SmallVectorImpl<WeakVH> &DeadInsts) {
   if (!isa<PHINode>(Inst)) {
     // By default, insert code at the user instruction.
@@ -468,7 +470,7 @@
     }
     Value *NewVal = InsertCodeForBaseAtPosition(NewBase,
                                                 OperandValToReplace->getType(),
-                                                Rewriter, InsertPt, L);
+                                                Rewriter, InsertPt, L, LI);
     // Replace the use of the operand Value with the new Phi we just created.
     Inst->replaceUsesOfWith(OperandValToReplace, NewVal);
 
@@ -527,7 +529,7 @@
                                 PN->getIncomingBlock(i)->getTerminator() :
                                 OldLoc->getParent()->getTerminator();
         Code = InsertCodeForBaseAtPosition(NewBase, PN->getType(),
-                                           Rewriter, InsertPt, L);
+                                           Rewriter, InsertPt, L, LI);
 
         DOUT << "      Changing PHI use to ";
         DEBUG(WriteAsOperand(*DOUT, Code, /*PrintType=*/false));
@@ -1580,8 +1582,8 @@
        << *Stride << ":\n"
        << "  Common base: " << *CommonExprs << "\n";
 
-  SCEVExpander Rewriter(*SE, *LI);
-  SCEVExpander PreheaderRewriter(*SE, *LI);
+  SCEVExpander Rewriter(*SE);
+  SCEVExpander PreheaderRewriter(*SE);
 
   BasicBlock  *Preheader = L->getLoopPreheader();
   Instruction *PreInsertPt = Preheader->getTerminator();
@@ -1636,8 +1638,7 @@
     // Emit the code for Base into the preheader.
     Value *BaseV = 0;
     if (!Base->isZero()) {
-      BaseV = PreheaderRewriter.expandCodeFor(Base, Base->getType(),
-                                              PreInsertPt);
+      BaseV = PreheaderRewriter.expandCodeFor(Base, 0, PreInsertPt);
 
       DOUT << "  INSERTING code for BASE = " << *Base << ":";
       if (BaseV->hasName())
@@ -1758,7 +1759,7 @@
         RewriteExpr = SE->getAddExpr(RewriteExpr, SE->getUnknown(BaseV));
 
       User.RewriteInstructionToUseNewBase(RewriteExpr, NewBasePt,
-                                          Rewriter, L, this,
+                                          Rewriter, L, this, *LI,
                                           DeadInsts);
 
       // Mark old value we replaced as possibly dead, so that it is eliminated

Modified: llvm/trunk/lib/Transforms/Utils/AddrModeMatcher.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/AddrModeMatcher.cpp?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/AddrModeMatcher.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/AddrModeMatcher.cpp Mon May 18 21:15:55 2009
@@ -255,43 +255,44 @@
 
     // Save the valid addressing mode in case we can't match.
     ExtAddrMode BackupAddrMode = AddrMode;
-    
-    // Check that this has no base reg yet.  If so, we won't have a place to
-    // put the base of the GEP (assuming it is not a null ptr).
-    bool SetBaseReg = true;
-    if (isa<ConstantPointerNull>(AddrInst->getOperand(0)))
-      SetBaseReg = false;   // null pointer base doesn't need representation.
-    else if (AddrMode.HasBaseReg)
-      return false;  // Base register already specified, can't match GEP.
-    else {
-      // Otherwise, we'll use the GEP base as the BaseReg.
+    unsigned OldSize = AddrModeInsts.size();
+
+    // See if the scale and offset amount is valid for this target.
+    AddrMode.BaseOffs += ConstantOffset;
+
+    // Match the base operand of the GEP.
+    if (!MatchAddr(AddrInst->getOperand(0), Depth+1)) {
+      // If it couldn't be matched, just stuff the value in a register.
+      if (AddrMode.HasBaseReg) {
+        AddrMode = BackupAddrMode;
+        AddrModeInsts.resize(OldSize);
+        return false;
+      }
       AddrMode.HasBaseReg = true;
       AddrMode.BaseReg = AddrInst->getOperand(0);
     }
-    
-    // See if the scale and offset amount is valid for this target.
-    AddrMode.BaseOffs += ConstantOffset;
-    
+
+    // Match the remaining variable portion of the GEP.
     if (!MatchScaledValue(AddrInst->getOperand(VariableOperand), VariableScale,
                           Depth)) {
+      // If it couldn't be matched, try stuffing the base into a register
+      // instead of matching it, and retrying the match of the scale.
       AddrMode = BackupAddrMode;
-      return false;
+      AddrModeInsts.resize(OldSize);
+      if (AddrMode.HasBaseReg)
+        return false;
+      AddrMode.HasBaseReg = true;
+      AddrMode.BaseReg = AddrInst->getOperand(0);
+      AddrMode.BaseOffs += ConstantOffset;
+      if (!MatchScaledValue(AddrInst->getOperand(VariableOperand),
+                            VariableScale, Depth)) {
+        // If even that didn't work, bail.
+        AddrMode = BackupAddrMode;
+        AddrModeInsts.resize(OldSize);
+        return false;
+      }
     }
-    
-    // If we have a null as the base of the GEP, folding in the constant offset
-    // plus variable scale is all we can do.
-    if (!SetBaseReg) return true;
-      
-    // If this match succeeded, we know that we can form an address with the
-    // GepBase as the basereg.  Match the base pointer of the GEP more
-    // aggressively by zeroing out BaseReg and rematching.  If the base is
-    // (for example) another GEP, this allows merging in that other GEP into
-    // the addressing mode we're forming.
-    AddrMode.HasBaseReg = false;
-    AddrMode.BaseReg = 0;
-    bool Success = MatchAddr(AddrInst->getOperand(0), Depth+1);
-    assert(Success && "MatchAddr should be able to fill in BaseReg!");
-    Success=Success;
+
     return true;
   }
   }

Added: llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep.ll?rev=72093&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep.ll (added)
+++ llvm/trunk/test/Transforms/IndVarSimplify/preserve-gep.ll Mon May 18 21:15:55 2009
@@ -0,0 +1,39 @@
+; RUN: llvm-as < %s | opt -indvars | llvm-dis > %t
+; RUN: not grep ptrtoint %t
+; RUN: not grep inttoptr %t
+; RUN: grep getelementptr %t | count 1
+
+; Indvars shouldn't leave getelementptrs expanded out as
+; inttoptr+ptrtoint in its output in common cases.
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-unknown-linux-gnu"
+	%struct.Foo = type { i32, i32, [10 x i32], i32 }
+
+define void @me(%struct.Foo* nocapture %Bar) nounwind {
+entry:
+	br i1 false, label %return, label %bb.nph
+
+bb.nph:		; preds = %entry
+	br label %bb
+
+bb:		; preds = %bb1, %bb.nph
+	%i.01 = phi i64 [ %4, %bb1 ], [ 0, %bb.nph ]		; <i64> [#uses=3]
+	%0 = getelementptr %struct.Foo* %Bar, i64 %i.01, i32 2, i64 3		; <i32*> [#uses=1]
+	%1 = load i32* %0, align 4		; <i32> [#uses=1]
+	%2 = mul i32 %1, 113		; <i32> [#uses=1]
+	%3 = getelementptr %struct.Foo* %Bar, i64 %i.01, i32 2, i64 3		; <i32*> [#uses=1]
+	store i32 %2, i32* %3, align 4
+	%4 = add i64 %i.01, 1		; <i64> [#uses=2]
+	br label %bb1
+
+bb1:		; preds = %bb
+	%phitmp = icmp sgt i64 %4, 19999		; <i1> [#uses=1]
+	br i1 %phitmp, label %bb1.return_crit_edge, label %bb
+
+bb1.return_crit_edge:		; preds = %bb1
+	br label %return
+
+return:		; preds = %bb1.return_crit_edge, %entry
+	ret void
+}

Modified: llvm/trunk/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll?rev=72093&r1=72092&r2=72093&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll (original)
+++ llvm/trunk/test/Transforms/LoopStrengthReduce/2009-04-28-no-reduce-mul.ll Mon May 18 21:15:55 2009
@@ -1,4 +1,5 @@
-; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis | grep {mul.*%lsr.iv} | count 2
+; RUN: llvm-as < %s | opt -loop-reduce | llvm-dis \
+; RUN:   | grep {getelementptr.*%lsr.iv.*%lsr.iv.*<i32\\*>}
 ; The multiply in bb2 must not be reduced to an add, as the sext causes the
 ; %1 argument to become negative after a while.
 ; ModuleID = '<stdin>'





More information about the llvm-commits mailing list