Skip to content

Commit 2dc44b3

Browse files
authored
[InstCombine] Fix multi-use handling for multi-GEP rewrite (#146689)
If we're expanding offsets for a chain of GEPs in RewriteGEPs mode, we should also rewrite GEPs that have one-use themselves, but are kept alive by a multi-use GEP later in the chain. For the sake of simplicity, I've changed this to just skip the one-use condition entirely (which will perform an unnecessary rewrite of a no longer used GEP, but shouldn't otherwise matter).
1 parent ad715be commit 2dc44b3

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,8 @@ Value *InstCombinerImpl::EmitGEPOffset(GEPOperator *GEP, bool RewriteGEP) {
205205
Builder.SetInsertPoint(Inst);
206206

207207
Value *Offset = EmitGEPOffset(GEP);
208-
// If a non-trivial GEP has other uses, rewrite it to avoid duplicating
209-
// the offset arithmetic.
210-
if (Inst && !GEP->hasOneUse() && !GEP->hasAllConstantIndices() &&
208+
// Rewrite non-trivial GEPs to avoid duplicating the offset arithmetic.
209+
if (Inst && !GEP->hasAllConstantIndices() &&
211210
!GEP->getSourceElementType()->isIntegerTy(8)) {
212211
replaceInstUsesWith(
213212
*Inst, Builder.CreateGEP(Builder.getInt8Ty(), GEP->getPointerOperand(),

llvm/test/Transforms/InstCombine/sub-gep.ll

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,70 @@ define i64 @multiple_geps_two_chains_gep_base(ptr %base, i64 %base.idx, i64 %idx
943943
ret i64 %d
944944
}
945945

946+
define i64 @multiple_geps_two_chains_multi_use(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
947+
; CHECK-LABEL: @multiple_geps_two_chains_multi_use(
948+
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX2:%.*]], 2
949+
; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[P1:%.*]], i64 [[P2_IDX]]
950+
; CHECK-NEXT: [[P4_IDX:%.*]] = shl nsw i64 [[IDX4:%.*]], 2
951+
; CHECK-NEXT: [[P5:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[P4_IDX]]
952+
; CHECK-NEXT: [[P3_IDX:%.*]] = shl nsw i64 [[IDX3:%.*]], 2
953+
; CHECK-NEXT: [[P3:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[P3_IDX]]
954+
; CHECK-NEXT: [[P4_IDX1:%.*]] = shl nsw i64 [[IDX5:%.*]], 2
955+
; CHECK-NEXT: [[P4:%.*]] = getelementptr inbounds i8, ptr [[P3]], i64 [[P4_IDX1]]
956+
; CHECK-NEXT: call void @use(ptr [[P5]])
957+
; CHECK-NEXT: call void @use(ptr [[P4]])
958+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[P2_IDX]], [[P4_IDX]]
959+
; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[P3_IDX]], [[P4_IDX1]]
960+
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
961+
; CHECK-NEXT: ret i64 [[GEPDIFF]]
962+
;
963+
%p1 = getelementptr inbounds i32, ptr %base, i64 %idx1
964+
%p2 = getelementptr inbounds i32, ptr %p1, i64 %idx2
965+
%p3 = getelementptr inbounds i32, ptr %base, i64 %idx3
966+
%p4 = getelementptr inbounds i32, ptr %p3, i64 %idx4
967+
call void @use(ptr %p2)
968+
call void @use(ptr %p4)
969+
%i1 = ptrtoint ptr %p4 to i64
970+
%i2 = ptrtoint ptr %p2 to i64
971+
%d = sub i64 %i2, %i1
972+
ret i64 %d
973+
}
974+
975+
define i64 @multiple_geps_two_chains_partial_multi_use(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4, i64 %idx5, i64 %idx6) {
976+
; CHECK-LABEL: @multiple_geps_two_chains_partial_multi_use(
977+
; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX2:%.*]], 2
978+
; CHECK-NEXT: [[P2:%.*]] = getelementptr inbounds i8, ptr [[P1:%.*]], i64 [[P2_IDX]]
979+
; CHECK-NEXT: [[P4_IDX:%.*]] = shl nsw i64 [[IDX4:%.*]], 2
980+
; CHECK-NEXT: [[P3:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[P4_IDX]]
981+
; CHECK-NEXT: [[P3_IDX:%.*]] = shl nsw i64 [[IDX3:%.*]], 2
982+
; CHECK-NEXT: [[P4_IDX1:%.*]] = shl nsw i64 [[IDX7:%.*]], 2
983+
; CHECK-NEXT: [[P5:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[P4_IDX1]]
984+
; CHECK-NEXT: [[P5_IDX:%.*]] = shl nsw i64 [[IDX5:%.*]], 2
985+
; CHECK-NEXT: [[P4:%.*]] = getelementptr inbounds i8, ptr [[P5]], i64 [[P5_IDX]]
986+
; CHECK-NEXT: [[P6_IDX:%.*]] = shl nsw i64 [[IDX6:%.*]], 2
987+
; CHECK-NEXT: call void @use(ptr [[P3]])
988+
; CHECK-NEXT: call void @use(ptr [[P4]])
989+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[P2_IDX]], [[P4_IDX]]
990+
; CHECK-NEXT: [[TMP2:%.*]] = add nsw i64 [[TMP1]], [[P3_IDX]]
991+
; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[P4_IDX1]], [[P5_IDX]]
992+
; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[TMP3]], [[P6_IDX]]
993+
; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[TMP2]], [[TMP4]]
994+
; CHECK-NEXT: ret i64 [[GEPDIFF]]
995+
;
996+
%p1 = getelementptr inbounds i32, ptr %base, i64 %idx1
997+
%p2 = getelementptr inbounds i32, ptr %p1, i64 %idx2
998+
%p3 = getelementptr inbounds i32, ptr %p2, i64 %idx3
999+
%p4 = getelementptr inbounds i32, ptr %base, i64 %idx4
1000+
%p5 = getelementptr inbounds i32, ptr %p4, i64 %idx5
1001+
%p6 = getelementptr inbounds i32, ptr %p5, i64 %idx6
1002+
call void @use(ptr %p2)
1003+
call void @use(ptr %p5)
1004+
%i1 = ptrtoint ptr %p6 to i64
1005+
%i2 = ptrtoint ptr %p3 to i64
1006+
%d = sub i64 %i2, %i1
1007+
ret i64 %d
1008+
}
1009+
9461010
define i64 @multiple_geps_inbounds(ptr %base, i64 %idx, i64 %idx2) {
9471011
; CHECK-LABEL: @multiple_geps_inbounds(
9481012
; CHECK-NEXT: [[D:%.*]] = add nsw i64 [[IDX:%.*]], [[IDX2:%.*]]

0 commit comments

Comments
 (0)