mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[InstCombine] propagate 'nsw' on pointer difference of 'inbounds' geps (PR47430)
There's no signed wrap if both geps have 'inbounds': https://alive2.llvm.org/ce/z/nZkQTg https://alive2.llvm.org/ce/z/7qFauh
This commit is contained in:
parent
7ae9f7c717
commit
f7e01a7376
@ -1671,11 +1671,12 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
|
||||
I->getOpcode() == Instruction::Mul)
|
||||
I->setHasNoUnsignedWrap();
|
||||
|
||||
// If we had a constant expression GEP on the other side offsetting the
|
||||
// pointer, subtract it from the offset we have.
|
||||
// If we have a 2nd GEP of the same base pointer, subtract the offsets.
|
||||
// If both GEPs are inbounds, then the subtract does not have signed overflow.
|
||||
if (GEP2) {
|
||||
Value *Offset = EmitGEPOffset(GEP2);
|
||||
Result = Builder.CreateSub(Result, Offset, "gepdiff");
|
||||
Result = Builder.CreateSub(Result, Offset, "gepdiff", /* NUW */ false,
|
||||
GEP1->isInBounds() && GEP2->isInBounds());
|
||||
}
|
||||
|
||||
// If we have p - gep(p, ...) then we have to negate the result.
|
||||
|
@ -245,7 +245,7 @@ define i64 @test24b(i8* %P, i64 %A){
|
||||
define i64 @test25(i8* %P, i64 %A){
|
||||
; CHECK-LABEL: @test25(
|
||||
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i64 [[A:%.*]], 1
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = add i64 [[B_IDX]], -84
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i64 [[B_IDX]], -84
|
||||
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
||||
;
|
||||
%B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A
|
||||
@ -260,7 +260,7 @@ define i16 @test25_as1(i8 addrspace(1)* %P, i64 %A) {
|
||||
; CHECK-LABEL: @test25_as1(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16
|
||||
; CHECK-NEXT: [[B_IDX:%.*]] = shl nsw i16 [[TMP1]], 1
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = add i16 [[B_IDX]], -84
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i16 [[B_IDX]], -84
|
||||
; CHECK-NEXT: ret i16 [[GEPDIFF]]
|
||||
;
|
||||
%B = getelementptr inbounds [42 x i16], [42 x i16] addrspace(1)* @Arr_as1, i64 0, i64 %A
|
||||
@ -272,7 +272,7 @@ define i16 @test25_as1(i8 addrspace(1)* %P, i64 %A) {
|
||||
define i64 @test30(i8* %foo, i64 %i, i64 %j) {
|
||||
; CHECK-LABEL: @test30(
|
||||
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[I:%.*]], 2
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[GEP1_IDX]], [[J:%.*]]
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[GEP1_IDX]], [[J:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
||||
;
|
||||
%bit = bitcast i8* %foo to i32*
|
||||
@ -287,7 +287,7 @@ define i64 @test30(i8* %foo, i64 %i, i64 %j) {
|
||||
define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
|
||||
; CHECK-LABEL: @test30_as1(
|
||||
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i16 [[I:%.*]], 2
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i16 [[GEP1_IDX]], [[J:%.*]]
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i16 [[GEP1_IDX]], [[J:%.*]]
|
||||
; CHECK-NEXT: ret i16 [[GEPDIFF]]
|
||||
;
|
||||
%bit = bitcast i8 addrspace(1)* %foo to i32 addrspace(1)*
|
||||
@ -299,9 +299,11 @@ define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) {
|
||||
ret i16 %sub
|
||||
}
|
||||
|
||||
; Inbounds translates to 'nsw' on sub
|
||||
|
||||
define i64 @gep_diff_both_inbounds(i8* %foo, i64 %i, i64 %j) {
|
||||
; CHECK-LABEL: @gep_diff_both_inbounds(
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[I:%.*]], [[J:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
||||
;
|
||||
%gep1 = getelementptr inbounds i8, i8* %foo, i64 %i
|
||||
@ -312,6 +314,8 @@ define i64 @gep_diff_both_inbounds(i8* %foo, i64 %i, i64 %j) {
|
||||
ret i64 %sub
|
||||
}
|
||||
|
||||
; Negative test for 'nsw' - both geps must be inbounds
|
||||
|
||||
define i64 @gep_diff_first_inbounds(i8* %foo, i64 %i, i64 %j) {
|
||||
; CHECK-LABEL: @gep_diff_first_inbounds(
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
|
||||
@ -325,6 +329,8 @@ define i64 @gep_diff_first_inbounds(i8* %foo, i64 %i, i64 %j) {
|
||||
ret i64 %sub
|
||||
}
|
||||
|
||||
; Negative test for 'nsw' - both geps must be inbounds
|
||||
|
||||
define i64 @gep_diff_second_inbounds(i8* %foo, i64 %i, i64 %j) {
|
||||
; CHECK-LABEL: @gep_diff_second_inbounds(
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]
|
||||
|
@ -1077,7 +1077,7 @@ define i64 @test58([100 x [100 x i8]]* %foo, i64 %i, i64 %j) {
|
||||
; CHECK-LABEL: @test58(
|
||||
; CHECK-NEXT: [[GEP1_OFFS:%.*]] = add i64 [[I:%.*]], 4200
|
||||
; CHECK-NEXT: [[GEP2_OFFS:%.*]] = add i64 [[J:%.*]], 4200
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[GEP1_OFFS]], [[GEP2_OFFS]]
|
||||
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[GEP1_OFFS]], [[GEP2_OFFS]]
|
||||
; CHECK-NEXT: ret i64 [[GEPDIFF]]
|
||||
;
|
||||
%gep1 = getelementptr inbounds [100 x [100 x i8]], [100 x [100 x i8]]* %foo, i64 0, i64 42, i64 %i
|
||||
|
Loading…
Reference in New Issue
Block a user