Skip to content

Commit feaddc1

Browse files
authored
[InstCombine] Preserve inbounds when canonicalizing gep+add (#90160)
When canonicalizing gep+add into gep+gep we can preserve inbounds if the add is also nsw and both add operands are non-negative (or both negative, but I don't think that's practically relevant). Proof: https://alive2.llvm.org/ce/z/tJLBta
1 parent 35b89dd commit feaddc1

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,6 +2948,14 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
29482948
return nullptr;
29492949

29502950
if (GEP.getNumIndices() == 1) {
2951+
// We can only preserve inbounds if the original gep is inbounds, the add
2952+
// is nsw, and the add operands are non-negative.
2953+
auto CanPreserveInBounds = [&](bool AddIsNSW, Value *Idx1, Value *Idx2) {
2954+
SimplifyQuery Q = SQ.getWithInstruction(&GEP);
2955+
return GEP.isInBounds() && AddIsNSW && isKnownNonNegative(Idx1, Q) &&
2956+
isKnownNonNegative(Idx2, Q);
2957+
};
2958+
29512959
// Try to replace ADD + GEP with GEP + GEP.
29522960
Value *Idx1, *Idx2;
29532961
if (match(GEP.getOperand(1),
@@ -2957,10 +2965,15 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
29572965
// as:
29582966
// %newptr = getelementptr i32, ptr %ptr, i64 %idx1
29592967
// %newgep = getelementptr i32, ptr %newptr, i64 %idx2
2960-
auto *NewPtr = Builder.CreateGEP(GEP.getResultElementType(),
2961-
GEP.getPointerOperand(), Idx1);
2962-
return GetElementPtrInst::Create(GEP.getResultElementType(), NewPtr,
2963-
Idx2);
2968+
bool IsInBounds = CanPreserveInBounds(
2969+
cast<OverflowingBinaryOperator>(GEP.getOperand(1))->hasNoSignedWrap(),
2970+
Idx1, Idx2);
2971+
auto *NewPtr =
2972+
Builder.CreateGEP(GEP.getResultElementType(), GEP.getPointerOperand(),
2973+
Idx1, "", IsInBounds);
2974+
return replaceInstUsesWith(
2975+
GEP, Builder.CreateGEP(GEP.getResultElementType(), NewPtr, Idx2, "",
2976+
IsInBounds));
29642977
}
29652978
ConstantInt *C;
29662979
if (match(GEP.getOperand(1), m_OneUse(m_SExtLike(m_OneUse(m_NSWAdd(
@@ -2971,12 +2984,17 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
29712984
// as:
29722985
// %newptr = getelementptr i32, ptr %ptr, i32 %idx1
29732986
// %newgep = getelementptr i32, ptr %newptr, i32 idx2
2987+
bool IsInBounds = CanPreserveInBounds(
2988+
/*IsNSW=*/true, Idx1, C);
29742989
auto *NewPtr = Builder.CreateGEP(
29752990
GEP.getResultElementType(), GEP.getPointerOperand(),
2976-
Builder.CreateSExt(Idx1, GEP.getOperand(1)->getType()));
2977-
return GetElementPtrInst::Create(
2978-
GEP.getResultElementType(), NewPtr,
2979-
Builder.CreateSExt(C, GEP.getOperand(1)->getType()));
2991+
Builder.CreateSExt(Idx1, GEP.getOperand(1)->getType()), "",
2992+
IsInBounds);
2993+
return replaceInstUsesWith(
2994+
GEP,
2995+
Builder.CreateGEP(GEP.getResultElementType(), NewPtr,
2996+
Builder.CreateSExt(C, GEP.getOperand(1)->getType()),
2997+
"", IsInBounds));
29802998
}
29812999
}
29823000

llvm/test/Transforms/InstCombine/array.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ define ptr @gep_inbounds_add_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) {
116116
; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]])
117117
; CHECK-NEXT: [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1
118118
; CHECK-NEXT: call void @llvm.assume(i1 [[B_NNEG]])
119-
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
120-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
119+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[A]]
120+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 [[B]]
121121
; CHECK-NEXT: ret ptr [[GEP]]
122122
;
123123
%a.nneg = icmp sgt i64 %a, -1
@@ -207,8 +207,8 @@ define ptr @gep_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) {
207207
; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1
208208
; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]])
209209
; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[A]] to i64
210-
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]]
211-
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 40
210+
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[TMP1]]
211+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 40
212212
; CHECK-NEXT: ret ptr [[GEP]]
213213
;
214214
%a.nneg = icmp sgt i32 %a, -1

0 commit comments

Comments
 (0)