[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