Skip to content

Commit 4a7abfe

Browse files
committed
[InstCombine] Preserve nuw in OptimizePointerDifference
If both the geps and the subs are nuw the new sub is also nuw. Proof: https://alive2.llvm.org/ce/z/mM8UvF
1 parent 4e80c53 commit 4a7abfe

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,11 +2109,13 @@ Value *InstCombinerImpl::OptimizePointerDifference(Value *LHS, Value *RHS,
21092109

21102110
// If we have a 2nd GEP of the same base pointer, subtract the offsets.
21112111
// If both GEPs are inbounds, then the subtract does not have signed overflow.
2112+
// If both GEPs are nuw and the original sub is nuw, the new sub is also nuw.
21122113
if (GEP2) {
2113-
bool GEP2IsInBounds = GEP2->isInBounds();
21142114
Value *Offset = EmitGEPOffset(GEP2, RewriteGEPs);
2115-
Result = Builder.CreateSub(Result, Offset, "gepdiff", /* NUW */ false,
2116-
GEP1IsInBounds && GEP2IsInBounds);
2115+
Result = Builder.CreateSub(Result, Offset, "gepdiff",
2116+
IsNUW && GEP1->hasNoUnsignedWrap() &&
2117+
GEP2->hasNoUnsignedWrap(),
2118+
GEP1IsInBounds && GEP2->isInBounds());
21172119
}
21182120

21192121
// If we have p - gep(p, ...) then we have to negate the result.

llvm/test/Transforms/InstCombine/sub-gep.ll

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,62 @@ define i64 @test_inbounds_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
156156
ret i64 %d
157157
}
158158

159+
define i64 @test_nusw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
160+
; CHECK-LABEL: @test_nusw_two_gep(
161+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
162+
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
163+
; CHECK-NEXT: ret i64 [[GEPDIFF]]
164+
;
165+
%p1 = getelementptr nusw [0 x i32], ptr %base, i64 0, i64 %idx
166+
%p2 = getelementptr nusw [0 x i32], ptr %base, i64 0, i64 %idx2
167+
%i1 = ptrtoint ptr %p1 to i64
168+
%i2 = ptrtoint ptr %p2 to i64
169+
%d = sub i64 %i2, %i1
170+
ret i64 %d
171+
}
172+
173+
define i64 @test_nuw_two_gep(ptr %base, i64 %idx, i64 %idx2) {
174+
; CHECK-LABEL: @test_nuw_two_gep(
175+
; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i64 [[IDX2:%.*]], [[IDX:%.*]]
176+
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl nuw i64 [[TMP1]], 2
177+
; CHECK-NEXT: ret i64 [[GEPDIFF]]
178+
;
179+
%p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
180+
%p2 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx2
181+
%i1 = ptrtoint ptr %p1 to i64
182+
%i2 = ptrtoint ptr %p2 to i64
183+
%d = sub nuw i64 %i2, %i1
184+
ret i64 %d
185+
}
186+
187+
define i64 @test_nuw_two_gep_missing_nuw_on_sub(ptr %base, i64 %idx, i64 %idx2) {
188+
; CHECK-LABEL: @test_nuw_two_gep_missing_nuw_on_sub(
189+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
190+
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
191+
; CHECK-NEXT: ret i64 [[GEPDIFF]]
192+
;
193+
%p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
194+
%p2 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx2
195+
%i1 = ptrtoint ptr %p1 to i64
196+
%i2 = ptrtoint ptr %p2 to i64
197+
%d = sub i64 %i2, %i1
198+
ret i64 %d
199+
}
200+
201+
define i64 @test_nuw_two_gep_missing_nuw_on_one_gep(ptr %base, i64 %idx, i64 %idx2) {
202+
; CHECK-LABEL: @test_nuw_two_gep_missing_nuw_on_one_gep(
203+
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[IDX2:%.*]], [[IDX:%.*]]
204+
; CHECK-NEXT: [[GEPDIFF:%.*]] = shl i64 [[TMP1]], 2
205+
; CHECK-NEXT: ret i64 [[GEPDIFF]]
206+
;
207+
%p1 = getelementptr nuw [0 x i32], ptr %base, i64 0, i64 %idx
208+
%p2 = getelementptr [0 x i32], ptr %base, i64 0, i64 %idx2
209+
%i1 = ptrtoint ptr %p1 to i64
210+
%i2 = ptrtoint ptr %p2 to i64
211+
%d = sub nuw i64 %i2, %i1
212+
ret i64 %d
213+
}
214+
159215
define i64 @test_inbounds_nuw_multi_index(ptr %base, i64 %idx, i64 %idx2) {
160216
; CHECK-LABEL: @test_inbounds_nuw_multi_index(
161217
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 3

0 commit comments

Comments
 (0)