Skip to content

Commit f7685af

Browse files
committed
[InstCombine] Move gep of phi fold into separate function
This makes sure that an early return during this fold doesn't end up skipping later gep folds.
1 parent d25d040 commit f7685af

32 files changed

+249
-252
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 107 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -2756,6 +2756,111 @@ static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
27562756
});
27572757
}
27582758

2759+
static Instruction *foldGEPOfPhi(GetElementPtrInst &GEP, PHINode *PN,
2760+
IRBuilderBase &Builder) {
2761+
auto *Op1 = dyn_cast<GetElementPtrInst>(PN->getOperand(0));
2762+
if (!Op1)
2763+
return nullptr;
2764+
2765+
// Don't fold a GEP into itself through a PHI node. This can only happen
2766+
// through the back-edge of a loop. Folding a GEP into itself means that
2767+
// the value of the previous iteration needs to be stored in the meantime,
2768+
// thus requiring an additional register variable to be live, but not
2769+
// actually achieving anything (the GEP still needs to be executed once per
2770+
// loop iteration).
2771+
if (Op1 == &GEP)
2772+
return nullptr;
2773+
2774+
int DI = -1;
2775+
2776+
for (auto I = PN->op_begin()+1, E = PN->op_end(); I !=E; ++I) {
2777+
auto *Op2 = dyn_cast<GetElementPtrInst>(*I);
2778+
if (!Op2 || Op1->getNumOperands() != Op2->getNumOperands() ||
2779+
Op1->getSourceElementType() != Op2->getSourceElementType())
2780+
return nullptr;
2781+
2782+
// As for Op1 above, don't try to fold a GEP into itself.
2783+
if (Op2 == &GEP)
2784+
return nullptr;
2785+
2786+
// Keep track of the type as we walk the GEP.
2787+
Type *CurTy = nullptr;
2788+
2789+
for (unsigned J = 0, F = Op1->getNumOperands(); J != F; ++J) {
2790+
if (Op1->getOperand(J)->getType() != Op2->getOperand(J)->getType())
2791+
return nullptr;
2792+
2793+
if (Op1->getOperand(J) != Op2->getOperand(J)) {
2794+
if (DI == -1) {
2795+
// We have not seen any differences yet in the GEPs feeding the
2796+
// PHI yet, so we record this one if it is allowed to be a
2797+
// variable.
2798+
2799+
// The first two arguments can vary for any GEP, the rest have to be
2800+
// static for struct slots
2801+
if (J > 1) {
2802+
assert(CurTy && "No current type?");
2803+
if (CurTy->isStructTy())
2804+
return nullptr;
2805+
}
2806+
2807+
DI = J;
2808+
} else {
2809+
// The GEP is different by more than one input. While this could be
2810+
// extended to support GEPs that vary by more than one variable it
2811+
// doesn't make sense since it greatly increases the complexity and
2812+
// would result in an R+R+R addressing mode which no backend
2813+
// directly supports and would need to be broken into several
2814+
// simpler instructions anyway.
2815+
return nullptr;
2816+
}
2817+
}
2818+
2819+
// Sink down a layer of the type for the next iteration.
2820+
if (J > 0) {
2821+
if (J == 1) {
2822+
CurTy = Op1->getSourceElementType();
2823+
} else {
2824+
CurTy =
2825+
GetElementPtrInst::getTypeAtIndex(CurTy, Op1->getOperand(J));
2826+
}
2827+
}
2828+
}
2829+
}
2830+
2831+
// If not all GEPs are identical we'll have to create a new PHI node.
2832+
// Check that the old PHI node has only one use so that it will get
2833+
// removed.
2834+
if (DI != -1 && !PN->hasOneUse())
2835+
return nullptr;
2836+
2837+
auto *NewGEP = cast<GetElementPtrInst>(Op1->clone());
2838+
if (DI == -1) {
2839+
// All the GEPs feeding the PHI are identical. Clone one down into our
2840+
// BB so that it can be merged with the current GEP.
2841+
} else {
2842+
// All the GEPs feeding the PHI differ at a single offset. Clone a GEP
2843+
// into the current block so it can be merged, and create a new PHI to
2844+
// set that index.
2845+
PHINode *NewPN;
2846+
{
2847+
IRBuilderBase::InsertPointGuard Guard(Builder);
2848+
Builder.SetInsertPoint(PN);
2849+
NewPN = Builder.CreatePHI(Op1->getOperand(DI)->getType(),
2850+
PN->getNumOperands());
2851+
}
2852+
2853+
for (auto &I : PN->operands())
2854+
NewPN->addIncoming(cast<GEPOperator>(I)->getOperand(DI),
2855+
PN->getIncomingBlock(I));
2856+
2857+
NewGEP->setOperand(DI, NewPN);
2858+
}
2859+
2860+
NewGEP->insertBefore(*GEP.getParent(), GEP.getParent()->getFirstInsertionPt());
2861+
return NewGEP;
2862+
}
2863+
27592864
Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
27602865
Value *PtrOp = GEP.getOperand(0);
27612866
SmallVector<Value *, 8> Indices(GEP.indices());
@@ -2846,107 +2951,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
28462951

