Skip to content

Commit

Permalink
[InstCombine] Move gep of phi fold into separate function
Browse files Browse the repository at this point in the history
This makes sure that an early return during this fold doesn't end
up skipping later gep folds.
  • Loading branch information
nikic committed Dec 5, 2024
1 parent d25d040 commit f7685af
Show file tree
Hide file tree
Showing 32 changed files with 249 additions and 252 deletions.
208 changes: 107 additions & 101 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2756,6 +2756,111 @@ static bool shouldCanonicalizeGEPToPtrAdd(GetElementPtrInst &GEP) {
});
}

static Instruction *foldGEPOfPhi(GetElementPtrInst &GEP, PHINode *PN,
IRBuilderBase &Builder) {
auto *Op1 = dyn_cast<GetElementPtrInst>(PN->getOperand(0));
if (!Op1)
return nullptr;

// Don't fold a GEP into itself through a PHI node. This can only happen
// through the back-edge of a loop. Folding a GEP into itself means that
// the value of the previous iteration needs to be stored in the meantime,
// thus requiring an additional register variable to be live, but not
// actually achieving anything (the GEP still needs to be executed once per
// loop iteration).
if (Op1 == &GEP)
return nullptr;

int DI = -1;

for (auto I = PN->op_begin()+1, E = PN->op_end(); I !=E; ++I) {
auto *Op2 = dyn_cast<GetElementPtrInst>(*I);
if (!Op2 || Op1->getNumOperands() != Op2->getNumOperands() ||
Op1->getSourceElementType() != Op2->getSourceElementType())
return nullptr;

// As for Op1 above, don't try to fold a GEP into itself.
if (Op2 == &GEP)
return nullptr;

// Keep track of the type as we walk the GEP.
Type *CurTy = nullptr;

for (unsigned J = 0, F = Op1->getNumOperands(); J != F; ++J) {
if (Op1->getOperand(J)->getType() != Op2->getOperand(J)->getType())
return nullptr;

if (Op1->getOperand(J) != Op2->getOperand(J)) {
if (DI == -1) {
// We have not seen any differences yet in the GEPs feeding the
// PHI yet, so we record this one if it is allowed to be a
// variable.

// The first two arguments can vary for any GEP, the rest have to be
// static for struct slots
if (J > 1) {
assert(CurTy && "No current type?");
if (CurTy->isStructTy())
return nullptr;
}

DI = J;
} else {
// The GEP is different by more than one input. While this could be
// extended to support GEPs that vary by more than one variable it
// doesn't make sense since it greatly increases the complexity and
// would result in an R+R+R addressing mode which no backend
// directly supports and would need to be broken into several
// simpler instructions anyway.
return nullptr;
}
}

// Sink down a layer of the type for the next iteration.
if (J > 0) {
if (J == 1) {
CurTy = Op1->getSourceElementType();
} else {
CurTy =
GetElementPtrInst::getTypeAtIndex(CurTy, Op1->getOperand(J));
}
}
}
}

// If not all GEPs are identical we'll have to create a new PHI node.
// Check that the old PHI node has only one use so that it will get
// removed.
if (DI != -1 && !PN->hasOneUse())
return nullptr;

auto *NewGEP = cast<GetElementPtrInst>(Op1->clone());
if (DI == -1) {
// All the GEPs feeding the PHI are identical. Clone one down into our
// BB so that it can be merged with the current GEP.
} else {
// All the GEPs feeding the PHI differ at a single offset. Clone a GEP
// into the current block so it can be merged, and create a new PHI to
// set that index.
PHINode *NewPN;
{
IRBuilderBase::InsertPointGuard Guard(Builder);
Builder.SetInsertPoint(PN);
NewPN = Builder.CreatePHI(Op1->getOperand(DI)->getType(),
PN->getNumOperands());
}

for (auto &I : PN->operands())
NewPN->addIncoming(cast<GEPOperator>(I)->getOperand(DI),
PN->getIncomingBlock(I));

NewGEP->setOperand(DI, NewPN);
}

NewGEP->insertBefore(*GEP.getParent(), GEP.getParent()->getFirstInsertionPt());
return NewGEP;
}

Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Value *PtrOp = GEP.getOperand(0);
SmallVector<Value *, 8> Indices(GEP.indices());
Expand Down Expand Up @@ -2846,107 +2951,8 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {

// Check to see if the inputs to the PHI node are getelementptr instructions.
if (auto *PN = dyn_cast<PHINode>(PtrOp)) {
auto *Op1 = dyn_cast<GetElementPtrInst>(PN->getOperand(0));
if (!Op1)
return nullptr;

// Don't fold a GEP into itself through a PHI node. This can only happen
// through the back-edge of a loop. Folding a GEP into itself means that
// the value of the previous iteration needs to be stored in the meantime,
// thus requiring an additional register variable to be live, but not
// actually achieving anything (the GEP still needs to be executed once per
// loop iteration).
if (Op1 == &GEP)
return nullptr;

int DI = -1;

for (auto I = PN->op_begin()+1, E = PN->op_end(); I !=E; ++I) {
auto *Op2 = dyn_cast<GetElementPtrInst>(*I);
if (!Op2 || Op1->getNumOperands() != Op2->getNumOperands() ||
Op1->getSourceElementType() != Op2->getSourceElementType())
return nullptr;

// As for Op1 above, don't try to fold a GEP into itself.
if (Op2 == &GEP)
return nullptr;

// Keep track of the type as we walk the GEP.
Type *CurTy = nullptr;

for (unsigned J = 0, F = Op1->getNumOperands(); J != F; ++J) {
if (Op1->getOperand(J)->getType() != Op2->getOperand(J)->getType())
return nullptr;

if (Op1->getOperand(J) != Op2->getOperand(J)) {
if (DI == -1) {
// We have not seen any differences yet in the GEPs feeding the
// PHI yet, so we record this one if it is allowed to be a
// variable.

// The first two arguments can vary for any GEP, the rest have to be
// static for struct slots
if (J > 1) {
assert(CurTy && "No current type?");
if (CurTy->isStructTy())
return nullptr;
}

DI = J;
} else {
// The GEP is different by more than one input. While this could be
// extended to support GEPs that vary by more than one variable it
// doesn't make sense since it greatly increases the complexity and
// would result in an R+R+R addressing mode which no backend
// directly supports and would need to be broken into several
// simpler instructions anyway.
return nullptr;
}
}

// Sink down a layer of the type for the next iteration.
if (J > 0) {
if (J == 1) {
CurTy = Op1->getSourceElementType();
} else {
CurTy =
GetElementPtrInst::getTypeAtIndex(CurTy, Op1->getOperand(J));
}
}
}
}

// If not all GEPs are identical we'll have to create a new PHI node.
// Check that the old PHI node has only one use so that it will get
// removed.
if (DI != -1 && !PN->hasOneUse())
return nullptr;

auto *NewGEP = cast<GetElementPtrInst>(Op1->clone());
if (DI == -1) {
// All the GEPs feeding the PHI are identical. Clone one down into our
// BB so that it can be merged with the current GEP.
} else {
// All the GEPs feeding the PHI differ at a single offset. Clone a GEP
// into the current block so it can be merged, and create a new PHI to
// set that index.
PHINode *NewPN;
{
IRBuilderBase::InsertPointGuard Guard(Builder);
Builder.SetInsertPoint(PN);
NewPN = Builder.CreatePHI(Op1->getOperand(DI)->getType(),
PN->getNumOperands());
}

for (auto &I : PN->operands())
NewPN->addIncoming(cast<GEPOperator>(I)->getOperand(DI),
PN->getIncomingBlock(I));

NewGEP->setOperand(DI, NewPN);
}

NewGEP->insertBefore(*GEP.getParent(), GEP.getParent()->getFirstInsertionPt());
return replaceOperand(GEP, 0, NewGEP);
if (Value *NewPtrOp = foldGEPOfPhi(GEP, PN, Builder))
return replaceOperand(GEP, 0, NewPtrOp);
}

if (auto *Src = dyn_cast<GEPOperator>(PtrOp))
Expand Down
24 changes: 12 additions & 12 deletions llvm/test/Analysis/ValueTracking/phi-known-bits.ll
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ define i1 @recursiveGEP_withPtrSub1(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -467,7 +467,7 @@ define i1 @recursiveGEP_withPtrSub1_PhiOperandsCommuted(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[VAL1:%.*]], [[ENTRY:%.*]] ], [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -498,7 +498,7 @@ define i1 @recursiveGEP_withPtrSub1_SubOperandsCommuted(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -561,7 +561,7 @@ define i1 @recursiveGEP_withPtrSub3(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -594,7 +594,7 @@ define i1 @recursiveGEP_withPtrSub1_notKnownNonEqual1(ptr %val1, i64 %val2) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -629,7 +629,7 @@ define i1 @recursiveGEP_withPtrSub1_notKnownNonEqual2(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST_VAL1]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -697,7 +697,7 @@ define i1 @recursiveGEP_withPtrSub_maybeZero(ptr %val1) {
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[A_PN_I]], align 2
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
; CHECK: while.end.i:
Expand Down Expand Up @@ -867,7 +867,7 @@ define i1 @recursiveGEP_withPtrSub_noninboundSameDefStartAndB(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -903,7 +903,7 @@ define i1 @recursiveGEP_withPtrSub_noninboundSameStartAndB(ptr %val1) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[TEST]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -1004,7 +1004,7 @@ define i1 @recursiveGEP_orcmp(ptr %val1, i64 %val2) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -1036,7 +1036,7 @@ define i1 @recursiveGEP_orcmp_orOperandsCommuted(ptr %val1, i64 %val2) {
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down Expand Up @@ -1069,7 +1069,7 @@ define i1 @recursiveGEP_orcmpMultiUse(ptr %val1, i64 %val2, ptr %dv1, ptr %dv2)
; CHECK-NEXT: br label [[WHILE_COND_I:%.*]]
; CHECK: while.cond.i:
; CHECK-NEXT: [[A_PN_I:%.*]] = phi ptr [ [[TEST_0_I:%.*]], [[WHILE_COND_I]] ], [ [[VAL1:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TEST_0_I]] = getelementptr inbounds nuw i8, ptr [[A_PN_I]], i64 1
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[TEST_0_I]], align 2
; CHECK-NEXT: [[CMP3_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[CMP3_NOT_I]], label [[WHILE_END_I:%.*]], label [[WHILE_COND_I]]
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/InstCombine/gepphigep.ll
Original file line number Diff line number Diff line change
Expand Up @@ -144,15 +144,15 @@ define ptr @test4(i32 %value, ptr %buffer) {
; CHECK: loop.body:
; CHECK-NEXT: [[BUFFER_PN:%.*]] = phi ptr [ [[BUFFER:%.*]], [[LOOP_HEADER]] ], [ [[LOOPPTR:%.*]], [[LOOP_BODY]] ]
; CHECK-NEXT: [[NEWVAL:%.*]] = phi i32 [ [[VALUE]], [[LOOP_HEADER]] ], [ [[SHR:%.*]], [[LOOP_BODY]] ]
; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds i8, ptr [[BUFFER_PN]], i64 1
; CHECK-NEXT: [[LOOPPTR]] = getelementptr inbounds nuw i8, ptr [[BUFFER_PN]], i64 1
; CHECK-NEXT: [[SHR]] = lshr i32 [[NEWVAL]], 7
; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[NEWVAL]], 16383
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP_BODY]], label [[LOOP_EXIT:%.*]]
; CHECK: loop.exit:
; CHECK-NEXT: br label [[EXIT]]
; CHECK: exit:
; CHECK-NEXT: [[TMP0:%.*]] = phi ptr [ [[LOOPPTR]], [[LOOP_EXIT]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[INCPTR3:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 2
; CHECK-NEXT: [[INCPTR3:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 2
; CHECK-NEXT: ret ptr [[INCPTR3]]
;
entry:
Expand Down Expand Up @@ -203,10 +203,10 @@ define void @test5(ptr %idx, ptr %in) #0 {
; CHECK-NEXT: [[LNOT:%.*]] = icmp eq i8 [[AND]], 0
; CHECK-NEXT: br i1 [[LNOT]], label [[WHILE_BODY]], label [[WHILE_COND_33:%.*]]
; CHECK: while.body:
; CHECK-NEXT: [[INCDEC_PTR32]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
; CHECK-NEXT: [[INCDEC_PTR32]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 1
; CHECK-NEXT: br label [[WHILE_COND]]
; CHECK: while.cond.33:
; CHECK-NEXT: [[INCDEC_PTR34:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
; CHECK-NEXT: [[INCDEC_PTR34:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR]], i64 1
; CHECK-NEXT: br label [[WHILE_COND_57:%.*]]
; CHECK: while.cond.57:
; CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR34]], align 1
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/indexed-gep-compares.ll
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ define ptr @test3_no_inbounds1(ptr %A, i32 %Offset) {
; CHECK: bb:
; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds nuw i8, ptr [[A]], i32 400
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i8, ptr [[RHS]], i32 4
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4
; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
; CHECK: bb2:
Expand Down Expand Up @@ -194,7 +194,7 @@ define ptr @test3_no_inbounds3(ptr %A, i32 %Offset) {
; CHECK: bb:
; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
; CHECK-NEXT: [[LHS:%.*]] = getelementptr i8, ptr [[A]], i32 400
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i8, ptr [[RHS]], i32 4
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds nuw i8, ptr [[RHS]], i32 4
; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
; CHECK: bb2:
Expand Down
Loading

0 comments on commit f7685af

Please sign in to comment.