Skip to content

Commit d248f7d

Browse files
committed
[InstCombine] Make indexed compare fold GEP source type independent
The indexed compare fold converts comparisons of GEPs with same (indirect) base into comparisons of offset. Currently, it only supports GEPs with the same source element type. This change makes the transform operate on offsets instead, which removes the type dependence. To keep closer to the scope of the original implementation, this keeps the limitation that we should only have at most one variable index per GEP.
1 parent 567c02a commit d248f7d

File tree

3 files changed

+72
-89
lines changed

3 files changed

+72
-89
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 36 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/Analysis/CmpInstAnalysis.h"
1919
#include "llvm/Analysis/ConstantFolding.h"
2020
#include "llvm/Analysis/InstructionSimplify.h"
21+
#include "llvm/Analysis/Utils/Local.h"
2122
#include "llvm/Analysis/VectorUtils.h"
2223
#include "llvm/IR/ConstantRange.h"
2324
#include "llvm/IR/DataLayout.h"
@@ -413,11 +414,12 @@ Instruction *InstCombinerImpl::foldCmpLoadFromIndexedGlobal(
413414
/// Returns true if we can rewrite Start as a GEP with pointer Base
414415
/// and some integer offset. The nodes that need to be re-written
415416
/// for this transformation will be added to Explored.
416-
static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
417+
static bool canRewriteGEPAsOffset(Value *Start, Value *Base,
417418
const DataLayout &DL,
418419
SetVector<Value *> &Explored) {
419420
SmallVector<Value *, 16> WorkList(1, Start);
420421
Explored.insert(Base);
422+
uint64_t IndexSize = DL.getIndexTypeSizeInBits(Start->getType());
421423

422424
// The following traversal gives us an order which can be used
423425
// when doing the final transformation. Since in the final
@@ -447,11 +449,11 @@ static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
447449
return false;
448450

449451
if (auto *GEP = dyn_cast<GEPOperator>(V)) {
450-
// We're limiting the GEP to having one index. This will preserve
451-
// the original pointer type. We could handle more cases in the
452-
// future.
453-
if (GEP->getNumIndices() != 1 || !GEP->isInBounds() ||
454-
GEP->getSourceElementType() != ElemTy)
452+
// Only allow GEPs with at most one variable offset.
453+
APInt Offset(IndexSize, 0);
454+
MapVector<Value *, APInt> VarOffsets;
455+
if (!GEP->collectOffset(DL, IndexSize, VarOffsets, Offset) ||
456+
VarOffsets.size() > 1)
455457
return false;
456458

457459
if (!Explored.contains(GEP->getOperand(0)))
@@ -528,7 +530,7 @@ static void setInsertionPoint(IRBuilder<> &Builder, Value *V,
528530

529531
/// Returns a re-written value of Start as an indexed GEP using Base as a
530532
/// pointer.
531-
static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
533+
static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
532534
const DataLayout &DL,
533535
SetVector<Value *> &Explored,
534536
InstCombiner &IC) {
@@ -539,8 +541,8 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
539541
// 3. Add the edges for the PHI nodes.
540542
// 4. Emit GEPs to get the original pointers.
541543
// 5. Remove the original instructions.
542-
Type *IndexType = IntegerType::get(
543-
Base->getContext(), DL.getIndexTypeSizeInBits(Start->getType()));
544+
uint64_t IndexSize = DL.getIndexTypeSizeInBits(Start->getType());
545+
Type *IndexType = IntegerType::get(Base->getContext(), IndexSize);
544546

545547
DenseMap<Value *, Value *> NewInsts;
546548
NewInsts[Base] = ConstantInt::getNullValue(IndexType);
@@ -559,29 +561,22 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
559561

560562
// Create all the other instructions.
561563
for (Value *Val : Explored) {
562-
563564
if (NewInsts.contains(Val))
564565
continue;
565566

566567
if (auto *GEP = dyn_cast<GEPOperator>(Val)) {
567-
Value *Index = NewInsts[GEP->getOperand(1)] ? NewInsts[GEP->getOperand(1)]
568-
: GEP->getOperand(1);
569-
setInsertionPoint(Builder, GEP);
570-
// Indices might need to be sign extended. GEPs will magically do
571-
// this, but we need to do it ourselves here.
572-
if (Index->getType()->getScalarSizeInBits() !=
573-
NewInsts[GEP->getOperand(0)]->getType()->getScalarSizeInBits()) {
574-
Index = Builder.CreateSExtOrTrunc(
575-
Index, NewInsts[GEP->getOperand(0)]->getType(),
576-
GEP->getOperand(0)->getName() + ".sext");
577-
}
568+
APInt Offset(IndexSize, 0);
569+
MapVector<Value *, APInt> VarOffsets;
570+
GEP->collectOffset(DL, IndexSize, VarOffsets, Offset);
578571

579-
auto *Op = NewInsts[GEP->getOperand(0)];
572+
setInsertionPoint(Builder, GEP);
573+
Value *Op = NewInsts[GEP->getOperand(0)];
574+
Value *OffsetV = emitGEPOffset(&Builder, DL, GEP);
580575
if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero())
581-
NewInsts[GEP] = Index;
576+
NewInsts[GEP] = OffsetV;
582577
else
583578
NewInsts[GEP] = Builder.CreateNSWAdd(
584-
Op, Index, GEP->getOperand(0)->getName() + ".add");
579+
Op, OffsetV, GEP->getOperand(0)->getName() + ".add");
585580
continue;
586581
}
587582
if (isa<PHINode>(Val))
@@ -609,23 +604,14 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
609604
}
610605
}
611606

612-
PointerType *PtrTy = PointerType::get(
613-
Base->getContext(), Start->getType()->getPointerAddressSpace());
614607
for (Value *Val : Explored) {
615608
if (Val == Base)
616609
continue;
617610

618-
// Depending on the type, for external users we have to emit
619-
// a GEP or a GEP + ptrtoint.
620611
setInsertionPoint(Builder, Val, false);
621-
622-
// Cast base to the expected type.
623-
Value *NewVal = Builder.CreateBitOrPointerCast(
624-
Base, PtrTy, Start->getName() + "to.ptr");
625-
NewVal = Builder.CreateInBoundsGEP(ElemTy, NewVal, ArrayRef(NewInsts[Val]),
626-
Val->getName() + ".ptr");
627-
NewVal = Builder.CreateBitOrPointerCast(
628-
NewVal, Val->getType(), Val->getName() + ".conv");
612+
// Create GEP for external users.
613+
Value *NewVal = Builder.CreateInBoundsGEP(
614+
Builder.getInt8Ty(), Base, NewInsts[Val], Val->getName() + ".ptr");
629615
IC.replaceInstUsesWith(*cast<Instruction>(Val), NewVal);
630616
// Add old instruction to worklist for DCE. We don't directly remove it
631617
// here because the original compare is one of the users.
@@ -637,28 +623,18 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
637623

638624
/// Looks through GEPs in order to express the input Value as a constant
639625
/// indexed GEP. Returns a pair containing the GEPs Pointer and Index.
640-
static std::pair<Value *, Value *>
641-
getAsConstantIndexedAddress(Type *ElemTy, Value *V, const DataLayout &DL) {
642-
Type *IndexType = IntegerType::get(V->getContext(),
643-
DL.getIndexTypeSizeInBits(V->getType()));
644-
645-
Constant *Index = ConstantInt::getNullValue(IndexType);
626+
static std::pair<Value *, APInt>
627+
getAsConstantIndexedAddress(Value *V, const DataLayout &DL) {
628+
APInt Offset = APInt(DL.getIndexTypeSizeInBits(V->getType()), 0);
646629
while (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
647630
// We accept only inbouds GEPs here to exclude the possibility of
648631
// overflow.
649-
if (!GEP->isInBounds())
632+
if (!GEP->isInBounds() || !GEP->accumulateConstantOffset(DL, Offset))
650633
break;
651-
if (GEP->hasAllConstantIndices() && GEP->getNumIndices() == 1 &&
652-
GEP->getSourceElementType() == ElemTy &&
653-
GEP->getOperand(1)->getType() == IndexType) {
654-
V = GEP->getOperand(0);
655-
Constant *GEPIndex = static_cast<Constant *>(GEP->getOperand(1));
656-
Index = ConstantExpr::getAdd(Index, GEPIndex);
657-
continue;
658-
}
659-
break;
634+
635+
V = GEP->getPointerOperand();
660636
}
661-
return {V, Index};
637+
return {V, Offset};
662638
}
663639

664640
/// Converts (CMP GEPLHS, RHS) if this change would make RHS a constant.
@@ -675,14 +651,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
675651
if (!GEPLHS->hasAllConstantIndices())
676652
return nullptr;
677653

678-
Type *ElemTy = GEPLHS->getSourceElementType();
679-
Value *PtrBase, *Index;
680-
std::tie(PtrBase, Index) = getAsConstantIndexedAddress(ElemTy, GEPLHS, DL);
654+
Value *PtrBase;
655+
APInt Offset;
656+
std::tie(PtrBase, Offset) = getAsConstantIndexedAddress(GEPLHS, DL);
681657

682658
// The set of nodes that will take part in this transformation.
683659
SetVector<Value *> Nodes;
684660

685-
if (!canRewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes))
661+
if (!canRewriteGEPAsOffset(RHS, PtrBase, DL, Nodes))
686662
return nullptr;
687663

688664
// We know we can re-write this as
@@ -691,13 +667,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
691667
// can't have overflow on either side. We can therefore re-write
692668
// this as:
693669
// OFFSET1 cmp OFFSET2
694-
Value *NewRHS = rewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes, IC);
670+
Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, DL, Nodes, IC);
695671

