Skip to content

Commit d01237c

Browse files
authored
[InstCombine] Make indexed compare fold GEP source type independent (#71663)
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. This addresses the main regression from #68882. TBH I have some doubts that this is really a useful transform (at least for the case where there are extra pointer users, so we have to rematerialize pointers at some point). I can only assume it exists for a reason...
1 parent aefca74 commit d01237c

File tree

3 files changed

+61
-96
lines changed

3 files changed

+61
-96
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 25 additions & 66 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,7 +414,7 @@ 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);
@@ -447,11 +448,9 @@ static bool canRewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
447448
return false;
448449

449450
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)
451+
// Only allow inbounds GEPs with at most one variable offset.
452+
auto IsNonConst = [](Value *V) { return !isa<ConstantInt>(V); };
453+
if (!GEP->isInBounds() || count_if(GEP->indices(), IsNonConst) > 1)
455454
return false;
456455

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

529528
/// Returns a re-written value of Start as an indexed GEP using Base as a
530529
/// pointer.
531-
static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
530+
static Value *rewriteGEPAsOffset(Value *Start, Value *Base,
532531
const DataLayout &DL,
533532
SetVector<Value *> &Explored,
534533
InstCombiner &IC) {
@@ -559,29 +558,18 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
559558

560559
// Create all the other instructions.
561560
for (Value *Val : Explored) {
562-
563561
if (NewInsts.contains(Val))
564562
continue;
565563

566564
if (auto *GEP = dyn_cast<GEPOperator>(Val)) {
567-
Value *Index = NewInsts[GEP->getOperand(1)] ? NewInsts[GEP->getOperand(1)]
568-
: GEP->getOperand(1);
569565
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-
}
578-
579-
auto *Op = NewInsts[GEP->getOperand(0)];
566+
Value *Op = NewInsts[GEP->getOperand(0)];
567+
Value *OffsetV = emitGEPOffset(&Builder, DL, GEP);
580568
if (isa<ConstantInt>(Op) && cast<ConstantInt>(Op)->isZero())
581-
NewInsts[GEP] = Index;
569+
NewInsts[GEP] = OffsetV;
582570
else
583571
NewInsts[GEP] = Builder.CreateNSWAdd(
584-
Op, Index, GEP->getOperand(0)->getName() + ".add");
572+
Op, OffsetV, GEP->getOperand(0)->getName() + ".add");
585573
continue;
586574
}
587575
if (isa<PHINode>(Val))
@@ -609,23 +597,14 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
609597
}
610598
}
611599

612-
PointerType *PtrTy = PointerType::get(
613-
Base->getContext(), Start->getType()->getPointerAddressSpace());
614600
for (Value *Val : Explored) {
615601
if (Val == Base)
616602
continue;
617603

618-
// Depending on the type, for external users we have to emit
619-
// a GEP or a GEP + ptrtoint.
620604
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");
605+
// Create GEP for external users.
606+
Value *NewVal = Builder.CreateInBoundsGEP(
607+
Builder.getInt8Ty(), Base, NewInsts[Val], Val->getName() + ".ptr");
629608
IC.replaceInstUsesWith(*cast<Instruction>(Val), NewVal);
630609
// Add old instruction to worklist for DCE. We don't directly remove it
631610
// here because the original compare is one of the users.
@@ -635,32 +614,6 @@ static Value *rewriteGEPAsOffset(Type *ElemTy, Value *Start, Value *Base,
635614
return NewInsts[Start];
636615
}
637616

638-
/// Looks through GEPs in order to express the input Value as a constant
639-
/// 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);
646-
while (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
647-
// We accept only inbouds GEPs here to exclude the possibility of
648-
// overflow.
649-
if (!GEP->isInBounds())
650-
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;
660-
}
661-
return {V, Index};
662-
}
663-
664617
/// Converts (CMP GEPLHS, RHS) if this change would make RHS a constant.
665618
/// We can look through PHIs, GEPs and casts in order to determine a common base
666619
/// between GEPLHS and RHS.
@@ -675,14 +628,19 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
675628
if (!GEPLHS->hasAllConstantIndices())
676629
return nullptr;
677630

678-
Type *ElemTy = GEPLHS->getSourceElementType();
679-
Value *PtrBase, *Index;
680-
std::tie(PtrBase, Index) = getAsConstantIndexedAddress(ElemTy, GEPLHS, DL);
631+
APInt Offset(DL.getIndexTypeSizeInBits(GEPLHS->getType()), 0);
632+
Value *PtrBase =
633+
GEPLHS->stripAndAccumulateConstantOffsets(DL, Offset,
634+
/*AllowNonInbounds*/ false);
635+
636+
// Bail if we looked through addrspacecast.
637+
if (PtrBase->getType() != GEPLHS->getType())
638+
return nullptr;
681639

