[DAG] TransformFPLoadStorePair - early out if we're not loading a simple type
[llvm-project.git] / llvm / test / Transforms / SROA / select-gep.ll
blob1342a2ca4ea2bed6ea150c643e4c76bd1e5b67f7
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes='sroa<preserve-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG
3 ; RUN: opt -S -passes='sroa<modify-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG
5 %pair = type { i32, i32 }
7 define i32 @test_sroa_select_gep(i1 %cond) {
8 ; CHECK-LABEL: @test_sroa_select_gep(
9 ; CHECK-NEXT:  bb:
10 ; CHECK-NEXT:    [[LOAD_SROA_SPECULATED:%.*]] = select i1 [[COND:%.*]], i32 1, i32 2
11 ; CHECK-NEXT:    ret i32 [[LOAD_SROA_SPECULATED]]
13 bb:
14   %a = alloca %pair, align 4
15   %b = alloca %pair, align 4
16   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
17   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
18   store i32 1, ptr %gep_a, align 4
19   store i32 2, ptr %gep_b, align 4
20   %select = select i1 %cond, ptr %a, ptr %b
21   %gep = getelementptr inbounds %pair, ptr %select, i32 0, i32 1
22   %load = load i32, ptr %gep, align 4
23   ret i32 %load
26 define i32 @test_sroa_select_gep_non_inbound(i1 %cond) {
27 ; CHECK-LABEL: @test_sroa_select_gep_non_inbound(
28 ; CHECK-NEXT:  bb:
29 ; CHECK-NEXT:    [[LOAD_SROA_SPECULATED:%.*]] = select i1 [[COND:%.*]], i32 1, i32 2
30 ; CHECK-NEXT:    ret i32 [[LOAD_SROA_SPECULATED]]
32 bb:
33   %a = alloca %pair, align 4
34   %b = alloca %pair, align 4
35   %gep_a = getelementptr %pair, ptr %a, i32 0, i32 1
36   %gep_b = getelementptr %pair, ptr %b, i32 0, i32 1
37   store i32 1, ptr %gep_a, align 4
38   store i32 2, ptr %gep_b, align 4
39   %select = select i1 %cond, ptr %a, ptr %b
40   %gep = getelementptr %pair, ptr %select, i32 0, i32 1
41   %load = load i32, ptr %gep, align 4
42   ret i32 %load
45 define i32 @test_sroa_select_gep_volatile_load(i1 %cond) {
46 ; CHECK-LABEL: @test_sroa_select_gep_volatile_load(
47 ; CHECK-NEXT:  bb:
48 ; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
49 ; CHECK-NEXT:    [[A_SROA_2:%.*]] = alloca i32, align 4
50 ; CHECK-NEXT:    [[B_SROA_0:%.*]] = alloca i32, align 4
51 ; CHECK-NEXT:    [[B_SROA_2:%.*]] = alloca i32, align 4
52 ; CHECK-NEXT:    store i32 11, ptr [[A_SROA_0]], align 4
53 ; CHECK-NEXT:    store i32 12, ptr [[B_SROA_0]], align 4
54 ; CHECK-NEXT:    store i32 21, ptr [[A_SROA_2]], align 4
55 ; CHECK-NEXT:    store i32 22, ptr [[B_SROA_2]], align 4
56 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], ptr [[A_SROA_0]], ptr [[B_SROA_0]]
57 ; CHECK-NEXT:    [[LOAD1:%.*]] = load volatile i32, ptr [[SELECT]], align 4
58 ; CHECK-NEXT:    [[SELECT_SROA_SEL:%.*]] = select i1 [[COND]], ptr [[A_SROA_2]], ptr [[B_SROA_2]]
59 ; CHECK-NEXT:    [[LOAD2:%.*]] = load volatile i32, ptr [[SELECT_SROA_SEL]], align 4
60 ; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD2]]
61 ; CHECK-NEXT:    ret i32 [[ADD]]
63 bb:
64   %a = alloca %pair, align 4
65   %b = alloca %pair, align 4
66   store i32 11, ptr %a, align 4
67   store i32 12, ptr %b, align 4
68   %gep_a1 = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
69   %gep_b1 = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
70   store i32 21, ptr %gep_a1, align 4
71   store i32 22, ptr %gep_b1, align 4
72   %select = select i1 %cond, ptr %a, ptr %b
73   %load1 = load volatile i32, ptr %select, align 4
74   %gep2 = getelementptr inbounds %pair, ptr %select, i32 0, i32 1
75   %load2 = load volatile i32, ptr %gep2, align 4
76   %add = add i32 %load1, %load2
77   ret i32 %add
80 define i32 @test_sroa_select_gep_poison(i1 %cond) {
81 ; CHECK-PRESERVE-CFG-LABEL: @test_sroa_select_gep_poison(
82 ; CHECK-PRESERVE-CFG-NEXT:  bb:
83 ; CHECK-PRESERVE-CFG-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
84 ; CHECK-PRESERVE-CFG-NEXT:    [[SELECT_SROA_SEL:%.*]] = select i1 [[COND:%.*]], ptr [[A_SROA_0]], ptr poison
85 ; CHECK-PRESERVE-CFG-NEXT:    [[LOAD:%.*]] = load i32, ptr [[SELECT_SROA_SEL]], align 4
86 ; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[LOAD]]
88 ; CHECK-MODIFY-CFG-LABEL: @test_sroa_select_gep_poison(
89 ; CHECK-MODIFY-CFG-NEXT:  bb:
90 ; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND:%.*]], label [[BB_CONT:%.*]], label [[BB_ELSE:%.*]]
91 ; CHECK-MODIFY-CFG:       bb.else:
92 ; CHECK-MODIFY-CFG-NEXT:    [[LOAD_ELSE_VAL:%.*]] = load i32, ptr poison, align 4
93 ; CHECK-MODIFY-CFG-NEXT:    br label [[BB_CONT]]
94 ; CHECK-MODIFY-CFG:       bb.cont:
95 ; CHECK-MODIFY-CFG-NEXT:    [[LOAD:%.*]] = phi i32 [ undef, [[BB:%.*]] ], [ [[LOAD_ELSE_VAL]], [[BB_ELSE]] ]
96 ; CHECK-MODIFY-CFG-NEXT:    ret i32 [[LOAD]]
98 bb:
99   %a = alloca %pair, align 4
100   %select = select i1 %cond, ptr %a, ptr poison
101   %gep = getelementptr inbounds %pair, ptr %select, i32 0, i32 1
102   %load = load i32, ptr %gep, align 4
103   ret i32 %load
106 define i32 @test_sroa_gep_select_gep(i1 %cond) {
107 ; CHECK-LABEL: @test_sroa_gep_select_gep(
108 ; CHECK-NEXT:  bb:
109 ; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
110 ; CHECK-NEXT:    [[B_SROA_0:%.*]] = alloca i32, align 4
111 ; CHECK-NEXT:    store i32 1, ptr [[A_SROA_0]], align 4
112 ; CHECK-NEXT:    store i32 2, ptr [[B_SROA_0]], align 4
113 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], ptr [[A_SROA_0]], ptr [[B_SROA_0]]
114 ; CHECK-NEXT:    [[SELECT2:%.*]] = select i1 [[COND]], ptr [[SELECT]], ptr [[A_SROA_0]]
115 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[SELECT2]], align 4
116 ; CHECK-NEXT:    ret i32 [[LOAD]]
119   %a = alloca %pair, align 4
120   %b = alloca %pair, align 4
121   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
122   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
123   store i32 1, ptr %gep_a, align 4
124   store i32 2, ptr %gep_b, align 4
125   %select = select i1 %cond, ptr %gep_a, ptr %gep_b
126   %select2 = select i1 %cond, ptr %select, ptr %gep_a
127   %load = load i32, ptr %select2, align 4
128   ret i32 %load
131 define i32 @test_sroa_gep_select_gep_nonconst_idx(i1 %cond, i32 %idx) {
132 ; CHECK-LABEL: @test_sroa_gep_select_gep_nonconst_idx(
133 ; CHECK-NEXT:  bb:
134 ; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
135 ; CHECK-NEXT:    [[B:%.*]] = alloca [[PAIR]], align 4
136 ; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1
137 ; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1
138 ; CHECK-NEXT:    store i32 1, ptr [[GEP_A]], align 4
139 ; CHECK-NEXT:    store i32 2, ptr [[GEP_B]], align 4
140 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND:%.*]], ptr [[A]], ptr [[B]]
141 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[SELECT]], i32 [[IDX:%.*]], i32 1
142 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
143 ; CHECK-NEXT:    ret i32 [[LOAD]]
146   %a = alloca %pair, align 4
147   %b = alloca %pair, align 4
148   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
149   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
150   store i32 1, ptr %gep_a, align 4
151   store i32 2, ptr %gep_b, align 4
152   %select = select i1 %cond, ptr %a, ptr %b
153   %gep = getelementptr inbounds %pair, ptr %select, i32 %idx, i32 1
154   %load = load i32, ptr %gep, align 4
155   ret i32 %load
158 ; Test gep of index select unfolding on an alloca that is splittable, but not
159 ; promotable. The allocas here will be optimized away by subsequent passes.
160 define i32 @test_select_idx_memcpy(i1 %c, ptr %p) {
161 ; CHECK-LABEL: @test_select_idx_memcpy(
162 ; CHECK-NEXT:    [[ALLOCA_SROA_0:%.*]] = alloca [4 x i8], align 8
163 ; CHECK-NEXT:    [[ALLOCA_SROA_2:%.*]] = alloca [20 x i8], align 4
164 ; CHECK-NEXT:    [[ALLOCA_SROA_22:%.*]] = alloca [4 x i8], align 8
165 ; CHECK-NEXT:    [[ALLOCA_SROA_3:%.*]] = alloca [132 x i8], align 4
166 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[ALLOCA_SROA_0]], ptr align 1 [[P:%.*]], i64 4, i1 false)
167 ; CHECK-NEXT:    [[ALLOCA_SROA_2_0_P_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
168 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ALLOCA_SROA_2]], ptr align 1 [[ALLOCA_SROA_2_0_P_SROA_IDX]], i64 20, i1 false)
169 ; CHECK-NEXT:    [[ALLOCA_SROA_22_0_P_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 24
170 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[ALLOCA_SROA_22]], ptr align 1 [[ALLOCA_SROA_22_0_P_SROA_IDX]], i64 4, i1 false)
171 ; CHECK-NEXT:    [[ALLOCA_SROA_3_0_P_SROA_IDX:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 28
172 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[ALLOCA_SROA_3]], ptr align 1 [[ALLOCA_SROA_3_0_P_SROA_IDX]], i64 132, i1 false)
173 ; CHECK-NEXT:    [[IDX:%.*]] = select i1 [[C:%.*]], i64 24, i64 0
174 ; CHECK-NEXT:    [[IDX_SROA_SEL:%.*]] = select i1 [[C]], ptr [[ALLOCA_SROA_22]], ptr [[ALLOCA_SROA_0]]
175 ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[IDX_SROA_SEL]], align 4
176 ; CHECK-NEXT:    ret i32 [[RES]]
178   %alloca = alloca [20 x i64], align 8
179   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr %p, i64 160, i1 false)
180   %idx = select i1 %c, i64 24, i64 0
181   %gep = getelementptr inbounds i8, ptr %alloca, i64 %idx
182   %res = load i32, ptr %gep, align 4
183   ret i32 %res
186 ; Test gep of index select unfolding on an alloca that is splittable and
187 ; promotable.
188 define i32 @test_select_idx_mem2reg(i1 %c) {
189 ; CHECK-LABEL: @test_select_idx_mem2reg(
190 ; CHECK-NEXT:    [[IDX:%.*]] = select i1 [[C:%.*]], i64 24, i64 0
191 ; CHECK-NEXT:    [[RES_SROA_SPECULATED:%.*]] = select i1 [[C]], i32 2, i32 1
192 ; CHECK-NEXT:    ret i32 [[RES_SROA_SPECULATED]]
194   %alloca = alloca [20 x i64], align 8
195   store i32 1, ptr %alloca
196   %gep1 = getelementptr inbounds i8, ptr %alloca, i64 24
197   store i32 2, ptr %gep1
198   %idx = select i1 %c, i64 24, i64 0
199   %gep2 = getelementptr inbounds i8, ptr %alloca, i64 %idx
200   %res = load i32, ptr %gep2, align 4
201   ret i32 %res
204 ; Test gep of index select unfolding on an alloca that escaped, and as such
205 ; is not splittable or promotable.
206 ; FIXME: Ideally, no transform would take place in this case.
207 define i32 @test_select_idx_escaped(i1 %c, ptr %p) {
208 ; CHECK-LABEL: @test_select_idx_escaped(
209 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [20 x i64], align 8
210 ; CHECK-NEXT:    store ptr [[ALLOCA]], ptr [[P:%.*]], align 8
211 ; CHECK-NEXT:    store i32 1, ptr [[ALLOCA]], align 4
212 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 24
213 ; CHECK-NEXT:    store i32 2, ptr [[GEP1]], align 4
214 ; CHECK-NEXT:    [[IDX:%.*]] = select i1 [[C:%.*]], i64 24, i64 0
215 ; CHECK-NEXT:    [[DOTSROA_GEP:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 24
216 ; CHECK-NEXT:    [[DOTSROA_GEP1:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 0
217 ; CHECK-NEXT:    [[IDX_SROA_SEL:%.*]] = select i1 [[C]], ptr [[DOTSROA_GEP]], ptr [[DOTSROA_GEP1]]
218 ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[IDX_SROA_SEL]], align 4
219 ; CHECK-NEXT:    ret i32 [[RES]]
221   %alloca = alloca [20 x i64], align 8
222   store ptr %alloca, ptr %p
223   store i32 1, ptr %alloca
224   %gep1 = getelementptr inbounds i8, ptr %alloca, i64 24
225   store i32 2, ptr %gep1
226   %idx = select i1 %c, i64 24, i64 0
227   %gep2 = getelementptr inbounds i8, ptr %alloca, i64 %idx
228   %res = load i32, ptr %gep2, align 4
229   ret i32 %res
232 ; FIXME: Should we allow recursive select unfolding if all the leaves are
233 ; constants?
234 define i32 @test_select_idx_nested(i1 %c, i1 %c2) {
235 ; CHECK-LABEL: @test_select_idx_nested(
236 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [20 x i64], align 8
237 ; CHECK-NEXT:    store i32 1, ptr [[ALLOCA]], align 4
238 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 8
239 ; CHECK-NEXT:    store i32 2, ptr [[GEP1]], align 4
240 ; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 24
241 ; CHECK-NEXT:    store i32 3, ptr [[GEP2]], align 4
242 ; CHECK-NEXT:    [[IDX1:%.*]] = select i1 [[C:%.*]], i64 24, i64 0
243 ; CHECK-NEXT:    [[IDX2:%.*]] = select i1 [[C2:%.*]], i64 [[IDX1]], i64 8
244 ; CHECK-NEXT:    [[GEP3:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 [[IDX2]]
245 ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[GEP3]], align 4
246 ; CHECK-NEXT:    ret i32 [[RES]]
248   %alloca = alloca [20 x i64], align 8
249   store i32 1, ptr %alloca
250   %gep1 = getelementptr inbounds i8, ptr %alloca, i64 8
251   store i32 2, ptr %gep1
252   %gep2 = getelementptr inbounds i8, ptr %alloca, i64 24
253   store i32 3, ptr %gep2
254   %idx1 = select i1 %c, i64 24, i64 0
255   %idx2 = select i1 %c2, i64 %idx1, i64 8
256   %gep3 = getelementptr inbounds i8, ptr %alloca, i64 %idx2
257   %res = load i32, ptr %gep3, align 4
258   ret i32 %res
261 ; The following cases involve non-constant indices and should not be
262 ; transformed.
264 define i32 @test_select_idx_not_constant1(i1 %c, ptr %p, i64 %arg) {
265 ; CHECK-LABEL: @test_select_idx_not_constant1(
266 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [20 x i64], align 8
267 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[ALLOCA]], ptr [[P:%.*]], i64 160, i1 false)
268 ; CHECK-NEXT:    [[IDX:%.*]] = select i1 [[C:%.*]], i64 24, i64 [[ARG:%.*]]
269 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 [[IDX]]
270 ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[GEP]], align 4
271 ; CHECK-NEXT:    ret i32 [[RES]]
273   %alloca = alloca [20 x i64], align 8
274   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr %p, i64 160, i1 false)
275   %idx = select i1 %c, i64 24, i64 %arg
276   %gep = getelementptr inbounds i8, ptr %alloca, i64 %idx
277   %res = load i32, ptr %gep, align 4
278   ret i32 %res
281 define i32 @test_select_idx_not_constant2(i1 %c, ptr %p, i64 %arg) {
282 ; CHECK-LABEL: @test_select_idx_not_constant2(
283 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [20 x i64], align 8
284 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[ALLOCA]], ptr [[P:%.*]], i64 160, i1 false)
285 ; CHECK-NEXT:    [[IDX:%.*]] = select i1 [[C:%.*]], i64 [[ARG:%.*]], i64 0
286 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i8, ptr [[ALLOCA]], i64 [[IDX]]
287 ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[GEP]], align 4
288 ; CHECK-NEXT:    ret i32 [[RES]]
290   %alloca = alloca [20 x i64], align 8
291   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr %p, i64 160, i1 false)
292   %idx = select i1 %c, i64 %arg, i64 0
293   %gep = getelementptr inbounds i8, ptr %alloca, i64 %idx
294   %res = load i32, ptr %gep, align 4
295   ret i32 %res
298 define i32 @test_select_idx_not_constant3(i1 %c, ptr %p, i64 %arg) {
299 ; CHECK-LABEL: @test_select_idx_not_constant3(
300 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [20 x i64], align 8
301 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i64(ptr [[ALLOCA]], ptr [[P:%.*]], i64 160, i1 false)
302 ; CHECK-NEXT:    [[IDX:%.*]] = select i1 [[C:%.*]], i64 24, i64 0
303 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [1 x i8], ptr [[ALLOCA]], i64 [[IDX]], i64 [[ARG:%.*]]
304 ; CHECK-NEXT:    [[RES:%.*]] = load i32, ptr [[GEP]], align 4
305 ; CHECK-NEXT:    ret i32 [[RES]]
307   %alloca = alloca [20 x i64], align 8
308   call void @llvm.memcpy.p0.p0.i64(ptr %alloca, ptr %p, i64 160, i1 false)
309   %idx = select i1 %c, i64 24, i64 0
310   %gep = getelementptr inbounds [1 x i8], ptr %alloca, i64 %idx, i64 %arg
311   %res = load i32, ptr %gep, align 4
312   ret i32 %res