Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / SROA / phi-gep.ll
blob776624c0798cfb9ec121f750e00bf0ce3f2dc09f
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_phi_gep(i1 %cond) {
8 ; CHECK-LABEL: @test_sroa_phi_gep(
9 ; CHECK-NEXT:  entry:
10 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
11 ; CHECK:       if.then:
12 ; CHECK-NEXT:    br label [[END]]
13 ; CHECK:       end:
14 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ]
15 ; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
17 entry:
18   %a = alloca %pair, align 4
19   %b = alloca %pair, align 4
20   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
21   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
22   store i32 1, ptr %gep_a, align 4
23   store i32 2, ptr %gep_b, align 4
24   br i1 %cond, label %if.then, label %end
26 if.then:
27   br label %end
29 end:
30   %phi = phi ptr [ %a, %entry], [ %b, %if.then ]
31   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
32   %load = load i32, ptr %gep, align 4
33   ret i32 %load
36 define i32 @test_sroa_phi_gep_non_inbound(i1 %cond) {
37 ; CHECK-LABEL: @test_sroa_phi_gep_non_inbound(
38 ; CHECK-NEXT:  entry:
39 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
40 ; CHECK:       if.then:
41 ; CHECK-NEXT:    br label [[END]]
42 ; CHECK:       end:
43 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ]
44 ; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
46 entry:
47   %a = alloca %pair, align 4
48   %b = alloca %pair, align 4
49   %gep_a = getelementptr %pair, ptr %a, i32 0, i32 1
50   %gep_b = getelementptr %pair, ptr %b, i32 0, i32 1
51   store i32 1, ptr %gep_a, align 4
52   store i32 2, ptr %gep_b, align 4
53   br i1 %cond, label %if.then, label %end
55 if.then:
56   br label %end
58 end:
59   %phi = phi ptr [ %a, %entry], [ %b, %if.then ]
60   %gep = getelementptr %pair, ptr %phi, i32 0, i32 1
61   %load = load i32, ptr %gep, align 4
62   ret i32 %load
65 define i32 @test_sroa_phi_gep_poison(i1 %cond) {
66 ; CHECK-LABEL: @test_sroa_phi_gep_poison(
67 ; CHECK-NEXT:  entry:
68 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
69 ; CHECK:       if.then:
70 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr poison, align 4
71 ; CHECK-NEXT:    br label [[END]]
72 ; CHECK:       end:
73 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN]], [[IF_THEN]] ]
74 ; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
76 entry:
77   %a = alloca %pair, align 4
78   br i1 %cond, label %if.then, label %end
80 if.then:
81   br label %end
83 end:
84   %phi = phi ptr [ %a, %entry], [ poison, %if.then ]
85   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
86   %load = load i32, ptr %gep, align 4
87   ret i32 %load
90 @g = global %pair zeroinitializer, align 4
92 define i32 @test_sroa_phi_gep_global(i1 %cond) {
93 ; CHECK-LABEL: @test_sroa_phi_gep_global(
94 ; CHECK-NEXT:  entry:
95 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
96 ; CHECK:       if.then:
97 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr getelementptr inbounds ([[PAIR:%.*]], ptr @g, i32 0, i32 1), align 4
98 ; CHECK-NEXT:    br label [[END]]
99 ; CHECK:       end:
100 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN]], [[IF_THEN]] ]
101 ; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
103 entry:
104   %a = alloca %pair, align 4
105   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
106   store i32 1, ptr %gep_a, align 4
107   br i1 %cond, label %if.then, label %end
109 if.then:
110   br label %end
112 end:
113   %phi = phi ptr [ %a, %entry], [ @g, %if.then ]
114   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
115   %load = load i32, ptr %gep, align 4
116   ret i32 %load
119 define i32 @test_sroa_phi_gep_arg_phi_inspt(i1 %cond) {
120 ; CHECK-LABEL: @test_sroa_phi_gep_arg_phi_inspt(
121 ; CHECK-NEXT:  entry:
122 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
123 ; CHECK:       for:
124 ; CHECK-NEXT:    [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]
125 ; CHECK-NEXT:    [[I]] = add i32 [[PHI_INSPT]], 1
126 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
127 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
128 ; CHECK:       end:
129 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 2, [[FOR]] ]
130 ; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
132 entry:
133   %a = alloca %pair, align 4
134   %b = alloca %pair, align 4
135   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
136   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
137   store i32 1, ptr %gep_a, align 4
138   store i32 2, ptr %gep_b, align 4
139   br i1 %cond, label %for, label %end
141 for:
142   %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ]
143   %i = add i32 %phi_inspt, 1
144   %loop.cond = icmp ult i32 %i, 10
145   br i1 %loop.cond, label %for, label %end
147 end:
148   %phi = phi ptr [ %a, %entry], [ %b, %for ]
149   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
150   %load = load i32, ptr %gep, align 4
151   ret i32 %load
154 define i32 @test_sroa_phi_gep_phi_inspt(i1 %cond) {
155 ; CHECK-LABEL: @test_sroa_phi_gep_phi_inspt(
156 ; CHECK-NEXT:  entry:
157 ; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
158 ; CHECK-NEXT:    [[B:%.*]] = alloca [[PAIR]], align 4
159 ; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1
160 ; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1
161 ; CHECK-NEXT:    store i32 1, ptr [[GEP_A]], align 4
162 ; CHECK-NEXT:    store i32 2, ptr [[GEP_B]], align 4
163 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
164 ; CHECK:       for:
165 ; CHECK-NEXT:    [[PHI_IN:%.*]] = phi ptr [ null, [[ENTRY:%.*]] ], [ [[B]], [[FOR]] ]
166 ; CHECK-NEXT:    [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I:%.*]], [[FOR]] ]
167 ; CHECK-NEXT:    [[I]] = add i32 [[PHI_INSPT]], 1
168 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
169 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
170 ; CHECK:       end:
171 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[PHI_IN]], [[FOR]] ]
172 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 0, i32 1
173 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
174 ; CHECK-NEXT:    ret i32 [[LOAD]]
176 entry:
177   %a = alloca %pair, align 4
178   %b = alloca %pair, align 4
179   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
180   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
181   store i32 1, ptr %gep_a, align 4
182   store i32 2, ptr %gep_b, align 4
183   br i1 %cond, label %for, label %end
185 for:
186   %phi_in = phi ptr [ null, %entry ], [ %b, %for ]
187   %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ]
188   %i = add i32 %phi_inspt, 1
189   %loop.cond = icmp ult i32 %i, 10
190   br i1 %loop.cond, label %for, label %end
192 end:
193   %phi = phi ptr [ %a, %entry], [ %phi_in, %for ]
194   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
195   %load = load i32, ptr %gep, align 4
196   ret i32 %load
199 define i32 @test_sroa_gep_phi_gep(i1 %cond) {
200 ; CHECK-LABEL: @test_sroa_gep_phi_gep(
201 ; CHECK-NEXT:  entry:
202 ; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
203 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
204 ; CHECK:       for:
205 ; CHECK-NEXT:    [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]
206 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ]
207 ; CHECK-NEXT:    [[I]] = add i32 [[PHI_I]], 1
208 ; CHECK-NEXT:    [[GEP_FOR]] = getelementptr inbounds i32, ptr [[PHI]], i32 0
209 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
210 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
211 ; CHECK:       end:
212 ; CHECK-NEXT:    [[PHI_END:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ]
213 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[PHI_END]], align 4
214 ; CHECK-NEXT:    ret i32 [[LOAD]]
216 entry:
217   %a = alloca %pair, align 4
218   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
219   br i1 %cond, label %for, label %end
221 for:
222   %phi_i = phi i32 [ 0, %entry ], [ %i, %for ]
223   %phi = phi ptr [ %gep_a, %entry], [ %gep_for, %for ]
224   %i = add i32 %phi_i, 1
225   %gep_for = getelementptr inbounds i32, ptr %phi, i32 0
226   %loop.cond = icmp ult i32 %i, 10
227   br i1 %loop.cond, label %for, label %end
229 end:
230   %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]
231   %load = load i32, ptr %phi_end, align 4
232   ret i32 %load
235 define i32 @test_sroa_invoke_phi_gep(i1 %cond) personality ptr @__gxx_personality_v0 {
236 ; CHECK-LABEL: @test_sroa_invoke_phi_gep(
237 ; CHECK-NEXT:  entry:
238 ; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
239 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[CALL:%.*]], label [[END:%.*]]
240 ; CHECK:       call:
241 ; CHECK-NEXT:    [[B:%.*]] = invoke ptr @foo()
242 ; CHECK-NEXT:            to label [[END]] unwind label [[INVOKE_CATCH:%.*]]
243 ; CHECK:       end:
244 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[CALL]] ]
245 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 0, i32 1
246 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
247 ; CHECK-NEXT:    ret i32 [[LOAD]]
248 ; CHECK:       invoke_catch:
249 ; CHECK-NEXT:    [[RES:%.*]] = landingpad { ptr, i32 }
250 ; CHECK-NEXT:            catch ptr null
251 ; CHECK-NEXT:    ret i32 0
253 entry:
254   %a = alloca %pair, align 4
255   br i1 %cond, label %call, label %end
257 call:
258   %b = invoke ptr @foo()
259   to label %end unwind label %invoke_catch
261 end:
262   %phi = phi ptr [ %a, %entry], [ %b, %call ]
263   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
264   %load = load i32, ptr %gep, align 4
265   ret i32 %load
267 invoke_catch:
268   %res = landingpad { ptr, i32 }
269   catch ptr null
270   ret i32 0
273 define i32 @test_sroa_phi_gep_nonconst_idx(i1 %cond, i32 %idx) {
274 ; CHECK-LABEL: @test_sroa_phi_gep_nonconst_idx(
275 ; CHECK-NEXT:  entry:
276 ; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
277 ; CHECK-NEXT:    [[B:%.*]] = alloca [[PAIR]], align 4
278 ; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1
279 ; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1
280 ; CHECK-NEXT:    store i32 1, ptr [[GEP_A]], align 4
281 ; CHECK-NEXT:    store i32 2, ptr [[GEP_B]], align 4
282 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
283 ; CHECK:       if.then:
284 ; CHECK-NEXT:    br label [[END]]
285 ; CHECK:       end:
286 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ]
287 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 [[IDX:%.*]], i32 1
288 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
289 ; CHECK-NEXT:    ret i32 [[LOAD]]
291 entry:
292   %a = alloca %pair, align 4
293   %b = alloca %pair, align 4
294   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
295   %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1
296   store i32 1, ptr %gep_a, align 4
297   store i32 2, ptr %gep_b, align 4
298   br i1 %cond, label %if.then, label %end
300 if.then:
301   br label %end
303 end:
304   %phi = phi ptr [ %a, %entry], [ %b, %if.then ]
305   %gep = getelementptr inbounds %pair, ptr %phi, i32 %idx, i32 1
306   %load = load i32, ptr %gep, align 4
307   ret i32 %load
310 define void @test_sroa_gep_phi_select_other_block(i1 %c1, i1 %c2, ptr %ptr) {
311 ; CHECK-LABEL: @test_sroa_gep_phi_select_other_block(
312 ; CHECK-NEXT:  entry:
313 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
314 ; CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
315 ; CHECK:       while.body:
316 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]
317 ; CHECK-NEXT:    [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]]
318 ; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]]
319 ; CHECK:       exit:
320 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1
321 ; CHECK-NEXT:    unreachable
323 entry:
324   %alloca = alloca %pair, align 8
325   br label %while.body
327 while.body:
328   %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ]
329   %select = select i1 %c1, ptr %phi, ptr %ptr
330   br i1 %c2, label %exit, label %while.body
332 exit:
333   %gep = getelementptr inbounds %pair, ptr %phi, i64 1
334   unreachable
337 define void @test_sroa_gep_phi_select_same_block(i1 %c1, i1 %c2, ptr %ptr) {
338 ; CHECK-LABEL: @test_sroa_gep_phi_select_same_block(
339 ; CHECK-NEXT:  entry:
340 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
341 ; CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
342 ; CHECK:       while.body:
343 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]
344 ; CHECK-NEXT:    [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]]
345 ; CHECK-NEXT:    [[PHI_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1
346 ; CHECK-NEXT:    [[PTR_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PTR]], i64 1
347 ; CHECK-NEXT:    [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]]
348 ; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]]
349 ; CHECK:       exit:
350 ; CHECK-NEXT:    ret void
352 entry:
353   %alloca = alloca %pair, align 8
354   br label %while.body
356 while.body:
357   %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ]
358   %select = select i1 %c1, ptr %phi, ptr %ptr
359   %gep = getelementptr inbounds %pair, ptr %select, i64 1
360   br i1 %c2, label %exit, label %while.body
362 exit:
363   ret void
366 define void @test_sroa_gep_phi_select_same_block_nuw(i1 %c1, i1 %c2, ptr %ptr) {
367 ; CHECK-LABEL: @test_sroa_gep_phi_select_same_block_nuw(
368 ; CHECK-NEXT:  entry:
369 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
370 ; CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
371 ; CHECK:       while.body:
372 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]
373 ; CHECK-NEXT:    [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]]
374 ; CHECK-NEXT:    [[PHI_SROA_GEP:%.*]] = getelementptr nuw [[PAIR]], ptr [[PHI]], i64 1
375 ; CHECK-NEXT:    [[PTR_SROA_GEP:%.*]] = getelementptr nuw [[PAIR]], ptr [[PTR]], i64 1
376 ; CHECK-NEXT:    [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]]
377 ; CHECK-NEXT:    br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]]
378 ; CHECK:       exit:
379 ; CHECK-NEXT:    ret void
381 entry:
382   %alloca = alloca %pair, align 8
383   br label %while.body
385 while.body:
386   %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ]
387   %select = select i1 %c1, ptr %phi, ptr %ptr
388   %gep = getelementptr nuw %pair, ptr %select, i64 1
389   br i1 %c2, label %exit, label %while.body
391 exit:
392   ret void
395 define i32 @test_sroa_gep_cast_phi_gep(i1 %cond) {
396 ; CHECK-LABEL: @test_sroa_gep_cast_phi_gep(
397 ; CHECK-NEXT:  entry:
398 ; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
399 ; CHECK-NEXT:    store i32 1065353216, ptr [[A_SROA_0]], align 4
400 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
401 ; CHECK:       for:
402 ; CHECK-NEXT:    [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]
403 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ]
404 ; CHECK-NEXT:    [[I]] = add i32 [[PHI_I]], 1
405 ; CHECK-NEXT:    [[GEP_FOR]] = getelementptr inbounds float, ptr [[PHI]], i32 0
406 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
407 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
408 ; CHECK:       end:
409 ; CHECK-NEXT:    [[PHI_END:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ]
410 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[PHI_END]], align 4
411 ; CHECK-NEXT:    ret i32 [[LOAD]]
413 entry:
414   %a = alloca %pair, align 4
415   %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1
416   store float 1.0, ptr %gep_a, align 4
417   br i1 %cond, label %for, label %end
419 for:
420   %phi_i = phi i32 [ 0, %entry ], [ %i, %for ]
421   %phi = phi ptr [ %gep_a, %entry], [ %gep_for, %for ]
422   %i = add i32 %phi_i, 1
423   %gep_for = getelementptr inbounds float, ptr %phi, i32 0
424   %loop.cond = icmp ult i32 %i, 10
425   br i1 %loop.cond, label %for, label %end
427 end:
428   %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]
429   %load = load i32, ptr %phi_end, align 4
430   ret i32 %load
433 define void @unreachable_term(i1 %c1) {
434 ; CHECK-LABEL: @unreachable_term(
435 ; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
436 ; CHECK-NEXT:    unreachable
437 ; CHECK:       bb1:
438 ; CHECK-NEXT:    br label [[BB1_I:%.*]]
439 ; CHECK:       bb1.i:
440 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[BB1:%.*]] ], [ null, [[BB1_I]] ]
441 ; CHECK-NEXT:    store i32 0, ptr [[PHI]], align 1
442 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[BB1_I]], label [[EXIT:%.*]]
443 ; CHECK:       exit:
444 ; CHECK-NEXT:    br label [[BB2:%.*]]
445 ; CHECK:       bb2:
446 ; CHECK-NEXT:    ret void
448   %a = alloca [3 x i32], align 1
449   unreachable
451 bb1:
452   br label %bb1.i
454 bb1.i:
455   %phi = phi ptr [ %a, %bb1 ], [ null, %bb1.i ]
456   store i32 0, ptr %phi, align 1
457   br i1 %c1, label %bb1.i, label %exit
459 exit:
460   br label %bb2
462 bb2:
463   ret void
466 define void @constant_value_phi(i1 %c1) {
467 ; CHECK-LABEL: @constant_value_phi(
468 ; CHECK-NEXT:  entry:
469 ; CHECK-NEXT:    br label [[LAND_LHS_TRUE_I:%.*]]
470 ; CHECK:       land.lhs.true.i:
471 ; CHECK-NEXT:    br i1 [[C1:%.*]], label [[COND_END_I:%.*]], label [[COND_END_I]]
472 ; CHECK:       cond.end.i:
473 ; CHECK-NEXT:    unreachable
475 entry:
476   %s1 = alloca [3 x i16]
477   %s = alloca [3 x i16]
478   br label %land.lhs.true.i
480 land.lhs.true.i:                                  ; preds = %entry
481   br i1 %c1, label %cond.end.i, label %cond.end.i
483 cond.end.i:                                       ; preds = %land.lhs.true.i, %land.lhs.true.i
484   %.pre-phi1 = phi ptr [ %s1, %land.lhs.true.i ], [ %s1, %land.lhs.true.i ]
485   call void @llvm.memcpy.p0.p0.i64(ptr %.pre-phi1, ptr %s, i64 3, i1 false)
486   %load = load i16, ptr %s
487   unreachable
490 define i32 @test_sroa_phi_gep_multiple_values_from_same_block(i32 %arg) {
491 ; CHECK-LABEL: @test_sroa_phi_gep_multiple_values_from_same_block(
492 ; CHECK-NEXT:  bb.1:
493 ; CHECK-NEXT:    switch i32 [[ARG:%.*]], label [[BB_3:%.*]] [
494 ; CHECK-NEXT:      i32 1, label [[BB_2:%.*]]
495 ; CHECK-NEXT:      i32 2, label [[BB_2]]
496 ; CHECK-NEXT:      i32 3, label [[BB_4:%.*]]
497 ; CHECK-NEXT:      i32 4, label [[BB_4]]
498 ; CHECK-NEXT:    ]
499 ; CHECK:       bb.2:
500 ; CHECK-NEXT:    br label [[BB_4]]
501 ; CHECK:       bb.3:
502 ; CHECK-NEXT:    br label [[BB_4]]
503 ; CHECK:       bb.4:
504 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[BB_3]] ], [ undef, [[BB_2]] ], [ undef, [[BB_1:%.*]] ], [ undef, [[BB_1]] ]
505 ; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
507 bb.1:
508   %a = alloca %pair, align 4
509   %b = alloca %pair, align 4
510   switch i32 %arg, label %bb.3 [
511   i32 1, label %bb.2
512   i32 2, label %bb.2
513   i32 3, label %bb.4
514   i32 4, label %bb.4
515   ]
517 bb.2:                                                ; preds = %bb.1, %bb.1
518   br label %bb.4
520 bb.3:                                                ; preds = %bb.1
521   br label %bb.4
523 bb.4:                                                ; preds = %bb.1, %bb.1, %bb.3, %bb.2
524   %phi = phi ptr [ %a, %bb.3 ], [ %a, %bb.2 ], [ %b, %bb.1 ], [ %b, %bb.1 ]
525   %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1
526   %load = load i32, ptr %gep, align 4
527   ret i32 %load
530 define i64 @test_phi_idx_mem2reg_const(i1 %arg) {
531 ; CHECK-LABEL: @test_phi_idx_mem2reg_const(
532 ; CHECK-NEXT:  bb:
533 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
534 ; CHECK:       bb1:
535 ; CHECK-NEXT:    br label [[END:%.*]]
536 ; CHECK:       bb2:
537 ; CHECK-NEXT:    br label [[END]]
538 ; CHECK:       end:
539 ; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i64 [ 2, [[BB1]] ], [ 3, [[BB2]] ]
540 ; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ 1, [[BB2]] ]
541 ; CHECK-NEXT:    ret i64 [[PHI_SROA_PHI_SROA_SPECULATED]]
544   %alloca = alloca [2 x i64], align 8
545   %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1
546   store i64 2, ptr %alloca
547   store i64 3, ptr %gep1
548   br i1 %arg, label %bb1, label %bb2
550 bb1:
551   br label %end
553 bb2:
554   br label %end
556 end:
557   %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ]
558   %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi
559   %load = load i64, ptr %getelementptr
560   ret i64 %load
563 define i64 @test_phi_idx_mem2reg_not_const(i1 %arg, i64 %idx) {
564 ; CHECK-LABEL: @test_phi_idx_mem2reg_not_const(
565 ; CHECK-NEXT:  bb:
566 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [2 x i64], align 8
567 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1
568 ; CHECK-NEXT:    store i64 2, ptr [[ALLOCA]], align 4
569 ; CHECK-NEXT:    store i64 3, ptr [[GEP1]], align 4
570 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
571 ; CHECK:       bb1:
572 ; CHECK-NEXT:    br label [[END:%.*]]
573 ; CHECK:       bb2:
574 ; CHECK-NEXT:    br label [[END]]
575 ; CHECK:       end:
576 ; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ [[IDX:%.*]], [[BB2]] ]
577 ; CHECK-NEXT:    [[GETELEMENTPTR:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[PHI]]
578 ; CHECK-NEXT:    [[LOAD:%.*]] = load i64, ptr [[GETELEMENTPTR]], align 4
579 ; CHECK-NEXT:    ret i64 [[LOAD]]
582   %alloca = alloca [2 x i64], align 8
583   %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1
584   store i64 2, ptr %alloca
585   store i64 3, ptr %gep1
586   br i1 %arg, label %bb1, label %bb2
588 bb1:
589   br label %end
591 bb2:
592   br label %end
594 end:
595   %phi = phi i64 [ 0, %bb1 ], [ %idx, %bb2 ]
596   %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi
597   %load = load i64, ptr %getelementptr
598   ret i64 %load
601 define i64 @test_phi_mem2reg_pointer_op_is_non_const_gep(i1 %arg, i64 %idx) {
602 ; CHECK-LABEL: @test_phi_mem2reg_pointer_op_is_non_const_gep(
603 ; CHECK-NEXT:  bb:
604 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [2 x i64], align 8
605 ; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1
606 ; CHECK-NEXT:    store i64 2, ptr [[ALLOCA]], align 4
607 ; CHECK-NEXT:    store i64 3, ptr [[GEP1]], align 4
608 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
609 ; CHECK:       bb1:
610 ; CHECK-NEXT:    br label [[END:%.*]]
611 ; CHECK:       bb2:
612 ; CHECK-NEXT:    br label [[END]]
613 ; CHECK:       end:
614 ; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ 1, [[BB2]] ]
615 ; CHECK-NEXT:    [[GETELEMENTPTR:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[IDX:%.*]]
616 ; CHECK-NEXT:    [[GETELEMENTPTR2:%.*]] = getelementptr inbounds i64, ptr [[GETELEMENTPTR]], i64 [[PHI]]
617 ; CHECK-NEXT:    [[LOAD:%.*]] = load i64, ptr [[GETELEMENTPTR]], align 4
618 ; CHECK-NEXT:    ret i64 [[LOAD]]
621   %alloca = alloca [2 x i64], align 8
622   %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1
623   store i64 2, ptr %alloca
624   store i64 3, ptr %gep1
625   br i1 %arg, label %bb1, label %bb2
627 bb1:
628   br label %end
630 bb2:
631   br label %end
633 end:
634   %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ]
635   %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %idx
636   %getelementptr2 = getelementptr inbounds i64, ptr %getelementptr, i64 %phi
637   %load = load i64, ptr %getelementptr
638   ret i64 %load
641 define i1 @test_phi_mem2reg_entry_block_alloca_not_at_beginning(i1 %arg) {
642 ; CHECK-LABEL: @test_phi_mem2reg_entry_block_alloca_not_at_beginning(
643 ; CHECK-NEXT:  bb:
644 ; CHECK-NEXT:    call void @f()
645 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8
646 ; CHECK-NEXT:    [[PHI_SROA_GEP:%.*]] = getelementptr i64, ptr [[ALLOCA]], i64 1
647 ; CHECK-NEXT:    [[PHI_SROA_GEP1:%.*]] = getelementptr i64, ptr [[ALLOCA]], i64 2
648 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB2:%.*]], label [[BB3:%.*]]
649 ; CHECK:       bb2:
650 ; CHECK-NEXT:    br label [[BB3]]
651 ; CHECK:       bb3:
652 ; CHECK-NEXT:    [[PHI_SROA_PHI:%.*]] = phi ptr [ [[PHI_SROA_GEP]], [[BB:%.*]] ], [ [[PHI_SROA_GEP1]], [[BB2]] ]
653 ; CHECK-NEXT:    [[PHI:%.*]] = phi i64 [ 1, [[BB]] ], [ 2, [[BB2]] ]
654 ; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq ptr [[PHI_SROA_PHI]], null
655 ; CHECK-NEXT:    ret i1 [[ICMP]]
658   call void @f()
659   %alloca = alloca i64
660   br i1 %arg, label %bb2, label %bb3
661 bb2:
662   br label %bb3
663 bb3:
664   %phi = phi i64 [ 1, %bb ], [ 2, %bb2 ]
665   %gep = getelementptr i64, ptr %alloca, i64 %phi
666   %icmp = icmp eq ptr %gep, null
667   ret i1 %icmp
670 define i32 @test_phi_mem2reg_alloca_not_in_entry_block(i1 %arg) {
671 ; CHECK-LABEL: @test_phi_mem2reg_alloca_not_in_entry_block(
672 ; CHECK-NEXT:  bb:
673 ; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca i64, align 8
674 ; CHECK-NEXT:    store i64 123, ptr [[ALLOCA]], align 4
675 ; CHECK-NEXT:    br label [[BB2:%.*]]
676 ; CHECK:       bb2:
677 ; CHECK-NEXT:    [[ALLOCA2:%.*]] = alloca i64, align 8
678 ; CHECK-NEXT:    store i64 124, ptr [[ALLOCA]], align 4
679 ; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
680 ; CHECK:       bb3:
681 ; CHECK-NEXT:    br label [[BB4]]
682 ; CHECK:       bb4:
683 ; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[BB2]] ], [ [[ALLOCA2]], [[BB3]] ]
684 ; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1
685 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4
686 ; CHECK-NEXT:    ret i32 [[LOAD]]
689   %alloca = alloca i64
690   store i64 123, ptr %alloca
691   br label %bb2
692 bb2:
693   %alloca2 = alloca i64
694   store i64 124, ptr %alloca
695   br i1 %arg, label %bb3, label %bb4
696 bb3:
697   br label %bb4
698 bb4:
699   %phi = phi ptr [ %alloca, %bb2 ], [ %alloca2, %bb3 ]
700   %gep = getelementptr i32, ptr %phi, i64 1
701   %load = load i32, ptr %gep
702   ret i32 %load
705 define i64 @test_unfold_phi_duplicate_phi_entry(ptr %arg, i8 %arg1, i1 %arg2) {
706 ; CHECK-LABEL: @test_unfold_phi_duplicate_phi_entry(
707 ; CHECK-NEXT:  bb:
708 ; CHECK-NEXT:    [[ALLOCA_SROA_0:%.*]] = alloca i64, align 8
709 ; CHECK-NEXT:    [[PHI_SROA_GEP:%.*]] = getelementptr i64, ptr [[ARG:%.*]], i64 1
710 ; CHECK-NEXT:    br i1 [[ARG2:%.*]], label [[BB5:%.*]], label [[BB3:%.*]]
711 ; CHECK:       bb3:
712 ; CHECK-NEXT:    switch i8 [[ARG1:%.*]], label [[BB4:%.*]] [
713 ; CHECK-NEXT:      i8 0, label [[BB5]]
714 ; CHECK-NEXT:      i8 1, label [[BB5]]
715 ; CHECK-NEXT:    ]
716 ; CHECK:       bb4:
717 ; CHECK-NEXT:    ret i64 0
718 ; CHECK:       bb5:
719 ; CHECK-NEXT:    [[PHI_SROA_PHI:%.*]] = phi ptr [ [[PHI_SROA_GEP]], [[BB3]] ], [ [[PHI_SROA_GEP]], [[BB3]] ], [ [[ALLOCA_SROA_0]], [[BB:%.*]] ]
720 ; CHECK-NEXT:    [[LOAD:%.*]] = load i64, ptr [[PHI_SROA_PHI]], align 4
721 ; CHECK-NEXT:    ret i64 [[LOAD]]
724   %alloca = alloca [2 x i64], align 8
725   br i1 %arg2, label %bb5, label %bb3
727 bb3:                                              ; preds = %bb
728   switch i8 %arg1, label %bb4 [
729   i8 0, label %bb5
730   i8 1, label %bb5
731   ]
733 bb4:                                              ; preds = %bb5, %bb3
734   ret i64 0
736 bb5:                                              ; preds = %bb3, %bb3, %bb
737   %phi = phi ptr [ %arg, %bb3 ], [ %arg, %bb3 ], [ %alloca, %bb ]
738   %getelementptr = getelementptr i64, ptr %phi, i64 1
739   %load = load i64, ptr %getelementptr
740   ret i64 %load
743 declare void @f()
745 declare ptr @foo()
747 declare i32 @__gxx_personality_v0(...)
749 declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
750 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
751 ; CHECK-MODIFY-CFG: {{.*}}
752 ; CHECK-PRESERVE-CFG: {{.*}}