[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