28472952
// Check to see if the inputs to the PHI node are getelementptr instructions.
28482953
if (auto *PN = dyn_cast<PHINode>(PtrOp)) {
2849-
auto *Op1 = dyn_cast<GetElementPtrInst>(PN->getOperand(0));
2850-
if (!Op1)
2851-
return nullptr;
2852-
2853-
// Don't fold a GEP into itself through a PHI node. This can only happen
2854-
// through the back-edge of a loop. Folding a GEP into itself means that
2855-
// the value of the previous iteration needs to be stored in the meantime,
2856-
// thus requiring an additional register variable to be live, but not
2857-
// actually achieving anything (the GEP still needs to be executed once per
2858-
// loop iteration).
2859-
if (Op1 == &GEP)
2860-
return nullptr;
2861-
2862-
int DI = -1;
2863-
2864-
for (auto I = PN->op_begin()+1, E = PN->op_end(); I !=E; ++I) {
2865-
auto *Op2 = dyn_cast<GetElementPtrInst>(*I);
2866-
if (!Op2 || Op1->getNumOperands() != Op2->getNumOperands() ||
2867-
Op1->getSourceElementType() != Op2->getSourceElementType())
2868-
return nullptr;
2869-
2870-
// As for Op1 above, don't try to fold a GEP into itself.
2871-
if (Op2 == &GEP)
2872-
return nullptr;
2873-
2874-
// Keep track of the type as we walk the GEP.
2875-
Type *CurTy = nullptr;
2876-
2877-
for (unsigned J = 0, F = Op1->getNumOperands(); J != F; ++J) {
2878-
if (Op1->getOperand(J)->getType() != Op2->getOperand(J)->getType())
2879-
return nullptr;
2880-
2881-
if (Op1->getOperand(J) != Op2->getOperand(J)) {
2882-
if (DI == -1) {
2883-
// We have not seen any differences yet in the GEPs feeding the
2884-
// PHI yet, so we record this one if it is allowed to be a
2885-
// variable.
2886-
2887-
// The first two arguments can vary for any GEP, the rest have to be
2888-
// static for struct slots
2889-
if (J > 1) {
2890-
assert(CurTy && "No current type?");
2891-
if (CurTy->isStructTy())
2892-
return nullptr;
2893-
}
2894-
2895-
DI = J;
2896-
} else {
2897-
// The GEP is different by more than one input. While this could be
2898-
// extended to support GEPs that vary by more than one variable it
2899-
// doesn't make sense since it greatly increases the complexity and
2900-
// would result in an R+R+R addressing mode which no backend
2901-
// directly supports and would need to be broken into several
2902-
// simpler instructions anyway.
2903-
return nullptr;
2904-
}
2905-
}
2906-
2907-
// Sink down a layer of the type for the next iteration.
2908-
if (J > 0) {
2909-
if (J == 1) {
2910-
CurTy = Op1->getSourceElementType();
2911-
} else {
2912-
CurTy =
2913-
GetElementPtrInst::getTypeAtIndex(CurTy, Op1->getOperand(J));
2914-
}
2915-
}
2916-
}
2917-
}
2918-
2919-
// If not all GEPs are identical we'll have to create a new PHI node.
2920-
// Check that the old PHI node has only one use so that it will get
2921-
// removed.
2922-
if (DI != -1 && !PN->hasOneUse())
2923-
return nullptr;
2924-
2925-
auto *NewGEP = cast<GetElementPtrInst>(Op1->clone());
2926-
if (DI == -1) {
2927-
// All the GEPs feeding the PHI are identical. Clone one down into our
2928-
// BB so that it can be merged with the current GEP.
2929-
} else {
2930-
// All the GEPs feeding the PHI differ at a single offset. Clone a GEP
2931-
// into the current block so it can be merged, and create a new PHI to
2932-
// set that index.
2933-
PHINode *NewPN;
2934-
{
2935-
IRBuilderBase::InsertPointGuard Guard(Builder);
2936-
Builder.SetInsertPoint(PN);
2937-
NewPN = Builder.CreatePHI(Op1->getOperand(DI)->getType(),
2938-
PN->getNumOperands());
2939-
}
2940-
2941-
for (auto &I : PN->operands())
2942-
NewPN->addIncoming(cast<GEPOperator>(I)->getOperand(DI),
2943-
PN->getIncomingBlock(I));
2944-
2945-
NewGEP->setOperand(DI, NewPN);
2946-
}
2947-
2948-
NewGEP->insertBefore(*GEP.getParent(), GEP.getParent()->getFirstInsertionPt());
2949-
return replaceOperand(GEP, 0, NewGEP);
2954+
if (Value *NewPtrOp = foldGEPOfPhi(GEP, PN, Builder))
2955+
return replaceOperand(GEP, 0, NewPtrOp);
29502956
}
29512957

