Skip to content

Commit c9ecd43

Browse files
nikicSterling-Augustine
authored andcommitted
[InstCombine] Preserve nuw flag in indexed compare fold
If all the involved GEPs have the nuw flag, also preserve it on the resulting adds and GEPs.
1 parent 2370f30 commit c9ecd43

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
423423
/// Returns true if we can rewrite Start as a GEP with pointer Base
424424
/// and some integer offset. The nodes that need to be re-written
425425
/// for this transformation will be added to Explored.
426-
static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
426+
static bool canRewriteGEPAsOffset(Value *Start, Value *Base, GEPNoWrapFlags &NW,
427427
const DataLayout &DL,
428428
SetVector<Value *> &Explored) {
429429
SmallVector<Value *, 16> WorkList(1, Start);
@@ -462,6 +462,7 @@ static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
462462
if (!GEP->isInBounds() || count_if(GEP->indices(), IsNonConst) > 1)
463463
return false;
464464

465+
NW = NW.intersectForOffsetAdd(GEP->getNoWrapFlags());
465466
if (!Explored.contains(GEP->getOperand(0)))
466467
WorkList.push_back(GEP->getOperand(0));
467468
}
@@ -536,7 +537,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
536537

537538
/// Returns a re-written value of Start as an indexed GEP using Base as a
538539
/// pointer.
539-
static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
540+
static Value *rewriteGEPAsOffset(Value *Start, Value *Base, GEPNoWrapFlags NW,
540541
const DataLayout &DL,
541542
SetVector<Value *> &Explored,
542543
InstCombiner &IC) {
@@ -578,8 +579,10 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
578579
if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero())
579580
NewInsts[GEP] = OffsetV;
580581
else
581-
NewInsts[GEP] = Builder.CreateNSWAdd(
582-
Op, OffsetV, GEP->getOperand(0)->getName() + ".add");
582+
NewInsts[GEP] = Builder.CreateAdd(
583+
Op, OffsetV, GEP->getOperand(0)->getName() + ".add",
584+
/*NUW=*/NW.hasNoUnsignedWrap(),
585+
/*NSW=*/NW.hasNoUnsignedSignedWrap());
583586
continue;
584587
}
585588
if (isa<PHINode>(Val))
@@ -613,8 +616,8 @@ static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
613616

614617
setInsertionPoint(Builder, Val, false);
615618
// Create GEP for external users.
616-
Value *NewVal = Builder.CreateInBoundsGEP(
617-
Builder.getInt8Ty(), Base, NewInsts[Val], Val->getName() + ".ptr");
619+
Value *NewVal = Builder.CreateGEP(Builder.getInt8Ty(), Base, NewInsts[Val],
620+
Val->getName() + ".ptr", NW);
618621
IC.replaceInstUsesWith(*cast<Instruction>(Val), NewVal);
619622
// Add old instruction to worklist for DCE. We don't directly remove it
620623
// here because the original compare is one of the users.
@@ -649,8 +652,8 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
649652

650653
// The set of nodes that will take part in this transformation.
651654
SetVector<Value *> Nodes;
652-
653-
if (!canRewriteGEPAsOffset(RHS, PtrBase, DL, Nodes))
655+
GEPNoWrapFlags NW = GEPLHS->getNoWrapFlags();
656+
if (!canRewriteGEPAsOffset(RHS, PtrBase, NW, DL, Nodes))
654657
return nullptr;
655658

656659
// We know we can re-write this as
@@ -659,7 +662,7 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
659662
// can't have overflow on either side. We can therefore re-write
660663
// this as:
661664
// OFFSET1 cmp OFFSET2
662-
Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, DL, Nodes, IC);
665+
Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, NW, DL, Nodes, IC);
663666

664667
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
665668
// GEP having PtrBase as the pointer base, and has returned in NewRHS the

llvm/test/Transforms/InstCombine/indexed-gep-compares.ll

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,64 @@ bb2:
3232
ret ptr %RHS
3333
}
3434

35+
define ptr @test1_nuw(ptr %A, i32 %Offset) {
36+
; CHECK-LABEL: @test1_nuw(
37+
; CHECK-NEXT: entry:
38+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nuw nsw i32 [[OFFSET:%.*]], 2
39+
; CHECK-NEXT: br label [[BB:%.*]]
40+
; CHECK: bb:
41+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
42+
; CHECK-NEXT: [[RHS_ADD]] = add nuw nsw i32 [[RHS_IDX]], 4
43+
; CHECK-NEXT: [[COND:%.*]] = icmp ugt i32 [[RHS_IDX]], 400
44+
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
45+
; CHECK: bb2:
46+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
47+
; CHECK-NEXT: ret ptr [[RHS_PTR]]
48+
;
49+
entry:
50+
%tmp = getelementptr inbounds nuw i32, ptr %A, i32 %Offset
51+
br label %bb
52+
53+
bb:
54+
%RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
55+
%LHS = getelementptr inbounds nuw i32, ptr %A, i32 100
56+
%RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 1
57+
%cond = icmp ult ptr %LHS, %RHS
58+
br i1 %cond, label %bb2, label %bb
59+
60+
bb2:
61+
ret ptr %RHS
62+
}
63+
64+
define ptr @test1_not_all_nuw(ptr %A, i32 %Offset) {
65+
; CHECK-LABEL: @test1_not_all_nuw(
66+
; CHECK-NEXT: entry:
67+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
68+
; CHECK-NEXT: br label [[BB:%.*]]
69+
; CHECK: bb:
70+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
71+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
72+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
73+
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
74+
; CHECK: bb2:
75+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
76+
; CHECK-NEXT: ret ptr [[RHS_PTR]]
77+
;
78+
entry:
79+
%tmp = getelementptr inbounds i32, ptr %A, i32 %Offset
80+
br label %bb
81+
82+
bb:
83+
%RHS = phi ptr [ %RHS.next, %bb ], [ %tmp, %entry ]
84+
%LHS = getelementptr inbounds nuw i32, ptr %A, i32 100
85+
%RHS.next = getelementptr inbounds nuw i32, ptr %RHS, i64 1
86+
%cond = icmp ult ptr %LHS, %RHS
87+
br i1 %cond, label %bb2, label %bb
88+
89+
bb2:
90+
ret ptr %RHS
91+
}
92+
3593
define ptr@test2(i32 %A, i32 %Offset) {
3694
; CHECK-LABEL: @test2(
3795
; CHECK-NEXT: entry:

0 commit comments

Comments
 (0)