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

Chris Lattner lattner at cs.uiuc.edu
Thu Jan 13 12:14:42 PST 2005



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.297 -> 1.298
---
Log message:

Fix a crash compiling 129.compress


---
Diffs of the changes:  (+109 -6)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.297 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.298
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.297	Sat Jan  8 13:42:22 2005
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Thu Jan 13 14:14:25 2005
@@ -116,6 +116,8 @@
     Instruction *visitSetCondInstWithCastAndConstant(BinaryOperator&I,
                                                      CastInst*LHSI,
                                                      ConstantInt* CI);
+    Instruction *FoldGEPSetCC(User *GEPLHS, Value *RHS,
+                              Instruction::BinaryOps Cond, Instruction &I);
     Instruction *visitShiftInst(ShiftInst &I);
     Instruction *visitCastInst(CastInst &CI);
     Instruction *visitSelectInst(SelectInst &CI);
@@ -347,6 +349,16 @@
   return 0;
 }
 
+/// dyn_castGetElementPtr - If this is a getelementptr instruction or constant
+/// expression, return it.
+static User *dyn_castGetElementPtr(Value *V) {
+  if (isa<GetElementPtrInst>(V)) return cast<User>(V);
+  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
+    if (CE->getOpcode() == Instruction::GetElementPtr)
+      return cast<User>(V);
+  return false;
+}
+
 // Log2 - Calculate the log base 2 for the specified value if it is exactly a
 // power of 2.
 static unsigned Log2(uint64_t Val) {
@@ -2078,6 +2090,91 @@
          cast<ConstantSInt>(In1)->getValue();
 }
 
+/// EmitGEPOffset - Given a getelementptr instruction/constantexpr, emit the
+/// code necessary to compute the offset from the base pointer (without adding
+/// in the base pointer).  Return the result as a signed integer of intptr size.
+static Value *EmitGEPOffset(User *GEP, Instruction &I, InstCombiner &IC) {
+  TargetData &TD = IC.getTargetData();
+  gep_type_iterator GTI = gep_type_begin(GEP);
+  const Type *UIntPtrTy = TD.getIntPtrType();
+  const Type *SIntPtrTy = UIntPtrTy->getSignedVersion();
+  Value *Result = Constant::getNullValue(SIntPtrTy);
+
+  // Build a mask for high order bits.
+  uint64_t PtrSizeMask = ~0ULL;
+  PtrSizeMask >>= 64-(TD.getPointerSize()*8);
+
+  ++GTI;   // Measure type stepping over.
+  for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
+    Value *Op = GEP->getOperand(i);
+    uint64_t Size = TD.getTypeSize(*GTI) & PtrSizeMask;
+    Constant *Scale = ConstantExpr::getCast(ConstantUInt::get(UIntPtrTy, Size),
+                                            SIntPtrTy);
+    if (Constant *OpC = dyn_cast<Constant>(Op)) {
+      if (!OpC->isNullValue()) {
+        Scale = ConstantExpr::getMul(OpC, Scale);
+        if (Constant *RC = dyn_cast<Constant>(Result))
+          Result = ConstantExpr::getAdd(RC, Scale);
+        else {
+          // Emit an add instruction.
+          Result = IC.InsertNewInstBefore(
+             BinaryOperator::createAdd(Result, Scale,
+                                       GEP->getName()+".offs"), I);
+        }
+      }
+    } else {
+      // We'll let instcombine(mul) convert this to a shl if possible.
+      Value *Offs = 
+        IC.InsertNewInstBefore(BinaryOperator::createMul(Op, Scale,
+                                                   GEP->getName()+".idx"), I);
+
+      // Emit an add instruction.
+      Result = IC.InsertNewInstBefore(BinaryOperator::createAdd(Offs, Result,
+                                                    GEP->getName()+".offs"), I);
+    }
+  }
+  return Result;
+}
+
+/// FoldGEPSetCC - Fold comparisons between a GEP instruction and something
+/// else.  At this point we know that the GEP is on the LHS of the comparison.
+Instruction *InstCombiner::FoldGEPSetCC(User *GEPLHS, Value *RHS,
+                                        Instruction::BinaryOps Cond,
+                                        Instruction &I) {
+  assert(dyn_castGetElementPtr(GEPLHS) && "LHS is not a getelementptr!");
+                                             
+  Value *PtrBase = GEPLHS->getOperand(0);
+  if (PtrBase == RHS) {
+    // As an optimization, we don't actually have to compute the actual value of
+    // OFFSET if this is a seteq or setne comparison, just return whether each
+    // index is zero or not.
+
+    // Only lower this if the setcc is the only user of the GEP or if we expect
+    // the result to fold to a constant!
+    if (isa<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) {
+      // ((gep Ptr, OFFSET) cmp Ptr)   ---> (OFFSET cmp 0).
+      Value *Offset = EmitGEPOffset(GEPLHS, I, *this);
+      return new SetCondInst(Cond, Offset,
+                             Constant::getNullValue(Offset->getType()));
+    }
+  } else if (User *GEPRHS = dyn_castGetElementPtr(RHS)) {
+    if (PtrBase != GEPRHS->getOperand(0))
+      return 0;
+
+    // Only lower this if the setcc is the only user of the GEP or if we expect
+    // the result to fold to a constant!
+    if ((isa<ConstantExpr>(GEPLHS) || GEPLHS->hasOneUse()) &&
+        (isa<ConstantExpr>(GEPRHS) || GEPRHS->hasOneUse())) {
+      // ((gep Ptr, OFFSET1) cmp (gep Ptr, OFFSET2)  --->  (OFFSET1 cmp OFFSET2)
+      Value *L = EmitGEPOffset(GEPLHS, I, *this);
+      Value *R = EmitGEPOffset(GEPRHS, I, *this);
+      return new SetCondInst(Cond, L, R);
+    }
+  }
+  return 0;
+}
+
+
 Instruction *InstCombiner::visitSetCondInst(BinaryOperator &I) {
   bool Changed = SimplifyCommutative(I);
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
@@ -2625,6 +2722,15 @@
     }
   }
 
