[llvm] 46a5745 - [InstSimplify] Fold icmp of allocas based on offset difference

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 29 00:16:36 PDT 2023


Author: Hanbum Park
Date: 2023-06-29T09:16:26+02:00
New Revision: 46a574501731dcf313f52e20cd5bc56111a2a492

URL: https://github.com/llvm/llvm-project/commit/46a574501731dcf313f52e20cd5bc56111a2a492
DIFF: https://github.com/llvm/llvm-project/commit/46a574501731dcf313f52e20cd5bc56111a2a492.diff

LOG: [InstSimplify] Fold icmp of allocas based on offset difference

Strengthen the fold for icmps of non-overlapping storage, by
working on the difference of offsets, rather than considering
both offsets independently. In particular, this allows handling
comparisons of pointers to the end of equal-sized allocations.

Proofs: https://alive2.llvm.org/ce/z/Po2nL4

Differential Revision: https://reviews.llvm.org/D153752

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
    llvm/test/Transforms/InstSimplify/past-the-end.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 54ce6264ef7ab..a32f6880e642b 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2793,11 +2793,11 @@ static Constant *computePointerICmp(CmpInst::Predicate Pred, Value *LHS,
       }(LHS);
       Opts.NullIsUnknownSize = F ? NullPointerIsDefined(F) : true;
       if (getObjectSize(LHS, LHSSize, DL, TLI, Opts) &&
-          getObjectSize(RHS, RHSSize, DL, TLI, Opts) &&
-          !LHSOffset.isNegative() && !RHSOffset.isNegative() &&
-          LHSOffset.ult(LHSSize) && RHSOffset.ult(RHSSize)) {
-        return ConstantInt::get(getCompareTy(LHS),
-                                !CmpInst::isTrueWhenEqual(Pred));
+          getObjectSize(RHS, RHSSize, DL, TLI, Opts)) {
+        APInt Dist = LHSOffset - RHSOffset;
+        if (Dist.isNonNegative() ? Dist.ult(LHSSize) : (-Dist).ult(RHSSize))
+          return ConstantInt::get(getCompareTy(LHS),
+                                  !CmpInst::isTrueWhenEqual(Pred));
       }
     }
 

diff  --git a/llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll b/llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
index 4766a39081da9..79fd9a22ba5cc 100644
--- a/llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
+++ b/llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll
@@ -40,15 +40,9 @@ define i1 @adjacent_alloca2() {
   ret i1 %res
 }
 
