[llvm-commits] [llvm] r92444 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/load-cmp.ll
Chris Lattner
sabre at nondot.org
Sat Jan 2 19:03:27 PST 2010
Author: lattner
Date: Sat Jan 2 21:03:27 2010
New Revision: 92444
URL: http://llvm.org/viewvc/llvm-project?rev=92444&view=rev
Log:
generalize the previous transformation to handle indexing into
arrays of structs and other arrays, so long as all the subsequent
indexes are constants. This triggers frequently for stuff like:
@divisions = internal constant [29 x [2 x i32]] [[2 x i32] zeroinitializer, [2 x i32] [i32 0, i32 1], [2 x i32] [i32 0, i32 2], [2 x i32] [i32 0, i32 1], [2 x i32] zeroinitializer, [2 x i32] [i32 0, i32 1], [2 x i32] [i32 0, i32 1], [2 x i32] [i32 0, i32 2], [2 x i32] [i32 0, i32 2], [2 x i32] zeroinitializer, [2 x i32] zeroinitializer, [2 x i32] zeroinitializer, [2 x i32] [i32 0, i32 2], [2 x i32] [i32 0, i32 1], [2 x i32] zeroinitializer, [2 x i32] [i32 1, i32 0], [2 x i32] [i32 1, i32 1], [2 x i32] [i32 1, i32 1], [2 x i32] [i32 1, i32 2], [2 x i32] [i32 1, i32 1], [2 x i32] [i32 1, i32 0], [2 x i32] [i32 1, i32 2], [2 x i32] [i32 1, i32 2], [2 x i32] [i32 1, i32 0], [2 x i32] [i32 1, i32 0], [2 x i32] [i32 1, i32 0], [2 x i32] [i32 1, i32 1], [2 x i32] [i32 1, i32 2], [2 x i32] [i32 1, i32 2]], align 32 ; <[29 x [2 x i32]]*> [#uses=50]
%623 = getelementptr inbounds [29 x [2 x i32]]* @divisions, i64 0, i64 %619, i64 0 ; <i32*> [#uses=1]
%684 = icmp eq i32 %683, 999
also for the "my_defs" table in 'gs', etc.
Modified:
llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
llvm/trunk/test/Transforms/InstCombine/load-cmp.ll
Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=92444&r1=92443&r2=92444&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Sat Jan 2 21:03:27 2010
@@ -6017,7 +6017,6 @@
return new ICmpInst(Pred, LHSI->getOperand(0), RHSInt);
}
-
/// FoldCmpLoadFromIndexedGlobal - Called we see this pattern:
/// cmp pred (load (gep GV, ...)), cmpcst
/// where GV is a global variable with a constant initializer. Try to simplify
@@ -6029,18 +6028,43 @@
Instruction *InstCombiner::
FoldCmpLoadFromIndexedGlobal(GetElementPtrInst *GEP, GlobalVariable *GV,
CmpInst &ICI, ConstantInt *AndCst) {
+ ConstantArray *Init = dyn_cast<ConstantArray>(GV->getInitializer());
+ if (Init == 0 || Init->getNumOperands() > 1024) return 0;
// There are many forms of this optimization we can handle, for now, just do
// the simple index into a single-dimensional array.
//
- // Require: GEP GV, 0, i
- if (GEP->getNumOperands() != 3 ||
+ // Require: GEP GV, 0, i {{, constant indices}}
+ if (GEP->getNumOperands() < 3 ||
!isa<ConstantInt>(GEP->getOperand(1)) ||
- !cast<ConstantInt>(GEP->getOperand(1))->isZero())
+ !cast<ConstantInt>(GEP->getOperand(1))->isZero() ||
+ isa<Constant>(GEP->getOperand(2)))
return 0;
-
- ConstantArray *Init = dyn_cast<ConstantArray>(GV->getInitializer());
- if (Init == 0 || Init->getNumOperands() > 1024) return 0;
+
+ // Check that indices after the variable are constants and in-range for the
+ // type they index. Collect the indices. This is typically for arrays of
+ // structs.
+ SmallVector<unsigned, 4> LaterIndices;
+
+ const Type *EltTy = cast<ArrayType>(Init->getType())->getElementType();
+ for (unsigned i = 3, e = GEP->getNumOperands(); i != e; ++i) {
+ ConstantInt *Idx = dyn_cast<ConstantInt>(GEP->getOperand(i));
+ if (Idx == 0) return 0; // Variable index.
+
+ uint64_t IdxVal = Idx->getZExtValue();
+ if ((unsigned)IdxVal != IdxVal) return 0; // Too large array index.
+
+ if (const StructType *STy = dyn_cast<StructType>(EltTy))
+ EltTy = STy->getElementType(IdxVal);
+ else if (const ArrayType *ATy = dyn_cast<ArrayType>(EltTy)) {
+ if (IdxVal >= ATy->getNumElements()) return 0;
+ EltTy = ATy->getElementType();
+ } else {
+ return 0; // Unknown type.
+ }
+
+ LaterIndices.push_back(IdxVal);
+ }
enum { Overdefined = -3, Undefined = -2 };
@@ -6076,6 +6100,11 @@
for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
Constant *Elt = Init->getOperand(i);
+ // If this is indexing an array of structures, get the structure element.
+ if (!LaterIndices.empty())
+ Elt = ConstantExpr::getExtractValue(Elt, LaterIndices.data(),
+ LaterIndices.size());
+
// If the element is masked, handle it.
if (AndCst) Elt = ConstantExpr::getAnd(Elt, AndCst);
@@ -6244,8 +6273,6 @@
return new ICmpInst(ICmpInst::ICMP_NE, V, ConstantInt::get(Ty, 0));
}
- // TODO: GEP 0, i, 4
-
return 0;
}
@@ -6337,12 +6364,15 @@
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0))) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
- !cast<LoadInst>(LHSI)->isVolatile())
+ !cast<LoadInst>(LHSI)->isVolatile()) {
if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV, I))
return Res;
- //errs() << "NOT HANDLED FP: " << *GV << "\n";
- //errs() << "\t" << *GEP << "\n";
- //errs() << "\t " << I << "\n\n\n";
+#if 0
+ errs() << "NOT HANDLED FP: " << *GV << "\n";
+ errs() << "\t" << *GEP << "\n";
+ errs() << "\t " << I << "\n\n\n";
+#endif
+ }
}
break;
}
@@ -6731,12 +6761,15 @@
dyn_cast<GetElementPtrInst>(LHSI->getOperand(0))) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(GEP->getOperand(0)))
if (GV->isConstant() && GV->hasDefinitiveInitializer() &&
- !cast<LoadInst>(LHSI)->isVolatile())
+ !cast<LoadInst>(LHSI)->isVolatile()) {
if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV, I))
return Res;
- //errs() << "NOT HANDLED INT: " << *GV << "\n";
- //errs() << "\t" << *GEP << "\n";
- //errs() << "\t " << I << "\n\n\n";
+#if 0
+ errs() << "NOT HANDLED INT: " << *GV << "\n";
+ errs() << "\t" << *GEP << "\n";
+ errs() << "\t " << I << "\n\n\n";
+#endif
+ }
}
break;
}
@@ -7401,9 +7434,12 @@
ConstantInt *C = cast<ConstantInt>(LHSI->getOperand(1));
if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV,ICI, C))
return Res;
- //errs() << "NOT HANDLED INT: " << *GV << "\n";
- //errs() << "\t" << *GEP << "\n";
- //errs() << "\t " << I << "\n\n\n";
+#if 0
+ errs() << "NOT HANDLED 'AND': " << *GV << "\n";
+ errs() << "\t" << *GEP << "\n";
+ errs() << "\t " << *LHSI << "\n\n\n";
+ errs() << "\t " << ICI << "\n\n\n";
+#endif
}
}
break;
Modified: llvm/trunk/test/Transforms/InstCombine/load-cmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/load-cmp.ll?rev=92444&r1=92443&r2=92444&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/load-cmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/load-cmp.ll Sat Jan 2 21:03:27 2010
@@ -92,3 +92,21 @@
; CHECK-NEXT: %S = icmp ult i32 {{.*}}, 2
; CHECK-NEXT: ret i1 %S
}
+
+ at GA = internal constant [4 x { i32, i32 } ] [
+ { i32, i32 } { i32 1, i32 0 },
+ { i32, i32 } { i32 2, i32 1 },
+ { i32, i32 } { i32 3, i32 1 },
+ { i32, i32 } { i32 4, i32 0 }
+]
+
+define i1 @test9(i32 %X) {
+ %P = getelementptr [4 x { i32, i32 } ]* @GA, i32 0, i32 %X, i32 1
+ %Q = load i32* %P
+ %R = icmp eq i32 %Q, 1
+ ret i1 %R
+; CHECK: @test9
+; CHECK-NEXT: add i32 %X, -1
+; CHECK-NEXT: %R = icmp ult i32 {{.*}}, 2
+; CHECK-NEXT: ret i1 %R
+}
More information about the llvm-commits
mailing list