696672
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
697673
// GEP having PtrBase as the pointer base, and has returned in NewRHS the
698674
// offset. Since Index is the offset of LHS to the base pointer, we will now
699675
// compare the offsets instead of comparing the pointers.
700-
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Index, NewRHS);
676+
return new ICmpInst(ICmpInst::getSignedPredicate(Cond),
677+
IC.Builder.getInt(Offset), NewRHS);
701678
}
702679

703680
/// Fold comparisons between a GEP instruction and something else. At this point

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

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f3
66
define ptr@test1(ptr %A, i32 %Offset) {
77
; CHECK-LABEL: @test1(
88
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
910
; CHECK-NEXT: br label [[BB:%.*]]
1011
; CHECK: bb:
11-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
12-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
13-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
12+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
13+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
14+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
1415
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
1516
; CHECK: bb2:
16-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i32 [[RHS_IDX]]
17+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i32 [[RHS_IDX]]
1718
; CHECK-NEXT: ret ptr [[RHS_PTR]]
1819
;
1920
entry:
@@ -34,15 +35,16 @@ bb2:
3435
define ptr@test2(i32 %A, i32 %Offset) {
3536
; CHECK-LABEL: @test2(
3637
; CHECK-NEXT: entry:
38+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
3739
; CHECK-NEXT: br label [[BB:%.*]]
3840
; CHECK: bb:
39-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
40-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
41-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
41+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
42+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
43+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
4244
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
4345
; CHECK: bb2:
4446
; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[A:%.*]] to ptr
45-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A_PTR]], i32 [[RHS_IDX]]
47+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
4648
; CHECK-NEXT: ret ptr [[RHS_PTR]]
4749
;
4850
entry:
@@ -99,16 +101,17 @@ bb2:
99101
define ptr@test4(i16 %A, i32 %Offset) {
100102
; CHECK-LABEL: @test4(
101103
; CHECK-NEXT: entry:
104+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
102105
; CHECK-NEXT: br label [[BB:%.*]]
103106
; CHECK: bb:
104-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
105-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
106-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
107+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
108+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
109+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
107110
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
108111
; CHECK: bb2:
109112
; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[A:%.*]] to i32
110113
; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[TMP0]] to ptr
111-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A_PTR]], i32 [[RHS_IDX]]
114+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
112115
; CHECK-NEXT: ret ptr [[RHS_PTR]]
113116
;
114117
entry:
@@ -137,14 +140,15 @@ define ptr@test5(i32 %Offset) personality ptr @__gxx_personality_v0 {
137140
; CHECK-NEXT: [[A:%.*]] = invoke ptr @fun_ptr()
138141
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
139142
; CHECK: cont:
143+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
140144
; CHECK-NEXT: br label [[BB:%.*]]
141145
; CHECK: bb:
142-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[CONT]] ]
143-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
144-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
146+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]
147+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
148+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
145149
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
146150
; CHECK: bb2:
147-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[RHS_IDX]]
151+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 [[RHS_IDX]]
148152
; CHECK-NEXT: ret ptr [[RHS_PTR]]
149153
; CHECK: lpad:
150154
; CHECK-NEXT: [[L:%.*]] = landingpad { ptr, i32 }
@@ -181,15 +185,16 @@ define ptr@test6(i32 %Offset) personality ptr @__gxx_personality_v0 {
181185
; CHECK-NEXT: [[A:%.*]] = invoke i32 @fun_i32()
182186
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
183187
; CHECK: cont:
188+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
184189
; CHECK-NEXT: br label [[BB:%.*]]
185190
; CHECK: bb:
186-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[CONT]] ]
187-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
188-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
191+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]
192+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
193+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
189194
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
190195
; CHECK: bb2:
191196
; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[A]] to ptr
192-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A_PTR]], i32 [[RHS_IDX]]
197+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
193198
; CHECK-NEXT: ret ptr [[RHS_PTR]]
194199
; CHECK: lpad:
195200
; CHECK-NEXT: [[L:%.*]] = landingpad { ptr, i32 }