-; FIXME: Can't be equal
 define i1 @positive_non_equal_end() {
 ; CHECK-LABEL: @positive_non_equal_end(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 4
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 4
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
@@ -142,15 +136,9 @@ define i1 @both_neg_equal() {
   ret i1 %res
 }
 
-; FIXME: Can't be equal
 define i1 @mixed_offsets1() {
 ; CHECK-LABEL: @mixed_offsets1(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -1
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 2
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
@@ -160,15 +148,9 @@ define i1 @mixed_offsets1() {
   ret i1 %res
 }
 
-; FIXME: Can't be equal
 define i1 @mixed_offsets2() {
 ; CHECK-LABEL: @mixed_offsets2(
-; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 1
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -2
-; CHECK-NEXT:    [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]]
-; CHECK-NEXT:    ret i1 [[RES]]
+; CHECK-NEXT:    ret i1 true
 ;
   %a = alloca i8, i32 4
   %b = alloca i8, i32 4
@@ -178,23 +160,74 @@ define i1 @mixed_offsets2() {
   ret i1 %res
 }
 
-; FIXME: Can't be equal
 define i1 @negative_in_other() {
 ; CHECK-LABEL: @negative_in_other(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = alloca i8, i32 4
+  %b = alloca i8, i32 4
+  %a.off = getelementptr i8, ptr %a, i64 -3
+  %b.off = getelementptr i8, ptr %b, i64 -2
+  %res = icmp ne ptr %a.off, %b.off
+  ret i1 %res
+}
+
+define i1 @mixed_alloca_size1() {
+; CHECK-LABEL: @mixed_alloca_size1(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = alloca i8, i32 2
+  %b = alloca i8, i32 4
+  %a.off = getelementptr i8, ptr %a, i64 1
+  %b.off = getelementptr i8, ptr %b, i64 3
+  %res = icmp ne ptr %a.off, %b.off
+  ret i1 %res
+}
+
+define i1 @mixed_alloca_size2() {
+; CHECK-LABEL: @mixed_alloca_size2(
 ; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
-; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -3
-; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -2
+; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 2, align 1
+; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 1
+; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 3
 ; CHECK-NEXT:    [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]]
 ; CHECK-NEXT:    ret i1 [[RES]]
 ;
   %a = alloca i8, i32 4
+  %b = alloca i8, i32 2
+  %a.off = getelementptr i8, ptr %a, i64 1
+  %b.off = getelementptr i8, ptr %b, i64 3
+  %res = icmp ne ptr %a.off, %b.off
+  ret i1 %res
+}
+
+define i1 @mixed_alloca_size3() {
+; CHECK-LABEL: @mixed_alloca_size3(
+; CHECK-NEXT:    [[A:%.*]] = alloca i8, i32 2, align 1
+; CHECK-NEXT:    [[B:%.*]] = alloca i8, i32 4, align 1
+; CHECK-NEXT:    [[A_OFF:%.*]] = getelementptr i8, ptr [[A]], i64 -1
+; CHECK-NEXT:    [[B_OFF:%.*]] = getelementptr i8, ptr [[B]], i64 -3
+; CHECK-NEXT:    [[RES:%.*]] = icmp ne ptr [[A_OFF]], [[B_OFF]]
+; CHECK-NEXT:    ret i1 [[RES]]
+;
+  %a = alloca i8, i32 2
   %b = alloca i8, i32 4
-  %a.off = getelementptr i8, ptr %a, i64 -3
-  %b.off = getelementptr i8, ptr %b, i64 -2
+  %a.off = getelementptr i8, ptr %a, i64 -1
+  %b.off = getelementptr i8, ptr %b, i64 -3
   %res = icmp ne ptr %a.off, %b.off
   ret i1 %res
 }
 
+define i1 @mixed_alloca_size4() {
+; CHECK-LABEL: @mixed_alloca_size4(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = alloca i8, i32 4
+  %b = alloca i8, i32 2
+  %a.off = getelementptr i8, ptr %a, i64 -1
+  %b.off = getelementptr i8, ptr %b, i64 -3
+  %res = icmp ne ptr %a.off, %b.off
+  ret i1 %res
+}
 
 attributes #0 = { null_pointer_is_valid }

diff  --git a/llvm/test/Transforms/InstSimplify/past-the-end.ll b/llvm/test/Transforms/InstSimplify/past-the-end.ll
index 98285fb7bec15..3138130e353bb 100644
--- a/llvm/test/Transforms/InstSimplify/past-the-end.ll
+++ b/llvm/test/Transforms/InstSimplify/past-the-end.ll
@@ -58,12 +58,7 @@ define zeroext i1 @no_alloca_offsets() {
 
 define zeroext i1 @both_past_the_end_alloca() {
 ; CHECK-LABEL: @both_past_the_end_alloca(
-; CHECK:         [[M:%.*]] = alloca i32
-; CHECK-NEXT:    [[N:%.*]] = alloca i32
-; CHECK-NEXT:    [[X:%.*]] = getelementptr i32, ptr [[M]], i32 1
-; CHECK-NEXT:    [[Y:%.*]] = getelementptr i32, ptr [[N]], i32 1
-; CHECK-NEXT:    [[T:%.*]] = icmp eq ptr [[X]], [[Y]]
-; CHECK-NEXT:    ret i1 [[T]]
+; CHECK-NEXT:    ret i1 false
 ;
   %m = alloca i32
   %n = alloca i32
@@ -71,7 +66,6 @@ define zeroext i1 @both_past_the_end_alloca() {
   %y = getelementptr i32, ptr %n, i32 1
   %t = icmp eq ptr %x, %y
   ret i1 %t
-  ; TODO: refine this
 }
 
 ; Comparing past-the-end addresses of one alloca to the base address


        


More information about the llvm-commits mailing list