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

Chris Lattner lattner at cs.uiuc.edu
Fri May 7 17:09:02 PDT 2004


Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.199 -> 1.200

---
Log message:

Implement folding of GEP's like:

        %tmp.0 = getelementptr [50 x sbyte]* %ar, uint 0, int 5         ; <sbyte*> [#uses=2]
        %tmp.7 = getelementptr sbyte* %tmp.0, int 8             ; <sbyte*> [#uses=1]

together.  This patch actually allows us to simplify and generalize the code.



---
Diffs of the changes:  (+43 -53)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.199 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.200
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.199	Fri May  7 10:35:56 2004
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Fri May  7 17:09:22 2004
@@ -2535,17 +2535,18 @@
 
 
 Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) {
+  Value *PtrOp = GEP.getOperand(0);
   // Is it 'getelementptr %P, long 0'  or 'getelementptr %P'
   // If so, eliminate the noop.
   if (GEP.getNumOperands() == 1)
-    return ReplaceInstUsesWith(GEP, GEP.getOperand(0));
+    return ReplaceInstUsesWith(GEP, PtrOp);
 
   bool HasZeroPointerIndex = false;
   if (Constant *C = dyn_cast<Constant>(GEP.getOperand(1)))
     HasZeroPointerIndex = C->isNullValue();
 
   if (GEP.getNumOperands() == 2 && HasZeroPointerIndex)
-    return ReplaceInstUsesWith(GEP, GEP.getOperand(0));
+    return ReplaceInstUsesWith(GEP, PtrOp);
 
   // Eliminate unneeded casts for indices.
   bool MadeChange = false;
@@ -2601,46 +2602,37 @@
   // getelementptr instructions into a single instruction.
   //
   std::vector<Value*> SrcGEPOperands;
-  if (GetElementPtrInst *Src = dyn_cast<GetElementPtrInst>(GEP.getOperand(0))) {
+  if (GetElementPtrInst *Src = dyn_cast<GetElementPtrInst>(PtrOp)) {
     SrcGEPOperands.assign(Src->op_begin(), Src->op_end());
-  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GEP.getOperand(0))) {
+  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(PtrOp)) {
     if (CE->getOpcode() == Instruction::GetElementPtr)
       SrcGEPOperands.assign(CE->op_begin(), CE->op_end());
   }
 
   if (!SrcGEPOperands.empty()) {
+    // Note that if our source is a gep chain itself that we wait for that
+    // chain to be resolved before we perform this transformation.  This
+    // avoids us creating a TON of code in some cases.
+    //
+    if (isa<GetElementPtrInst>(SrcGEPOperands[0]) &&
+        cast<Instruction>(SrcGEPOperands[0])->getNumOperands() == 2)
+      return 0;   // Wait until our source is folded to completion.
+
     std::vector<Value *> Indices;
+
+    // Find out whether the last index in the source GEP is a sequential idx.
+    bool EndsWithSequential = false;
+    for (gep_type_iterator I = gep_type_begin(*cast<User>(PtrOp)),
+           E = gep_type_end(*cast<User>(PtrOp)); I != E; ++I)
+      if (!isa<StructType>(*I))
+        EndsWithSequential = true;
   
     // Can we combine the two pointer arithmetics offsets?
-    if (SrcGEPOperands.size() == 2 && isa<Constant>(SrcGEPOperands[1]) &&
-        isa<Constant>(GEP.getOperand(1))) {
-      Constant *SGC = cast<Constant>(SrcGEPOperands[1]);
-      Constant *GC  = cast<Constant>(GEP.getOperand(1));
-      if (SGC->getType() != GC->getType()) {
-        SGC = ConstantExpr::getSignExtend(SGC, Type::LongTy);
-        GC = ConstantExpr::getSignExtend(GC, Type::LongTy);
-      }
-      
-      // Replace: gep (gep %P, long C1), long C2, ...
-      // With:    gep %P, long (C1+C2), ...
-      GEP.setOperand(0, SrcGEPOperands[0]);
-      GEP.setOperand(1, ConstantExpr::getAdd(SGC, GC));
-      if (Instruction *I = dyn_cast<Instruction>(GEP.getOperand(0)))
-        AddUsersToWorkList(*I);   // Reduce use count of Src
-      return &GEP;
-    } else if (SrcGEPOperands.size() == 2) {
+    if (EndsWithSequential) {
       // Replace: gep (gep %P, long B), long A, ...
       // With:    T = long A+B; gep %P, T, ...
       //
-      // Note that if our source is a gep chain itself that we wait for that
-      // chain to be resolved before we perform this transformation.  This
-      // avoids us creating a TON of code in some cases.
-      //
-      if (isa<GetElementPtrInst>(SrcGEPOperands[0]) &&
-          cast<Instruction>(SrcGEPOperands[0])->getNumOperands() == 2)
-        return 0;   // Wait until our source is folded to completion.
-
-      Value *Sum, *SO1 = SrcGEPOperands[1], *GO1 = GEP.getOperand(1);
+      Value *Sum, *SO1 = SrcGEPOperands.back(), *GO1 = GEP.getOperand(1);
       if (SO1 == Constant::getNullValue(SO1->getType())) {
         Sum = GO1;
       } else if (GO1 == Constant::getNullValue(GO1->getType())) {
@@ -2670,13 +2662,26 @@
             }
           }
         }
-        Sum = BinaryOperator::create(Instruction::Add, SO1, GO1,
-                                     GEP.getOperand(0)->getName()+".sum", &GEP);
-        WorkList.push_back(cast<Instruction>(Sum));
+        if (isa<Constant>(SO1) && isa<Constant>(GO1))
+          Sum = ConstantExpr::getAdd(cast<Constant>(SO1), cast<Constant>(GO1));
+        else {
+          Sum = BinaryOperator::create(Instruction::Add, SO1, GO1,
+                                       PtrOp->getName()+".sum", &GEP);
+          WorkList.push_back(cast<Instruction>(Sum));
+        }
+      }
+
+      // Recycle the GEP we already have if possible.
+      if (SrcGEPOperands.size() == 2) {
+        GEP.setOperand(0, SrcGEPOperands[0]);
+        GEP.setOperand(1, Sum);
+        return &GEP;
+      } else {
+        Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
+                       SrcGEPOperands.end()-1);
+        Indices.push_back(Sum);
+        Indices.insert(Indices.end(), GEP.op_begin()+2, GEP.op_end());
       }
-      GEP.setOperand(0, SrcGEPOperands[0]);
-      GEP.setOperand(1, Sum);
-      return &GEP;
     } else if (isa<Constant>(*GEP.idx_begin()) && 
                cast<Constant>(*GEP.idx_begin())->isNullValue() &&
                SrcGEPOperands.size() != 1) { 
@@ -2684,27 +2689,12 @@
       Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
                      SrcGEPOperands.end());
       Indices.insert(Indices.end(), GEP.idx_begin()+1, GEP.idx_end());