+  // If we can optimize a 'setcc GEP, P' or 'setcc P, GEP', do so now.
+  if (User *GEP = dyn_castGetElementPtr(Op0))
+    if (Instruction *NI = FoldGEPSetCC(GEP, Op1, I.getOpcode(), I))
+      return NI;
+  if (User *GEP = dyn_castGetElementPtr(Op1))
+    if (Instruction *NI = FoldGEPSetCC(GEP, Op0,
+                           SetCondInst::getSwappedCondition(I.getOpcode()), I))
+      return NI;
+
   // Test to see if the operands of the setcc are casted versions of other
   // values.  If the cast can be stripped off both arguments, we do so now.
   if (CastInst *CI = dyn_cast<CastInst>(Op0)) {
@@ -3951,12 +4057,8 @@
   // getelementptr instructions into a single instruction.
   //
   std::vector<Value*> SrcGEPOperands;
-  if (GetElementPtrInst *Src = dyn_cast<GetElementPtrInst>(PtrOp)) {
+  if (User *Src = dyn_castGetElementPtr(PtrOp))
     SrcGEPOperands.assign(Src->op_begin(), Src->op_end());
-  } 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
@@ -4079,7 +4181,8 @@
                 GEP.setOperand(0, X);
                 return &GEP;
               }
-      } else if (GEP.getNumOperands() == 2) {
+      } else if (GEP.getNumOperands() == 2 &&
+                 isa<PointerType>(CE->getOperand(0)->getType())) {
         // Transform things like:
         // %t = getelementptr ubyte* cast ([2 x sbyte]* %str to ubyte*), uint %V
         // into:  %t1 = getelementptr [2 x sbyte*]* %str, int 0, uint %V; cast






More information about the llvm-commits mailing list