[llvm-commits] [llvm] r153419 - in /llvm/trunk: lib/Analysis/InstructionSimplify.cpp test/Transforms/InstSimplify/compare.ll
Chandler Carruth
chandlerc at gmail.com
Sun Mar 25 14:28:15 PDT 2012
Author: chandlerc
Date: Sun Mar 25 16:28:14 2012
New Revision: 153419
URL: http://llvm.org/viewvc/llvm-project?rev=153419&view=rev
Log:
Teach instsimplify how to simplify comparisons of pointers which are
constant-offsets of a common base using the generic GEP-walking logic
I added for computing pointer differences in the same situation.
Modified:
llvm/trunk/lib/Analysis/InstructionSimplify.cpp
llvm/trunk/test/Transforms/InstSimplify/compare.ll
Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=153419&r1=153418&r2=153419&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original)
+++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Sun Mar 25 16:28:14 2012
@@ -1591,6 +1591,45 @@
return 0;
}
+static Constant *computePointerICmp(const TargetData &TD,
+ CmpInst::Predicate Pred,
+ Value *LHS, Value *RHS) {
+ // We can only fold certain predicates on pointer comparisons.
+ switch (Pred) {
+ default:
+ return 0;
+
+ // Equality comaprisons are easy to fold.
+ case CmpInst::ICMP_EQ:
+ case CmpInst::ICMP_NE:
+ break;
+
+ // We can only handle unsigned relational comparisons because 'inbounds' on
+ // a GEP only protects against unsigned wrapping.
+ case CmpInst::ICMP_UGT:
+ case CmpInst::ICMP_UGE:
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_ULE:
+ // However, we have to switch them to their signed variants to handle
+ // negative indices from the base pointer.
+ Pred = ICmpInst::getSignedPredicate(Pred);
+ break;
+ }
+
+ Constant *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
+ if (!LHSOffset)
+ return 0;
+ Constant *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
+ if (!RHSOffset)
+ return 0;
+
+ // If LHS and RHS are not related via constant offsets to the same base
+ // value, there is nothing we can do here.
+ if (LHS != RHS)
+ return 0;
+
+ return ConstantExpr::getICmp(Pred, LHSOffset, RHSOffset);
+}
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
/// fold the result. If not, this returns null.
@@ -2311,7 +2350,12 @@
return getFalse(ITy);
}
- // Simplify comparisons of GEPs.
+ // Simplify comparisons of related pointers using a powerful, recursive
+ // GEP-walk when we have target data available..
+ if (Q.TD && LHS->getType()->isPointerTy() && RHS->getType()->isPointerTy())
+ if (Constant *C = computePointerICmp(*Q.TD, Pred, LHS, RHS))
+ return C;
+
if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) {
if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) {
if (GLHS->getPointerOperand() == GRHS->getPointerOperand() &&
Modified: llvm/trunk/test/Transforms/InstSimplify/compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstSimplify/compare.ll?rev=153419&r1=153418&r2=153419&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstSimplify/compare.ll (original)
+++ llvm/trunk/test/Transforms/InstSimplify/compare.ll Sun Mar 25 16:28:14 2012
@@ -103,6 +103,68 @@
; CHECK: ret i1 %equal
}
+define i1 @gep9(i8* %ptr) {
+; CHECK: @gep9
+; CHECK-NOT: ret
+; CHECK: ret i1 true
+
+entry:
+ %first1 = getelementptr inbounds i8* %ptr, i32 0
+ %first2 = getelementptr inbounds i8* %first1, i32 1
+ %first3 = getelementptr inbounds i8* %first2, i32 2
+ %first4 = getelementptr inbounds i8* %first3, i32 4
+ %last1 = getelementptr inbounds i8* %first2, i32 48
+ %last2 = getelementptr inbounds i8* %last1, i32 8
+ %last3 = getelementptr inbounds i8* %last2, i32 -4
+ %last4 = getelementptr inbounds i8* %last3, i32 -4
+ %first.int = ptrtoint i8* %first4 to i32
+ %last.int = ptrtoint i8* %last4 to i32
+ %cmp = icmp ne i32 %last.int, %first.int
+ ret i1 %cmp
+}
+
+define i1 @gep10(i8* %ptr) {
+; CHECK: @gep10
+; CHECK-NOT: ret
+; CHECK: ret i1 true
+
+entry:
+ %first1 = getelementptr inbounds i8* %ptr, i32 -2
+ %first2 = getelementptr inbounds i8* %first1, i32 44
+ %last1 = getelementptr inbounds i8* %ptr, i32 48
+ %last2 = getelementptr inbounds i8* %last1, i32 -6
+ %first.int = ptrtoint i8* %first2 to i32
+ %last.int = ptrtoint i8* %last2 to i32
+ %cmp = icmp eq i32 %last.int, %first.int
+ ret i1 %cmp
+}
+
+define i1 @gep11(i8* %ptr) {
+; CHECK: @gep11
+; CHECK-NOT: ret
+; CHECK: ret i1 true
+
+entry:
+ %first1 = getelementptr inbounds i8* %ptr, i32 -2
+ %last1 = getelementptr inbounds i8* %ptr, i32 48
+ %last2 = getelementptr inbounds i8* %last1, i32 -6
+ %cmp = icmp ult i8* %first1, %last2
+ ret i1 %cmp
+}
+
+define i1 @gep12(i8* %ptr) {
+; CHECK: @gep12
+; CHECK-NOT: ret
+; CHECK: ret i1 %cmp
+
+entry:
+ %first1 = getelementptr inbounds i8* %ptr, i32 -2
+ %last1 = getelementptr inbounds i8* %ptr, i32 48
+ %last2 = getelementptr inbounds i8* %last1, i32 -6
+ %cmp = icmp slt i8* %first1, %last2
+ ret i1 %cmp
+}
+
define i1 @zext(i32 %x) {
; CHECK: @zext
%e1 = zext i32 %x to i64
More information about the llvm-commits
mailing list