Skip to content

Commit d4d2d7d

Browse files
authored
[InstCombine] Preserve nuw in canonicalizeGEPOfConstGEPI8() (#151533)
Proof: https://alive2.llvm.org/ce/z/4j8U3f
1 parent f616127 commit d4d2d7d

File tree

2 files changed

+191
-2
lines changed

2 files changed

+191
-2
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,9 +2654,18 @@ static Instruction *canonicalizeGEPOfConstGEPI8(GetElementPtrInst &GEP,
26542654
APInt NewOffset = TypeSize * *C2 + *C1;
26552655
if (NewOffset.isZero() ||
26562656
(Src->hasOneUse() && GEP.getOperand(1)->hasOneUse())) {
2657+
GEPNoWrapFlags Flags = GEPNoWrapFlags::none();
2658+
if (GEP.hasNoUnsignedWrap() &&
2659+
cast<GEPOperator>(Src)->hasNoUnsignedWrap() &&
2660+
match(GEP.getOperand(1), m_NUWAddLike(m_Value(), m_Value()))) {
2661+
Flags |= GEPNoWrapFlags::noUnsignedWrap();
2662+
if (GEP.isInBounds() && cast<GEPOperator>(Src)->isInBounds())
2663+
Flags |= GEPNoWrapFlags::inBounds();
2664+
}
2665+
26572666
Value *GEPConst =
2658-
IC.Builder.CreatePtrAdd(Base, IC.Builder.getInt(NewOffset));
2659-
return GetElementPtrInst::Create(BaseType, GEPConst, VarIndex);
2667+
IC.Builder.CreatePtrAdd(Base, IC.Builder.getInt(NewOffset), "", Flags);
2668+
return GetElementPtrInst::Create(BaseType, GEPConst, VarIndex, Flags);
26602669
}
26612670

26622671
return nullptr;

llvm/test/Transforms/InstCombine/gepofconstgepi8.ll

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,3 +293,183 @@ entry:
293293
%p2 = getelementptr <vscale x 4 x i32>, ptr %p1, i64 %index
294294
ret ptr %p2
295295
}
296+
297+
define ptr @test_all_nuw(ptr %base, i64 %a) {
298+
; CHECK-LABEL: define ptr @test_all_nuw(
299+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
300+
; CHECK-NEXT: entry:
301+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
302+
; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
303+
; CHECK-NEXT: ret ptr [[P2]]
304+
;
305+
entry:
306+
%p1 = getelementptr nuw i8, ptr %base, i64 1
307+
%index = add nuw i64 %a, 2
308+
%p2 = getelementptr nuw i32, ptr %p1, i64 %index
309+
ret ptr %p2
310+
}
311+
312+
define ptr @test_all_partial_nuw1(ptr %base, i64 %a) {
313+
; CHECK-LABEL: define ptr @test_all_partial_nuw1(
314+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
315+
; CHECK-NEXT: entry:
316+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
317+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
318+
; CHECK-NEXT: ret ptr [[P2]]
319+
;
320+
entry:
321+
%p1 = getelementptr i8, ptr %base, i64 1
322+
%index = add nuw i64 %a, 2
323+
%p2 = getelementptr nuw i32, ptr %p1, i64 %index
324+
ret ptr %p2
325+
}
326+
327+
define ptr @test_all_partial_nuw2(ptr %base, i64 %a) {
328+
; CHECK-LABEL: define ptr @test_all_partial_nuw2(
329+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
330+
; CHECK-NEXT: entry:
331+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
332+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
333+
; CHECK-NEXT: ret ptr [[P2]]
334+
;
335+
entry:
336+
%p1 = getelementptr nuw i8, ptr %base, i64 1
337+
%index = add i64 %a, 2
338+
%p2 = getelementptr nuw i32, ptr %p1, i64 %index
339+
ret ptr %p2
340+
}
341+
342+
define ptr @test_all_partial_nuw3(ptr %base, i64 %a) {
343+
; CHECK-LABEL: define ptr @test_all_partial_nuw3(
344+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
345+
; CHECK-NEXT: entry:
346+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
347+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
348+
; CHECK-NEXT: ret ptr [[P2]]
349+
;
350+
entry:
351+
%p1 = getelementptr nuw i8, ptr %base, i64 1
352+
%index = add nuw i64 %a, 2
353+
%p2 = getelementptr i32, ptr %p1, i64 %index
354+
ret ptr %p2
355+
}
356+
357+
define ptr @test_all_nuw_disjoint(ptr %base, i64 %a) {
358+
; CHECK-LABEL: define ptr @test_all_nuw_disjoint(
359+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
360+
; CHECK-NEXT: entry:
361+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
362+
; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
363+
; CHECK-NEXT: ret ptr [[P2]]
364+
;
365+
entry:
366+
%p1 = getelementptr nuw i8, ptr %base, i64 1
367+
%index = or disjoint i64 %a, 2
368+
%p2 = getelementptr nuw i32, ptr %p1, i64 %index
369+
ret ptr %p2
370+
}
371+
372+
define ptr @test_all_inbounds_nuw(ptr %base, i64 %a) {
373+
; CHECK-LABEL: define ptr @test_all_inbounds_nuw(
374+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
375+
; CHECK-NEXT: entry:
376+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE]], i64 9
377+
; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP0]], i64 [[A]]
378+
; CHECK-NEXT: ret ptr [[P2]]
379+
;
380+
entry:
381+
%p1 = getelementptr inbounds nuw i8, ptr %base, i64 1
382+
%index = add nuw i64 %a, 2
383+
%p2 = getelementptr inbounds nuw i32, ptr %p1, i64 %index
384+
ret ptr %p2
385+
}
386+
387+
define ptr @test_all_partial_inbounds1(ptr %base, i64 %a) {
388+
; CHECK-LABEL: define ptr @test_all_partial_inbounds1(
389+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
390+
; CHECK-NEXT: entry:
391+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
392+
; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
393+
; CHECK-NEXT: ret ptr [[P2]]
394+
;
395+
entry:
396+
%p1 = getelementptr nuw i8, ptr %base, i64 1
397+
%index = add nuw i64 %a, 2
398+
%p2 = getelementptr inbounds nuw i32, ptr %p1, i64 %index
399+
ret ptr %p2
400+
}
401+
402+
define ptr @test_all_partial_inbounds2(ptr %base, i64 %a) {
403+
; CHECK-LABEL: define ptr @test_all_partial_inbounds2(
404+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
405+
; CHECK-NEXT: entry:
406+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
407+
; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
408+
; CHECK-NEXT: ret ptr [[P2]]
409+
;
410+
entry:
411+
%p1 = getelementptr inbounds nuw i8, ptr %base, i64 1
412+
%index = add nuw i64 %a, 2
413+
%p2 = getelementptr nuw i32, ptr %p1, i64 %index
414+
ret ptr %p2
415+
}
416+
417+
define ptr @test_all_inbounds_partial_nuw1(ptr %base, i64 %a) {
418+
; CHECK-LABEL: define ptr @test_all_inbounds_partial_nuw1(
419+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
420+
; CHECK-NEXT: entry:
421+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 7
422+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
423+
; CHECK-NEXT: ret ptr [[P2]]
424+
;
425+
entry:
426+
%p1 = getelementptr inbounds i8, ptr %base, i64 -1
427+
%index = add nuw i64 %a, 2
428+
%p2 = getelementptr inbounds nuw i32, ptr %p1, i64 %index
429+
ret ptr %p2
430+
}
431+
432+
define ptr @test_all_inbounds_partial_nuw2(ptr %base, i64 %a) {
433+
; CHECK-LABEL: define ptr @test_all_inbounds_partial_nuw2(
434+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
435+
; CHECK-NEXT: entry:
436+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
437+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
438+
; CHECK-NEXT: ret ptr [[P2]]
439+
;
440+
entry:
441+
%p1 = getelementptr inbounds nuw i8, ptr %base, i64 1
442+
%index = add nuw i64 %a, 2
443+
%p2 = getelementptr inbounds i32, ptr %p1, i64 %index
444+
ret ptr %p2
445+
}
446+
447+
define ptr @test_all_inbounds_partial_nuw3(ptr %base, i64 %a) {
448+
; CHECK-LABEL: define ptr @test_all_inbounds_partial_nuw3(
449+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
450+
; CHECK-NEXT: entry:
451+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[BASE]], i64 9
452+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
453+
; CHECK-NEXT: ret ptr [[P2]]
454+
;
455+
entry:
456+
%p1 = getelementptr inbounds nuw i8, ptr %base, i64 1
457+
%index = add i64 %a, 2
458+
%p2 = getelementptr inbounds nuw i32, ptr %p1, i64 %index
459+
ret ptr %p2
460+
}
461+
462+
define ptr @test_all_nusw_nuw(ptr %base, i64 %a) {
463+
; CHECK-LABEL: define ptr @test_all_nusw_nuw(
464+
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]]) {
465+
; CHECK-NEXT: entry:
466+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 9
467+
; CHECK-NEXT: [[P2:%.*]] = getelementptr nuw i32, ptr [[TMP0]], i64 [[A]]
468+
; CHECK-NEXT: ret ptr [[P2]]
469+
;
470+
entry:
471+
%p1 = getelementptr nusw nuw i8, ptr %base, i64 1
472+
%index = add nsw nuw i64 %a, 2
473+
%p2 = getelementptr nusw nuw i32, ptr %p1, i64 %index
474+
ret ptr %p2
475+
}

0 commit comments

Comments
 (0)