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

Chris Lattner lattner at cs.uiuc.edu
Thu Jan 13 14:25:37 PST 2005



Changes in directory llvm/lib/Transforms/Scalar:

InstructionCombining.cpp updated: 1.299 -> 1.300
---
Log message:

Implement an optimization for == and != comparisons like this:

_Bool test2(int X, int Y) {
  return &arr[X][Y] == arr;
}

instead of generating this:

bool %test2(int %X, int %Y) {
        %tmp.3.idx = mul int %X, 160            ; <int> [#uses=1]
        %tmp.3.idx1 = shl int %Y, ubyte 2               ; <int> [#uses=1]
        %tmp.3.offs2 = sub int 0, %tmp.3.idx            ; <int> [#uses=1]
        %tmp.7 = seteq int %tmp.3.idx1, %tmp.3.offs2            ; <bool> [#uses=1]
        ret bool %tmp.7
}


generate this:

bool %test2(int %X, int %Y) {
        seteq int %X, 0         ; <bool>:0 [#uses=1]
        seteq int %Y, 0         ; <bool>:1 [#uses=1]
        %tmp.7 = and bool %0, %1                ; <bool> [#uses=1]
        ret bool %tmp.7
}

This idiom occurs in C++ programs when iterating from begin() to end(), 
in a vector or array.  For example, we now compile this:

void test(int X, int Y) {
  for (int *i = arr; i != arr+100; ++i)
    foo(*i);
}

to this:

no_exit:                ; preds = %entry, %no_exit
	...
        %exitcond = seteq uint %indvar.next, 100                ; <bool> [#uses=1]
        br bool %exitcond, label %return, label %no_exit



instead of this:

no_exit:                ; preds = %entry, %no_exit
	...
        %inc5 = getelementptr [100 x [40 x int]]* %arr, int 0, int 0, int %inc.rec              ; <int*> [#uses=1]
        %tmp.8 = seteq int* %inc5, getelementptr ([100 x [40 x int]]* %arr, int 0, int 100, int 0)              ; <bool> [#uses=1]
        %indvar.next = add uint %indvar, 1              ; <uint> [#uses=1]
        br bool %tmp.8, label %return, label %no_exit




---
Diffs of the changes:  (+63 -1)

Index: llvm/lib/Transforms/Scalar/InstructionCombining.cpp
diff -u llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.299 llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.300
--- llvm/lib/Transforms/Scalar/InstructionCombining.cpp:1.299	Thu Jan 13 14:40:58 2005
+++ llvm/lib/Transforms/Scalar/InstructionCombining.cpp	Thu Jan 13 16:25:21 2005
@@ -2149,12 +2149,53 @@
                                         Instruction::BinaryOps Cond,
                                         Instruction &I) {
   assert(dyn_castGetElementPtr(GEPLHS) && "LHS is not a getelementptr!");
-                                             
+
+  if (CastInst *CI = dyn_cast<CastInst>(RHS))
+    if (isa<PointerType>(CI->getOperand(0)->getType()))
+      RHS = CI->getOperand(0);
+
   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.
+    if (Cond == Instruction::SetEQ || Cond == Instruction::SetNE) {
+      Instruction *InVal = 0;
+      for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i) {
+        bool EmitIt = true;
+        if (Constant *C = dyn_cast<Constant>(GEPLHS->getOperand(i))) {
+          if (isa<UndefValue>(C))  // undef index -> undef.
+            return ReplaceInstUsesWith(I, UndefValue::get(I.getType()));
+          if (C->isNullValue())
+            EmitIt = false;
+          else if (isa<ConstantInt>(C))
+            return ReplaceInstUsesWith(I, // No comparison is needed here.
+                                 ConstantBool::get(Cond == Instruction::SetNE));
+        }
+
+        if (EmitIt) {
+          Instruction *Comp = 
+            new SetCondInst(Cond, GEPLHS->getOperand(i),
+                    Constant::getNullValue(GEPLHS->getOperand(i)->getType()));
+          if (InVal == 0)
+            InVal = Comp;
+          else {
+            InVal = InsertNewInstBefore(InVal, I);
+            InsertNewInstBefore(Comp, I);
+            if (Cond == Instruction::SetNE)   // True if any are unequal
+              InVal = BinaryOperator::createOr(InVal, Comp);
+            else                              // True if all are equal
+              InVal = BinaryOperator::createAnd(InVal, Comp);
+          }
+        }
+      }
+
+      if (InVal)
+        return InVal;
+      else
+        ReplaceInstUsesWith(I, // No comparison is needed here, all indexes = 0
+                            ConstantBool::get(Cond == Instruction::SetEQ));
+    }
 
     // Only lower this if the setcc is the only user of the GEP or if we expect
     // the result to fold to a constant!
@@ -2168,6 +2209,27 @@
     if (PtrBase != GEPRHS->getOperand(0))
       return 0;
 
+    // If one of the GEPs has all zero indices, recurse.
+    bool AllZeros = true;
+    for (unsigned i = 1, e = GEPLHS->getNumOperands(); i != e; ++i)
+      if (!isa<Constant>(GEPLHS->getOperand(i)) ||
+          !cast<Constant>(GEPLHS->getOperand(i))->isNullValue()) {
+        AllZeros = false;
+        break;
+      }
+    if (AllZeros)
+      return FoldGEPSetCC(GEPRHS, GEPLHS->getOperand(0),
+                          SetCondInst::getSwappedCondition(Cond), I);
+    AllZeros = true;
+    for (unsigned i = 1, e = GEPRHS->getNumOperands(); i != e; ++i)
+      if (!isa<Constant>(GEPRHS->getOperand(i)) ||
+          !cast<Constant>(GEPRHS->getOperand(i))->isNullValue()) {
+        AllZeros = false;
+        break;
+      }
+    if (AllZeros)
+      return FoldGEPSetCC(GEPLHS, GEPRHS->getOperand(0), Cond, I);
+
     // 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()) &&






More information about the llvm-commits mailing list