29522958
if (auto *Src = dyn_cast<GEPOperator>(PtrOp))

llvm/test/Analysis/ValueTracking/phi-known-bits.ll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ define i1 @recursiveGEP_withPtrSub1(ptr %val1) {
436436
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
437437
; CHECK: while.cond.i:
438438
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
439-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
439+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
440440
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
441441
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
442442
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -467,7 +467,7 @@ define i1 @recursiveGEP_withPtrSub1_PhiOperandsCommuted(ptr %val1) {
467467
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
468468
; CHECK: while.cond.i:
469469
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[VAL1:%.*]], [[ENTRY:%.*]] ], [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ]
470-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
470+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
471471
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
472472
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
473473
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -498,7 +498,7 @@ define i1 @recursiveGEP_withPtrSub1_SubOperandsCommuted(ptr %val1) {
498498
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
499499
; CHECK: while.cond.i:
500500
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
501-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
501+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
502502
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
503503
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
504504
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -561,7 +561,7 @@ define i1 @recursiveGEP_withPtrSub3(ptr %val1) {
561561
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
562562
; CHECK: while.cond.i:
563563
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
564-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
564+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
565565
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
566566
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
567567
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -594,7 +594,7 @@ define i1 @recursiveGEP_withPtrSub1_notKnownNonEqual1(ptr %val1, i64 %val2) {
594594
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
595595
; CHECK: while.cond.i:
596596
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
597-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
597+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
598598
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
599599
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
600600
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -629,7 +629,7 @@ define i1 @recursiveGEP_withPtrSub1_notKnownNonEqual2(ptr %val1) {
629629
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
630630
; CHECK: while.cond.i:
631631
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
632-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
632+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
633633
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
634634
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
635635
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -697,7 +697,7 @@ define i1 @recursiveGEP_withPtrSub_maybeZero(ptr %val1) {
697697
; CHECK: while.cond.i:
698698
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
699699
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A_PN_I]], align 2
700-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
700+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
701701
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
702702
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
703703
; CHECK: while.end.i:
@@ -867,7 +867,7 @@ define i1 @recursiveGEP_withPtrSub_noninboundSameDefStartAndB(ptr %val1) {
867867
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
868868
; CHECK: while.cond.i:
869869
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST]], [[ENTRY:%.*]] ]
870-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
870+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
871871
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
872872
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
873873
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -903,7 +903,7 @@ define i1 @recursiveGEP_withPtrSub_noninboundSameStartAndB(ptr %val1) {
903903
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
904904
; CHECK: while.cond.i:
905905
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST]], [[ENTRY:%.*]] ]
906-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
906+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
907907
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
908908
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
909909
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -1004,7 +1004,7 @@ define i1 @recursiveGEP_orcmp(ptr %val1, i64 %val2) {
10041004
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
10051005
; CHECK: while.cond.i:
10061006
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
1007-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
1007+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
10081008
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
10091009
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
10101010
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -1036,7 +1036,7 @@ define i1 @recursiveGEP_orcmp_orOperandsCommuted(ptr %val1, i64 %val2) {
10361036
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
10371037
; CHECK: while.cond.i:
10381038
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
1039-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
1039+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
10401040
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
10411041
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
10421042
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
@@ -1069,7 +1069,7 @@ define i1 @recursiveGEP_orcmpMultiUse(ptr %val1, i64 %val2, ptr %dv1, ptr %dv2)
10691069
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
10701070
; CHECK: while.cond.i:
10711071
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
1072-
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
1072+
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
10731073
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
10741074
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
10751075
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]

llvm/test/Transforms/InstCombine/gepphigep.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,15 @@ define ptr @test4(i32 %value, ptr %buffer) {
144144
; CHECK: loop.body:
145145
; CHECK-NEXT: [[BUFFER_PN:%.*]] = phi ptr [ [[BUFFER:%.*]], [[LOOP_HEADER]] ], [ [[LOOPPTR:%.*]], [[LOOP_BODY]] ]
146146
; CHECK-NEXT: [[NEWVAL:%.*]] = phi i32 [ [[VALUE]], [[LOOP_HEADER]] ], [ [[SHR:%.*]], [[LOOP_BODY]] ]
147-
; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds i8, ptr [[BUFFER_PN]], i64 1
147+
; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds nuw i8, ptr [[BUFFER_PN]], i64 1
148148
; CHECK-NEXT: [[SHR]] = lshr i32 [[NEWVAL]], 7
149149
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[NEWVAL]], 16383
150150
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]]
151151
; CHECK: loop.exit:
152152
; CHECK-NEXT: br label [[EXIT]]
153153
; CHECK: exit:
154154
; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[LOOPPTR]], [[LOOP_EXIT]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
155-
; CHECK-NEXT: [[INCPTR3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 2
155+
; CHECK-NEXT: [[INCPTR3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 2
156156
; CHECK-NEXT: ret ptr [[INCPTR3]]
157157
;
158158
entry:
@@ -203,10 +203,10 @@ define void @test5(ptr %idx, ptr %in) #0 {
203203
; CHECK-NEXT: [[LNOT:%.*]] = icmp eq i8 [[AND]], 0
204204
; CHECK-NEXT: br i1 [[LNOT]], label [[WHILE_BODY]], label [[WHILE_COND_33:%.*]]
205205
; CHECK: while.body:
206-
; CHECK-NEXT: [[INCDEC_PTR32]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
206+
; CHECK-NEXT: [[INCDEC_PTR32]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 1
207207
; CHECK-NEXT: br label [[WHILE_COND]]
208208
; CHECK: while.cond.33:
209-
; CHECK-NEXT: [[INCDEC_PTR34:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
209+
; CHECK-NEXT: [[INCDEC_PTR34:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 1
210210
; CHECK-NEXT: br label [[WHILE_COND_57:%.*]]
211211
; CHECK: while.cond.57:
212212
; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR34]], align 1

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ define ptr @test3_no_inbounds1(ptr %A, i32 %Offset) {
136136
; CHECK: bb:
137137
; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
138138
; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i32 400
139-
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i8, ptr [[RHS]], i32 4
139+
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4
140140
; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
141141
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
142142
; CHECK: bb2:
@@ -194,7 +194,7 @@ define ptr @test3_no_inbounds3(ptr %A, i32 %Offset) {
194194
; CHECK: bb:
195195
; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
196196
; CHECK-NEXT: [[LHS:%.*]] = getelementptr i8, ptr [[A]], i32 400
197-
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i8, ptr [[RHS]], i32 4
197+
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4
198198
; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
199199
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
200200
; CHECK: bb2:

0 commit comments

Comments
 (0)