682640
// The set of nodes that will take part in this transformation.
683641
SetVector<Value *> Nodes;
684642

685-
if (!canRewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes))
643+
if (!canRewriteGEPAsOffset(RHS, PtrBase, DL, Nodes))
686644
return nullptr;
687645

688646
// We know we can re-write this as
@@ -691,13 +649,14 @@ static Instruction *transformToIndexedCompare(GEPOperator *GEPLHS, Value *RHS,
691649
// can't have overflow on either side. We can therefore re-write
692650
// this as:
693651
// OFFSET1 cmp OFFSET2
694-
Value *NewRHS = rewriteGEPAsOffset(ElemTy, RHS, PtrBase, DL, Nodes, IC);
652+
Value *NewRHS = rewriteGEPAsOffset(RHS, PtrBase, DL, Nodes, IC);
695653

696654
// RewriteGEPAsOffset has replaced RHS and all of its uses with a re-written
697655
// GEP having PtrBase as the pointer base, and has returned in NewRHS the
698656
// offset. Since Index is the offset of LHS to the base pointer, we will now
699657
// compare the offsets instead of comparing the pointers.
700-
return new ICmpInst(ICmpInst::getSignedPredicate(Cond), Index, NewRHS);
658+
return new ICmpInst(ICmpInst::getSignedPredicate(Cond),
659+
IC.Builder.getInt(Offset), NewRHS);
701660
}
702661

703662
/// 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:
@@ -157,16 +159,17 @@ bb2:
157159
define ptr@test4(i16 %A, i32 %Offset) {
158160
; CHECK-LABEL: @test4(
159161
; CHECK-NEXT: entry:
162+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
160163
; CHECK-NEXT: br label [[BB:%.*]]
161164
; CHECK: bb:
162-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[ENTRY:%.*]] ]
163-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
164-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
165+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[ENTRY:%.*]] ]
166+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
167+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
165168
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
166169
; CHECK: bb2:
167170
; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[A:%.*]] to i32
168171
; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[TMP0]] to ptr
169-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A_PTR]], i32 [[RHS_IDX]]
172+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
170173
; CHECK-NEXT: ret ptr [[RHS_PTR]]
171174
;
172175
entry:
@@ -195,14 +198,15 @@ define ptr@test5(i32 %Offset) personality ptr @__gxx_personality_v0 {
195198
; CHECK-NEXT: [[A:%.*]] = invoke ptr @fun_ptr()
196199
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
197200
; CHECK: cont:
201+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
198202
; CHECK-NEXT: br label [[BB:%.*]]
199203
; CHECK: bb:
200-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[CONT]] ]
201-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
202-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
204+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]
205+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
206+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
203207
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
204208
; CHECK: bb2:
205-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[RHS_IDX]]
209+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A]], i32 [[RHS_IDX]]
206210
; CHECK-NEXT: ret ptr [[RHS_PTR]]
207211
; CHECK: lpad:
208212
; CHECK-NEXT: [[L:%.*]] = landingpad { ptr, i32 }
@@ -239,15 +243,16 @@ define ptr@test6(i32 %Offset) personality ptr @__gxx_personality_v0 {
239243
; CHECK-NEXT: [[A:%.*]] = invoke i32 @fun_i32()
240244
; CHECK-NEXT: to label [[CONT:%.*]] unwind label [[LPAD:%.*]]
241245
; CHECK: cont:
246+
; CHECK-NEXT: [[TMP_IDX:%.*]] = shl nsw i32 [[OFFSET:%.*]], 2
242247
; CHECK-NEXT: br label [[BB:%.*]]
243248
; CHECK: bb:
244-
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[OFFSET:%.*]], [[CONT]] ]
245-
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 1
246-
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 100
249+
; CHECK-NEXT: [[RHS_IDX:%.*]] = phi i32 [ [[RHS_ADD:%.*]], [[BB]] ], [ [[TMP_IDX]], [[CONT]] ]
250+
; CHECK-NEXT: [[RHS_ADD]] = add nsw i32 [[RHS_IDX]], 4
251+
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[RHS_IDX]], 400
247252
; CHECK-NEXT: br i1 [[COND]], label [[BB2:%.*]], label [[BB]]
248253
; CHECK: bb2:
249254
; CHECK-NEXT: [[A_PTR:%.*]] = inttoptr i32 [[A]] to ptr
250-
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i32, ptr [[A_PTR]], i32 [[RHS_IDX]]
255+
; CHECK-NEXT: [[RHS_PTR:%.*]] = getelementptr inbounds i8, ptr [[A_PTR]], i32 [[RHS_IDX]]
251256
; CHECK-NEXT: ret ptr [[RHS_PTR]]
252257
; CHECK: lpad:
253258
; 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)