llvm/test/Transforms/InstCombine/opaque-ptr.ll

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -382,14 +382,15 @@ define <4 x i1> @compare_geps_same_indices_scalar_vector_base_mismatch(ptr %ptr,
382382
define ptr @indexed_compare(ptr %A, i64 %offset) {
383383
; CHECK-LABEL: @indexed_compare(
384384
; CHECK-NEXT: entry:
385+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 2
385386
; CHECK-NEXT: br label [[BB:%.*]]
386387
; CHECK: bb:
387-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i64 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
388-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i64 [[RHS_IDX]], 1
389-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[RHS_IDX]], 100
388+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i64 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
389+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i64 [[RHS_IDX]], 4
390+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[RHS_IDX]], 400
390391
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
391392
; CHECK: bb2:
392-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[RHS_IDX]]
393+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[RHS_IDX]]
393394
; CHECK-NEXT: ret ptr [[RHS_PTR]]
394395
;
395396
entry:
@@ -410,16 +411,16 @@ bb2:
410411
define ptr @indexed_compare_different_types(ptr %A, i64 %offset) {
411412
; CHECK-LABEL: @indexed_compare_different_types(
412413
; CHECK-NEXT: entry:
413-
; CHECK-NEXT: [[TMP:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[OFFSET:%.*]]
414+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i64 [[OFFSET:%.*]], 2
414415
; CHECK-NEXT: br label [[BB:%.*]]
415416
; CHECK: bb:
416-
; CHECK-NEXT: [[RHS:%.*]] = phi ptr [ [[RHS_NEXT:%.*]], [[BB]] ], [ [[TMP]], [[ENTRY:%.*]] ]
417-
; CHECK-NEXT: [[LHS:%.*]] = getelementptr inbounds i64, ptr [[A]], i64 100
418-
; CHECK-NEXT: [[RHS_NEXT]] = getelementptr inbounds i32, ptr [[RHS]], i64 1
419-
; CHECK-NEXT: [[COND:%.*]] = icmp ult ptr [[LHS]], [[RHS]]
417+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i64 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
418+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i64 [[RHS_IDX]], 4
419+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[RHS_IDX]], 800
420420
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
421421
; CHECK: bb2:
422-
; CHECK-NEXT: ret ptr [[RHS]]
422+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A:%.*]], i64 [[RHS_IDX]]
423+
; CHECK-NEXT: ret ptr [[RHS_PTR]]
423424
;
424425
entry:
425426
%tmp = getelementptr inbounds i32, ptr %A, i64 %offset

0 commit comments

Comments
 (0)