diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2793,11 +2793,11 @@ }(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 --- a/llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll +++ b/llvm/test/Transforms/InstSimplify/cmp-alloca-offsets.ll @@ -40,15 +40,9 @@ 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 @@ 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 @@ 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 @@ 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 --- 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 @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 @@ %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