Skip to content

Commit a301e1a

Browse files
authored
[InstCombine] Split GEPs with multiple non-zero offsets (#151333)
Split GEPs that have more than one non-zero offset into two GEPs. This is in preparation for the ptradd migration, which can only represent such GEPs. This also enables CSE and LICM of the common base.
1 parent bdebbd9 commit a301e1a

23 files changed

+369
-346
lines changed

clang/test/CodeGen/union-tbaa1.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ void bar(vect32 p[][2]);
1919
// CHECK-NEXT: [[MUL:%.*]] = mul i32 [[TMP1]], [[NUM]]
2020
// CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds [2 x %union.vect32], ptr [[TMP]], i32 [[TMP0]]
2121
// CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 8, !tbaa [[TBAA6:![0-9]+]]
22-
// CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [2 x i32], ptr [[ARR]], i32 [[TMP0]], i32 1
22+
// CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX]], i32 4
2323
// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX5]], align 4, !tbaa [[TBAA2]]
2424
// CHECK-NEXT: [[MUL6:%.*]] = mul i32 [[TMP2]], [[NUM]]
25-
// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds [2 x %union.vect32], ptr [[TMP]], i32 [[TMP0]], i32 1
25+
// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX2]], i32 4
2626
// CHECK-NEXT: store i32 [[MUL6]], ptr [[ARRAYIDX8]], align 4, !tbaa [[TBAA6]]
2727
// CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[MUL]], 16
2828
// CHECK-NEXT: store i32 [[TMP3]], ptr [[VEC]], align 4, !tbaa [[TBAA2]]
2929
// CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[INDEX]], align 4, !tbaa [[TBAA2]]
30-
// CHECK-NEXT: [[ARRAYIDX14:%.*]] = getelementptr inbounds [2 x %union.vect32], ptr [[TMP]], i32 [[TMP4]], i32 1
31-
// CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX14]], i32 2
30+
// CHECK-NEXT: [[ARRAYIDX13:%.*]] = getelementptr inbounds [2 x %union.vect32], ptr [[TMP]], i32 [[TMP4]]
31+
// CHECK-NEXT: [[ARRAYIDX15:%.*]] = getelementptr inbounds nuw i8, ptr [[ARRAYIDX13]], i32 6
3232
// CHECK-NEXT: [[TMP5:%.*]] = load i16, ptr [[ARRAYIDX15]], align 2, !tbaa [[TBAA6]]
3333
// CHECK-NEXT: [[CONV16:%.*]] = zext i16 [[TMP5]] to i32
3434
// CHECK-NEXT: [[ARRAYIDX17:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i32 4

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 39 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -2744,125 +2744,53 @@ Instruction *InstCombinerImpl::visitGEPOfGEP(GetElementPtrInst &GEP,
27442744
if (auto *I = combineConstantOffsets(GEP, *this))
27452745
return I;
27462746

2747-
// For constant GEPs, use a more general offset-based folding approach.
2748-
Type *PtrTy = Src->getType()->getScalarType();
2749-
if (GEP.hasAllConstantIndices() &&
2750-
(Src->hasOneUse() || Src->hasAllConstantIndices())) {
2751-
// Split Src into a variable part and a constant suffix.
2752-
gep_type_iterator GTI = gep_type_begin(*Src);
2753-
Type *BaseType = GTI.getIndexedType();
2754-
bool IsFirstType = true;
2755-
unsigned NumVarIndices = 0;
2756-
for (auto Pair : enumerate(Src->indices())) {
2757-
if (!isa<ConstantInt>(Pair.value())) {
2758-
BaseType = GTI.getIndexedType();
2759-
IsFirstType = false;
2760-
NumVarIndices = Pair.index() + 1;
2761-
}
2762-
++GTI;
2763-
}
2764-
2765-
// Determine the offset for the constant suffix of Src.
2766-
APInt Offset(DL.getIndexTypeSizeInBits(PtrTy), 0);
2767-
if (NumVarIndices != Src->getNumIndices()) {
2768-
// FIXME: getIndexedOffsetInType() does not handled scalable vectors.
2769-
if (BaseType->isScalableTy())
2770-
return nullptr;
2771-
2772-
SmallVector<Value *> ConstantIndices;
2773-
if (!IsFirstType)
2774-
ConstantIndices.push_back(
2775-
Constant::getNullValue(Type::getInt32Ty(GEP.getContext())));
2776-
append_range(ConstantIndices, drop_begin(Src->indices(), NumVarIndices));
2777-
Offset += DL.getIndexedOffsetInType(BaseType, ConstantIndices);
2778-
}
2779-
2780-
// Add the offset for GEP (which is fully constant).
2781-
if (!GEP.accumulateConstantOffset(DL, Offset))
2782-
return nullptr;
2783-
2784-
// Convert the total offset back into indices.
2785-
SmallVector<APInt> ConstIndices =
2786-
DL.getGEPIndicesForOffset(BaseType, Offset);
2787-
if (!Offset.isZero() || (!IsFirstType && !ConstIndices[0].isZero()))
2788-
return nullptr;
2789-
2790-
GEPNoWrapFlags NW = getMergedGEPNoWrapFlags(*Src, *cast<GEPOperator>(&GEP));
2791-
SmallVector<Value *> Indices(
2792-
drop_end(Src->indices(), Src->getNumIndices() - NumVarIndices));
2793-
for (const APInt &Idx : drop_begin(ConstIndices, !IsFirstType)) {
2794-
Indices.push_back(ConstantInt::get(GEP.getContext(), Idx));
2795-
// Even if the total offset is inbounds, we may end up representing it
2796-
// by first performing a larger negative offset, and then a smaller
2797-
// positive one. The large negative offset might go out of bounds. Only
2798-
// preserve inbounds if all signs are the same.
2799-
if (Idx.isNonNegative() != ConstIndices[0].isNonNegative())
2800-
NW = NW.withoutNoUnsignedSignedWrap();
2801-
if (!Idx.isNonNegative())
2802-
NW = NW.withoutNoUnsignedWrap();
2803-
}
2804-
2805-
return replaceInstUsesWith(
2806-
GEP, Builder.CreateGEP(Src->getSourceElementType(), Src->getOperand(0),
2807-
Indices, "", NW));
2808-
}
2809-
28102747
if (Src->getResultElementType() != GEP.getSourceElementType())
28112748
return nullptr;
28122749

2813-
SmallVector<Value*, 8> Indices;
2814-
28152750
// Find out whether the last index in the source GEP is a sequential idx.
28162751
bool EndsWithSequential = false;
28172752
for (gep_type_iterator I = gep_type_begin(*Src), E = gep_type_end(*Src);
28182753
I != E; ++I)
28192754
EndsWithSequential = I.isSequential();
2755+
if (!EndsWithSequential)
2756+
return nullptr;
28202757

2821-
// Can we combine the two pointer arithmetics offsets?
2822-
if (EndsWithSequential) {
2823-
// Replace: gep (gep %P, long B), long A, ...
2824-
// With: T = long A+B; gep %P, T, ...
2825-
Value *SO1 = Src->getOperand(Src->getNumOperands()-1);
2826-
Value *GO1 = GEP.getOperand(1);
2827-
2828-
// If they aren't the same type, then the input hasn't been processed
2829-
// by the loop above yet (which canonicalizes sequential index types to
2830-
// intptr_t). Just avoid transforming this until the input has been
2831-
// normalized.
2832-
if (SO1->getType() != GO1->getType())
2833-
return nullptr;
2758+
// Replace: gep (gep %P, long B), long A, ...
2759+
// With: T = long A+B; gep %P, T, ...
2760+
Value *SO1 = Src->getOperand(Src->getNumOperands() - 1);
2761+
Value *GO1 = GEP.getOperand(1);
28342762

2835-
Value *Sum =
2836-
simplifyAddInst(GO1, SO1, false, false, SQ.getWithInstruction(&GEP));
2837-
// Only do the combine when we are sure the cost after the
2838-
// merge is never more than that before the merge.
2839-
if (Sum == nullptr)
2840-
return nullptr;
2763+
// If they aren't the same type, then the input hasn't been processed
2764+
// by the loop above yet (which canonicalizes sequential index types to
2765+
// intptr_t). Just avoid transforming this until the input has been
2766+
// normalized.
2767+
if (SO1->getType() != GO1->getType())
2768+
return nullptr;
28412769

2842-
Indices.append(Src->op_begin()+1, Src->op_end()-1);
2843-
Indices.push_back(Sum);
2844-
Indices.append(GEP.op_begin()+2, GEP.op_end());
2845-
} else if (isa<Constant>(*GEP.idx_begin()) &&
2846-
cast<Constant>(*GEP.idx_begin())->isNullValue() &&
2847-
Src->getNumOperands() != 1) {
2848-
// Otherwise we can do the fold if the first index of the GEP is a zero
2849-
Indices.append(Src->op_begin()+1, Src->op_end());
2850-
Indices.append(GEP.idx_begin()+1, GEP.idx_end());
2851-
}
2852-
2853-
// Don't create GEPs with more than one variable index.
2854-
unsigned NumVarIndices =
2855-
count_if(Indices, [](Value *Idx) { return !isa<Constant>(Idx); });
2856-
if (NumVarIndices > 1)
2770+
Value *Sum =
2771+
simplifyAddInst(GO1, SO1, false, false, SQ.getWithInstruction(&GEP));
2772+
// Only do the combine when we are sure the cost after the
2773+
// merge is never more than that before the merge.
2774+
if (Sum == nullptr)
28572775
return nullptr;
28582776

2859-
if (!Indices.empty())
2860-
return replaceInstUsesWith(
2861-
GEP, Builder.CreateGEP(
2862-
Src->getSourceElementType(), Src->getOperand(0), Indices, "",
2863-
getMergedGEPNoWrapFlags(*Src, *cast<GEPOperator>(&GEP))));
2777+
SmallVector<Value *, 8> Indices;
2778+
Indices.append(Src->op_begin() + 1, Src->op_end() - 1);
2779+
Indices.push_back(Sum);
2780+
Indices.append(GEP.op_begin() + 2, GEP.op_end());
28642781

2865-
return nullptr;
2782+
// Don't create GEPs with more than one non-zero index.
2783+
unsigned NumNonZeroIndices = count_if(Indices, [](Value *Idx) {
2784+
auto *C = dyn_cast<Constant>(Idx);
2785+
return !C || !C->isNullValue();
2786+
});
2787+
if (NumNonZeroIndices > 1)
2788+
return nullptr;
2789+
2790+
return replaceInstUsesWith(
2791+
GEP, Builder.CreateGEP(
2792+
Src->getSourceElementType(), Src->getOperand(0), Indices, "",
2793+
getMergedGEPNoWrapFlags(*Src, *cast<GEPOperator>(&GEP))));
28662794
}
28672795

28682796
Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
@@ -3334,17 +3262,18 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
33343262
return replaceInstUsesWith(GEP, Res);
33353263
}
33363264