-    } else if (SrcGEPOperands.back() ==
-               Constant::getNullValue(SrcGEPOperands.back()->getType())) {
-      // We have to check to make sure this really is an ARRAY index we are
-      // ending up with, not a struct index.
-      generic_gep_type_iterator<std::vector<Value*>::iterator>
-        GTI = gep_type_begin(SrcGEPOperands[0]->getType(),
-                             SrcGEPOperands.begin()+1, SrcGEPOperands.end());
-      std::advance(GTI, SrcGEPOperands.size()-2);
-      if (isa<SequentialType>(*GTI)) {
-        // If the src gep ends with a constant array index, merge this get into
-        // it, even if we have a non-zero array index.
-        Indices.insert(Indices.end(), SrcGEPOperands.begin()+1,
-                       SrcGEPOperands.end()-1);
-        Indices.insert(Indices.end(), GEP.idx_begin(), GEP.idx_end());
-      }
     }
 
     if (!Indices.empty())
       return new GetElementPtrInst(SrcGEPOperands[0], Indices, GEP.getName());
 
-  } else if (GlobalValue *GV = dyn_cast<GlobalValue>(GEP.getOperand(0))) {
+  } else if (GlobalValue *GV = dyn_cast<GlobalValue>(PtrOp)) {
     // GEP of global variable.  If all of the indices for this GEP are
     // constants, we can promote this to a constexpr instead of an instruction.
 
@@ -2721,7 +2711,7 @@
       // Replace all uses of the GEP with the new constexpr...
       return ReplaceInstUsesWith(GEP, CE);
     }
-  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GEP.getOperand(0))) {
+  } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(PtrOp)) {
     if (CE->getOpcode() == Instruction::Cast) {
       if (HasZeroPointerIndex) {
         // transform: GEP (cast [10 x ubyte]* X to [0 x ubyte]*), long 0, ...





More information about the llvm-commits mailing list