Skip to content

Commit f7247d5

Browse files
authored
[InstCombine] Canonicalise SextADD + GEP (#69581)
1 parent 98f8b1a commit f7247d5

File tree

2 files changed

+93
-3
lines changed

2 files changed

+93
-3
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2436,15 +2436,31 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
24362436
if (match(GEP.getOperand(1),
24372437
m_OneUse(m_Add(m_Value(Idx1), m_Value(Idx2))))) {
24382438
// %idx = add i64 %idx1, %idx2
2439-
// %gep = getelementptr i32, i32* %ptr, i64 %idx
2439+
// %gep = getelementptr i32, ptr %ptr, i64 %idx
24402440
// as:
2441-
// %newptr = getelementptr i32, i32* %ptr, i64 %idx1
2442-
// %newgep = getelementptr i32, i32* %newptr, i64 %idx2
2441+
// %newptr = getelementptr i32, ptr %ptr, i64 %idx1
2442+
// %newgep = getelementptr i32, ptr %newptr, i64 %idx2
24432443
auto *NewPtr = Builder.CreateGEP(GEP.getResultElementType(),
24442444
GEP.getPointerOperand(), Idx1);
24452445
return GetElementPtrInst::Create(GEP.getResultElementType(), NewPtr,
24462446
Idx2);
24472447
}
2448+
ConstantInt *C;
2449+
if (match(GEP.getOperand(1), m_OneUse(m_SExt(m_OneUse(m_NSWAdd(
2450+
m_Value(Idx1), m_ConstantInt(C))))))) {
2451+
// %add = add nsw i32 %idx1, idx2
2452+
// %sidx = sext i32 %add to i64
2453+
// %gep = getelementptr i32, ptr %ptr, i64 %sidx
2454+
// as:
2455+
// %newptr = getelementptr i32, ptr %ptr, i32 %idx1
2456+
// %newgep = getelementptr i32, ptr %newptr, i32 idx2
2457+
auto *NewPtr = Builder.CreateGEP(
2458+
GEP.getResultElementType(), GEP.getPointerOperand(),
2459+
Builder.CreateSExt(Idx1, GEP.getOperand(1)->getType()));
2460+
return GetElementPtrInst::Create(
2461+
GEP.getResultElementType(), NewPtr,
2462+
Builder.CreateSExt(C, GEP.getOperand(1)->getType()));
2463+
}
24482464
}
24492465

24502466
if (!GEP.isInBounds()) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define void @test(ptr %ptr, i32 %a, i32 %b) {
5+
; CHECK-LABEL: define void @test(
6+
; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
7+
; CHECK-NEXT: entry:
8+
; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[A]] to i64
9+
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP0]]
10+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 10
11+
; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4
12+
; CHECK-NEXT: ret void
13+
;
14+
entry:
15+
%add = add nsw i32 %a, 10
16+
%idx = sext i32 %add to i64
17+
%gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
18+
store i32 %b, ptr %gep
19+
ret void
20+
}
21+
22+
define i32 @test_add_res_moreoneuse(ptr %ptr, i32 %a, i32 %b) {
23+
; CHECK-LABEL: define i32 @test_add_res_moreoneuse(
24+
; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
25+
; CHECK-NEXT: entry:
26+
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[A]], 5
27+
; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64
28+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]]
29+
; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4
30+
; CHECK-NEXT: ret i32 [[ADD]]
31+
;
32+
entry:
33+
%add = add nsw i32 %a, 5
34+
%idx = sext i32 %add to i64
35+
%gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
36+
store i32 %b, ptr %gep
37+
ret i32 %add
38+
}
39+
40+
define void @test_addop_nonsw_flag(ptr %ptr, i32 %a, i32 %b) {
41+
; CHECK-LABEL: define void @test_addop_nonsw_flag(
42+
; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
43+
; CHECK-NEXT: entry:
44+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], 10
45+
; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64
46+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]]
47+
; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4
48+
; CHECK-NEXT: ret void
49+
;
50+
entry:
51+
%add = add i32 %a, 10
52+
%idx = sext i32 %add to i64
53+
%gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
54+
store i32 %b, ptr %gep
55+
ret void
56+
}
57+
58+
define void @test_add_op2_not_constant(ptr %ptr, i32 %a, i32 %b) {
59+
; CHECK-LABEL: define void @test_add_op2_not_constant(
60+
; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
61+
; CHECK-NEXT: entry:
62+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[A]], [[B]]
63+
; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[ADD]] to i64
64+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]]
65+
; CHECK-NEXT: store i32 [[B]], ptr [[GEP]], align 4
66+
; CHECK-NEXT: ret void
67+
;
68+
entry:
69+
%add = add i32 %a, %b
70+
%idx = sext i32 %add to i64
71+
%gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
72+
store i32 %b, ptr %gep
73+
ret void
74+
}

0 commit comments

Comments
 (0)