fold comparisons of gep'd alloca points with null to false,
authorChris Lattner <sabre@nondot.org>
Mon, 20 Feb 2012 00:42:49 +0000 (00:42 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 20 Feb 2012 00:42:49 +0000 (00:42 +0000)
implementing PR12013.  We now compile the testcase to:

__Z4testv:                              ## @_Z4testv
## BB#0:                                ## %_ZN4llvm15SmallVectorImplIiE9push_backERKi.exit
pushq %rbx
subq $64, %rsp
leaq 32(%rsp), %rbx
movq %rbx, (%rsp)
leaq 64(%rsp), %rax
movq %rax, 16(%rsp)
movl $1, 32(%rsp)
leaq 36(%rsp), %rax
movq %rax, 8(%rsp)
leaq (%rsp), %rdi
callq __Z1gRN4llvm11SmallVectorIiLj8EEE
movq (%rsp), %rdi
cmpq %rbx, %rdi
je LBB0_2
## BB#1:
callq _free
LBB0_2:                                 ## %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit
addq $64, %rsp
popq %rbx
ret

instead of:

__Z4testv:                              ## @_Z4testv
## BB#0:
pushq %rbx
subq $64, %rsp
xorl %eax, %eax
leaq (%rsp), %rbx
addq $32, %rbx
movq %rbx, (%rsp)
movq %rbx, 8(%rsp)
leaq 64(%rsp), %rcx
movq %rcx, 16(%rsp)
je LBB0_2
## BB#1:
movl $1, 32(%rsp)
movq %rbx, %rax
LBB0_2:                                 ## %_ZN4llvm15SmallVectorImplIiE9push_backERKi.exit
addq $4, %rax
movq %rax, 8(%rsp)
leaq (%rsp), %rdi
callq __Z1gRN4llvm11SmallVectorIiLj8EEE
movq (%rsp), %rdi
cmpq %rbx, %rdi
je LBB0_4
## BB#3:
callq _free
LBB0_4:                                 ## %_ZN4llvm11SmallVectorIiLj8EED1Ev.exit
addq $64, %rsp
popq %rbx
ret

This doesn't shrink clang noticably though.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@150944 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/InstructionSimplify.cpp
test/Transforms/InstSimplify/compare.ll

index 88a2c53e806e7d8f202765dbf14e67a428db793c..9b0ce1113acd4f3f940605a2dae1e257200728c7 100644 (file)
@@ -1520,6 +1520,15 @@ static Value *ExtractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
   return 0;
 }
 
+/// stripPointerAdjustments - This is like Value::stripPointerCasts, but also
+/// removes inbounds gep operations, regardless of their indices.
+static Value *stripPointerAdjustments(Value *V) {
+  if (GEPOperator *GEP = dyn_cast<GEPOperator>(V))
+    if (GEP->isInBounds())
+      return stripPointerAdjustments(GEP->getOperand(0)->stripPointerCasts());
+  return V;
+}
+
 /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
 /// fold the result.  If not, this returns null.
 static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
@@ -1595,10 +1604,18 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
   Value *RHSPtr = RHS->stripPointerCasts();
   if (LHSPtr == RHSPtr)
     return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred));
-  if (isa<AllocaInst>(LHSPtr) && (isa<GlobalValue>(RHSPtr) ||
-                                  isa<AllocaInst>(RHSPtr)  ||
-                                  isa<ConstantPointerNull>(RHSPtr)))
-    return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
+  
+  // Be more aggressive about stripping pointer adjustments when checking a
+  // comparison of an alloca address to another object.  We can rip off all
+  // inbounds GEP operations, even if they are variable.
+  LHSPtr = stripPointerAdjustments(LHSPtr);
+  if (isa<AllocaInst>(LHSPtr)) {
+    RHSPtr = stripPointerAdjustments(RHSPtr);
+    if (LHSPtr != RHSPtr &&
+        (isa<GlobalValue>(RHSPtr) || isa<AllocaInst>(RHSPtr)  ||
+         isa<ConstantPointerNull>(RHSPtr)))
+      return ConstantInt::get(ITy, CmpInst::isFalseWhenEqual(Pred));
+  }
 
   // If we are comparing with zero then try hard since this is a common case.
   if (match(RHS, m_Zero())) {
index 92b8fc7e3a9274d70fd141713b5f620879c70c82..f22ac46397f5389a395b1cf6b1843f19f92215e0 100644 (file)
@@ -446,9 +446,20 @@ define <2 x i1> @vectorselect1(<2 x i1> %cond) {
 ; CHECK: ret <2 x i1> %cond
 }
 
-define <2 x i1> @vectorselectcrash(i32 %arg1) { ; PR11948
+; PR11948
+define <2 x i1> @vectorselectcrash(i32 %arg1) {
   %tobool40 = icmp ne i32 %arg1, 0
   %cond43 = select i1 %tobool40, <2 x i16> <i16 -5, i16 66>, <2 x i16> <i16 46, i16 1>
   %cmp45 = icmp ugt <2 x i16> %cond43, <i16 73, i16 21>
   ret <2 x i1> %cmp45
 }
+
+; PR12013
+define i1 @alloca_compare(i64 %idx) {
+  %sv = alloca { i32, i32, [124 x i32] }
+  %1 = getelementptr inbounds { i32, i32, [124 x i32] }* %sv, i32 0, i32 2, i64 %idx
+  %2 = icmp eq i32* %1, null
+  ret i1 %2
+  ; CHECK: alloca_compare
+  ; CHECK: ret i1 false
+}