3337-
bool SeenVarIndex = false;
3265+
bool SeenNonZeroIndex = false;
33383266
for (auto [IdxNum, Idx] : enumerate(Indices)) {
3339-
if (isa<Constant>(Idx))
3267+
auto *C = dyn_cast<Constant>(Idx);
3268+
if (C && C->isNullValue())
33403269
continue;
33413270

3342-
if (!SeenVarIndex) {
3343-
SeenVarIndex = true;
3271+
if (!SeenNonZeroIndex) {
3272+
SeenNonZeroIndex = true;
33443273
continue;
33453274
}
33463275

3347-
// GEP has multiple variable indices: Split it.
3276+
// GEP has multiple non-zero indices: Split it.
33483277
ArrayRef<Value *> FrontIndices = ArrayRef(Indices).take_front(IdxNum);
33493278
Value *FrontGEP =
33503279
Builder.CreateGEP(GEPEltType, PtrOp, FrontIndices,

llvm/test/Analysis/BasicAA/featuretest.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,14 @@ define i32 @gep_distance_test(ptr %A) {
102102
; cannot alias, even if there is a variable offset between them...
103103
define i32 @gep_distance_test2(ptr %A, i64 %distance) {
104104
; NO_ASSUME-LABEL: @gep_distance_test2(
105-
; NO_ASSUME-NEXT: [[B:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[DISTANCE:%.*]], i32 1
105+
; NO_ASSUME-NEXT: [[B_SPLIT:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[DISTANCE:%.*]]
106+
; NO_ASSUME-NEXT: [[B:%.*]] = getelementptr i8, ptr [[B_SPLIT]], i64 4
106107
; NO_ASSUME-NEXT: store i32 7, ptr [[B]], align 4
107108
; NO_ASSUME-NEXT: ret i32 0
108109
;
109110
; USE_ASSUME-LABEL: @gep_distance_test2(
110-
; USE_ASSUME-NEXT: [[B:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[DISTANCE:%.*]], i32 1
111+
; USE_ASSUME-NEXT: [[B_SPLIT:%.*]] = getelementptr { i32, i32 }, ptr [[A:%.*]], i64 [[DISTANCE:%.*]]
112+
; USE_ASSUME-NEXT: [[B:%.*]] = getelementptr i8, ptr [[B_SPLIT]], i64 4
111113
; USE_ASSUME-NEXT: store i32 7, ptr [[B]], align 4
112114
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[A]], i64 4), "nonnull"(ptr [[A]]), "align"(ptr [[A]], i64 4) ]
113115
; USE_ASSUME-NEXT: ret i32 0

llvm/test/Transforms/InstCombine/2010-11-21-SizeZeroTypeGEP.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ define ptr @foo(ptr %x, i32 %n) {
1515
define ptr @bar(i64 %n, ptr %p) {
1616
; CHECK-LABEL: define ptr @bar(
1717
; CHECK-SAME: i64 [[N:%.*]], ptr [[P:%.*]]) {
18-
; CHECK-NEXT: [[G:%.*]] = getelementptr { {}, [0 x { [0 x i8] }] }, ptr [[P]], i64 0, i32 1, i64 0, i32 0, i64 [[N]]
18+
; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[P]], i64 [[N]]
1919
; CHECK-NEXT: ret ptr [[G]]
2020
;
2121
%g = getelementptr {{}, [0 x {[0 x i8]}]}, ptr %p, i64 %n, i32 1, i64 %n, i32 0, i64 %n

llvm/test/Transforms/InstCombine/gep-merge-constant-indices.ll

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ define ptr @structStruct(ptr %p) {
118118
; result = (ptr) &((struct.B*) p)[i].member1 + 2
119119
define ptr @appendIndex(ptr %p, i64 %i) {
120120
; CHECK-LABEL: @appendIndex(
121-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[P:%.*]], i64 [[I:%.*]], i32 1, i64 2
121+
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[P:%.*]], i64 [[I:%.*]]
122+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 6
122123
; CHECK-NEXT: ret ptr [[TMP1]]
123124
;
124125
%1 = getelementptr inbounds %struct.B, ptr %p, i64 %i, i32 1
@@ -173,7 +174,8 @@ define ptr @partialConstant3(ptr %p) {
173174
; result = &((struct.C*) p + a).member2
174175
define ptr @partialConstantMemberAliasing1(ptr %p, i64 %a) {
175176
; CHECK-LABEL: @partialConstantMemberAliasing1(
176-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]], i32 2
177+
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]]
178+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 8
177179
; CHECK-NEXT: ret ptr [[TMP1]]
178180
;
179181
%1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1
@@ -185,8 +187,8 @@ define ptr @partialConstantMemberAliasing1(ptr %p, i64 %a) {
185187
; address of another member.
186188
define ptr @partialConstantMemberAliasing2(ptr %p, i64 %a) {
187189
; CHECK-LABEL: @partialConstantMemberAliasing2(
188-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]], i32 1
189-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 1
190+
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]]
191+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 5
190192
; CHECK-NEXT: ret ptr [[TMP2]]
191193
;
192194
%1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 1
@@ -198,8 +200,8 @@ define ptr @partialConstantMemberAliasing2(ptr %p, i64 %a) {
198200
; range of the object currently pointed by the non-constant GEP.
199201
define ptr @partialConstantMemberAliasing3(ptr %p, i64 %a) {
200202
; CHECK-LABEL: @partialConstantMemberAliasing3(
201-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]], i32 2
202-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 4
203+
; CHECK-NEXT: [[DOTSPLIT:%.*]] = getelementptr inbounds [[STRUCT_C:%.*]], ptr [[P:%.*]], i64 [[A:%.*]]
204+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i8, ptr [[DOTSPLIT]], i64 12
203205
; CHECK-NEXT: ret ptr [[TMP2]]
204206
;
205207
%1 = getelementptr inbounds %struct.C, ptr %p, i64 %a, i32 2

llvm/test/Transforms/InstCombine/gepofconstgepi8.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ define ptr @test_too_many_indices(ptr %base, i64 %a, i64 %b) {
147147
; CHECK-SAME: ptr [[BASE:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
148148
; CHECK-NEXT: entry:
149149
; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[BASE]], i64 [[B]]
150-
; CHECK-NEXT: [[INDEX:%.*]] = add i64 [[A]], 1
151-
; CHECK-NEXT: [[P2:%.*]] = getelementptr [8 x i32], ptr [[P1]], i64 1, i64 [[INDEX]]
150+
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[P1]], i64 36
151+
; CHECK-NEXT: [[P2:%.*]] = getelementptr i32, ptr [[TMP0]], i64 [[A]]
152152
; CHECK-NEXT: ret ptr [[P2]]
153153
;
154154
entry:

llvm/test/Transforms/InstCombine/gepphigep.ll

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ define i32 @test1(ptr %dm, i1 %c, i64 %idx1, i64 %idx2) {
2121
; CHECK-NEXT: br label [[BB3]]
2222
; CHECK: bb3:
2323
; CHECK-NEXT: [[TMP0:%.*]] = phi i64 [ [[IDX1]], [[BB1]] ], [ [[IDX2]], [[BB2]] ]
24-
; CHECK-NEXT: [[INST24:%.*]] = getelementptr inbounds [[STRUCT2]], ptr [[INST1]], i64 [[TMP0]], i32 1
24+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT2]], ptr [[INST1]], i64 [[TMP0]]
25+
; CHECK-NEXT: [[INST24:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP1]], i64 4
2526
; CHECK-NEXT: [[INST25:%.*]] = load i32, ptr [[INST24]], align 4
2627
; CHECK-NEXT: ret i32 [[INST25]]
2728
;
@@ -76,11 +77,13 @@ define i32 @test3(ptr %dm, i1 %c, i64 %idx1, i64 %idx2, i64 %idx3) personality p
7677
; CHECK-NEXT: bb:
7778
; CHECK-NEXT: br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
7879
; CHECK: bb1:
79-
; CHECK-NEXT: [[INST1:%.*]] = getelementptr inbounds [[STRUCT3:%.*]], ptr [[DM:%.*]], i64 [[IDX1:%.*]], i32 1
80+
; CHECK-NEXT: [[INST1_SPLIT:%.*]] = getelementptr inbounds [[STRUCT3:%.*]], ptr [[DM:%.*]], i64 [[IDX1:%.*]]
81+
; CHECK-NEXT: [[INST1:%.*]] = getelementptr inbounds nuw i8, ptr [[INST1_SPLIT]], i64 4
8082
; CHECK-NEXT: store i32 0, ptr [[INST1]], align 4
8183
; CHECK-NEXT: br label [[BB3:%.*]]
8284
; CHECK: bb2:
83-
; CHECK-NEXT: [[INST12:%.*]] = getelementptr inbounds [[STRUCT3]], ptr [[DM]], i64 [[IDX2:%.*]], i32 1, i32 0, i32 1
85+
; CHECK-NEXT: [[INST2_SPLIT:%.*]] = getelementptr inbounds [[STRUCT3]], ptr [[DM]], i64 [[IDX2:%.*]]
86+
; CHECK-NEXT: [[INST12:%.*]] = getelementptr inbounds nuw i8, ptr [[INST2_SPLIT]], i64 8
8487
; CHECK-NEXT: store i32 0, ptr [[INST12]], align 4
8588
; CHECK-NEXT: br label [[BB3]]
8689
; CHECK: bb3:
@@ -92,8 +95,9 @@ define i32 @test3(ptr %dm, i1 %c, i64 %idx1, i64 %idx2, i64 %idx3) personality p
9295
; CHECK: bb5:
9396
; CHECK-NEXT: [[INST27:%.*]] = landingpad { ptr, i32 }
9497
; CHECK-NEXT: catch ptr @_ZTIi
95-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT3]], ptr [[DM]], i64 [[TMP0]], i32 1
96-
; CHECK-NEXT: [[INST35:%.*]] = getelementptr inbounds [[STRUCT4:%.*]], ptr [[TMP1]], i64 [[IDX3:%.*]], i32 1, i32 1
98+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[STRUCT3]], ptr [[DM]], i64 [[TMP0]]
99+
; CHECK-NEXT: [[INST34_SPLIT:%.*]] = getelementptr [[STRUCT4:%.*]], ptr [[TMP1]], i64 [[IDX3:%.*]]
100+
; CHECK-NEXT: [[INST35:%.*]] = getelementptr i8, ptr [[INST34_SPLIT]], i64 16
97101
; CHECK-NEXT: [[INST25:%.*]] = load i32, ptr [[INST35]], align 4
98102
; CHECK-NEXT: ret i32 [[INST25]]
99103
;

llvm/test/Transforms/InstCombine/getelementptr.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,7 +1947,8 @@ define ptr @gep_merge_nusw_add_zero(ptr %p, i64 %idx, i64 %idx2) {
19471947

19481948
define ptr @gep_merge_nuw_const(ptr %p, i64 %idx, i64 %idx2) {
19491949
; CHECK-LABEL: @gep_merge_nuw_const(
1950-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]], i64 1
1950+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]]
1951+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr nuw i8, ptr [[GEP1]], i64 4
19511952
; CHECK-NEXT: ret ptr [[GEP]]
19521953
;
19531954
%gep1 = getelementptr nuw [2 x i32], ptr %p, i64 %idx
@@ -1970,7 +1971,8 @@ define ptr @gep_merge_nuw_const_neg(ptr %p, i64 %idx, i64 %idx2) {
19701971
; does not overflow.
19711972
define ptr @gep_merge_nusw_const(ptr %p, i64 %idx, i64 %idx2) {
19721973
; CHECK-LABEL: @gep_merge_nusw_const(
1973-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]], i64 1
1974+
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nusw [2 x i32], ptr [[P:%.*]], i64 [[IDX:%.*]]
1975+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr nusw nuw i8, ptr [[GEP1]], i64 4
19741976
; CHECK-NEXT: ret ptr [[GEP]]
19751977
;
19761978
%gep1 = getelementptr nusw [2 x i32], ptr %p, i64 %idx

llvm/test/Transforms/InstCombine/load-cmp.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ define i1 @load_vs_array_type_mismatch_offset2(i32 %idx) {
462462

463463
define i1 @offset_larger_than_stride(i32 %idx) {
464464
; CHECK-LABEL: @offset_larger_than_stride(
465-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr [2 x i16], ptr @g_i16_1, i32 1, i32 [[TMP1:%.*]]
465+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i16, ptr getelementptr inbounds nuw (i8, ptr @g_i16_1, i32 4), i32 [[IDX:%.*]]
466466
; CHECK-NEXT: [[LOAD:%.*]] = load i16, ptr [[GEP]], align 2
467467
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[LOAD]], 0
468468
; CHECK-NEXT: ret i1 [[CMP]]
@@ -554,7 +554,7 @@ entry:
554554
define i1 @cmp_load_constant_additional_positive_offset(i32 %x) {
555555
; CHECK-LABEL: @cmp_load_constant_additional_positive_offset(
556556
; CHECK-NEXT: entry:
557-
; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 5, i32 [[X:%.*]]
557+
; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds i32, ptr getelementptr inbounds nuw (i8, ptr @CG_CLEAR, i32 20), i32 [[X:%.*]]
558558
; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
559559
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], 5
560560
; CHECK-NEXT: ret i1 [[COND]]
@@ -569,7 +569,8 @@ entry:
569569
define i1 @cmp_load_constant_additional_negative_offset(i32 %x) {
570570
; CHECK-LABEL: @cmp_load_constant_additional_negative_offset(
571571
; CHECK-NEXT: entry:
572-
; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 [[X:%.*]], i32 -5
572+
; CHECK-NEXT: [[ISOK_PTR_SPLIT:%.*]] = getelementptr inbounds [1 x i32], ptr @CG_CLEAR, i32 [[X:%.*]]
573+
; CHECK-NEXT: [[ISOK_PTR:%.*]] = getelementptr inbounds i8, ptr [[ISOK_PTR_SPLIT]], i32 -20
573574
; CHECK-NEXT: [[ISOK:%.*]] = load i32, ptr [[ISOK_PTR]], align 4
574575
; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[ISOK]], 5
575576
; CHECK-NEXT: ret i1 [[COND]]

0 commit comments

Comments
 (0)