1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -sroa < %s | FileCheck %s
3
4%pair = type { i32, i32 }
5
6define i32 @test_sroa_phi_gep(i1 %cond) {
7; CHECK-LABEL: @test_sroa_phi_gep(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
10; CHECK:       if.then:
11; CHECK-NEXT:    br label [[END]]
12; CHECK:       end:
13; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ]
14; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
15;
16entry:
17  %a = alloca %pair, align 4
18  %b = alloca %pair, align 4
19  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
20  %gep_b = getelementptr inbounds %pair, %pair* %b, i32 0, i32 1
21  store i32 1, i32* %gep_a, align 4
22  store i32 2, i32* %gep_b, align 4
23  br i1 %cond, label %if.then, label %end
24
25if.then:
26  br label %end
27
28end:
29  %phi = phi %pair* [ %a, %entry], [ %b, %if.then ]
30  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
31  %load = load i32, i32* %gep, align 4
32  ret i32 %load
33}
34
35define i32 @test_sroa_phi_gep_non_inbound(i1 %cond) {
36; CHECK-LABEL: @test_sroa_phi_gep_non_inbound(
37; CHECK-NEXT:  entry:
38; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
39; CHECK:       if.then:
40; CHECK-NEXT:    br label [[END]]
41; CHECK:       end:
42; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ]
43; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
44;
45entry:
46  %a = alloca %pair, align 4
47  %b = alloca %pair, align 4
48  %gep_a = getelementptr %pair, %pair* %a, i32 0, i32 1
49  %gep_b = getelementptr %pair, %pair* %b, i32 0, i32 1
50  store i32 1, i32* %gep_a, align 4
51  store i32 2, i32* %gep_b, align 4
52  br i1 %cond, label %if.then, label %end
53
54if.then:
55  br label %end
56
57end:
58  %phi = phi %pair* [ %a, %entry], [ %b, %if.then ]
59  %gep = getelementptr %pair, %pair* %phi, i32 0, i32 1
60  %load = load i32, i32* %gep, align 4
61  ret i32 %load
62}
63
64define i32 @test_sroa_phi_gep_undef(i1 %cond) {
65; CHECK-LABEL: @test_sroa_phi_gep_undef(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
68; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
69; CHECK:       if.then:
70; CHECK-NEXT:    br label [[END]]
71; CHECK:       end:
72; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[A]], [[ENTRY:%.*]] ], [ undef, [[IF_THEN]] ]
73; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i32 0, i32 1
74; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[GEP]], align 4
75; CHECK-NEXT:    ret i32 [[LOAD]]
76;
77entry:
78  %a = alloca %pair, align 4
79  br i1 %cond, label %if.then, label %end
80
81if.then:
82  br label %end
83
84end:
85  %phi = phi %pair* [ %a, %entry], [ undef, %if.then ]
86  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
87  %load = load i32, i32* %gep, align 4
88  ret i32 %load
89}
90
91@g = global %pair zeroinitializer, align 4
92
93define i32 @test_sroa_phi_gep_global(i1 %cond) {
94; CHECK-LABEL: @test_sroa_phi_gep_global(
95; CHECK-NEXT:  entry:
96; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
97; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[A]], i32 0, i32 1
98; CHECK-NEXT:    store i32 1, i32* [[GEP_A]], align 4
99; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
100; CHECK:       if.then:
101; CHECK-NEXT:    br label [[END]]
102; CHECK:       end:
103; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[A]], [[ENTRY:%.*]] ], [ @g, [[IF_THEN]] ]
104; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i32 0, i32 1
105; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[GEP]], align 4
106; CHECK-NEXT:    ret i32 [[LOAD]]
107;
108entry:
109  %a = alloca %pair, align 4
110  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
111  store i32 1, i32* %gep_a, align 4
112  br i1 %cond, label %if.then, label %end
113
114if.then:
115  br label %end
116
117end:
118  %phi = phi %pair* [ %a, %entry], [ @g, %if.then ]
119  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
120  %load = load i32, i32* %gep, align 4
121  ret i32 %load
122}
123
124define i32 @test_sroa_phi_gep_arg_phi_inspt(i1 %cond) {
125; CHECK-LABEL: @test_sroa_phi_gep_arg_phi_inspt(
126; CHECK-NEXT:  entry:
127; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
128; CHECK:       for:
129; CHECK-NEXT:    [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]
130; CHECK-NEXT:    [[I]] = add i32 [[PHI_INSPT]], 1
131; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
132; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
133; CHECK:       end:
134; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 2, [[FOR]] ]
135; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
136;
137entry:
138  %a = alloca %pair, align 4
139  %b = alloca %pair, align 4
140  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
141  %gep_b = getelementptr inbounds %pair, %pair* %b, i32 0, i32 1
142  store i32 1, i32* %gep_a, align 4
143  store i32 2, i32* %gep_b, align 4
144  br i1 %cond, label %for, label %end
145
146for:
147  %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ]
148  %i = add i32 %phi_inspt, 1
149  %loop.cond = icmp ult i32 %i, 10
150  br i1 %loop.cond, label %for, label %end
151
152end:
153  %phi = phi %pair* [ %a, %entry], [ %b, %for ]
154  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
155  %load = load i32, i32* %gep, align 4
156  ret i32 %load
157}
158
159define i32 @test_sroa_phi_gep_phi_inspt(i1 %cond) {
160; CHECK-LABEL: @test_sroa_phi_gep_phi_inspt(
161; CHECK-NEXT:  entry:
162; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
163; CHECK-NEXT:    [[B:%.*]] = alloca [[PAIR]], align 4
164; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[A]], i32 0, i32 1
165; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[B]], i32 0, i32 1
166; CHECK-NEXT:    store i32 1, i32* [[GEP_A]], align 4
167; CHECK-NEXT:    store i32 2, i32* [[GEP_B]], align 4
168; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
169; CHECK:       for:
170; CHECK-NEXT:    [[PHI_IN:%.*]] = phi %pair* [ null, [[ENTRY:%.*]] ], [ [[B]], [[FOR]] ]
171; CHECK-NEXT:    [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I:%.*]], [[FOR]] ]
172; CHECK-NEXT:    [[I]] = add i32 [[PHI_INSPT]], 1
173; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
174; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
175; CHECK:       end:
176; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[A]], [[ENTRY]] ], [ [[PHI_IN]], [[FOR]] ]
177; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i32 0, i32 1
178; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[GEP]], align 4
179; CHECK-NEXT:    ret i32 [[LOAD]]
180;
181entry:
182  %a = alloca %pair, align 4
183  %b = alloca %pair, align 4
184  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
185  %gep_b = getelementptr inbounds %pair, %pair* %b, i32 0, i32 1
186  store i32 1, i32* %gep_a, align 4
187  store i32 2, i32* %gep_b, align 4
188  br i1 %cond, label %for, label %end
189
190for:
191  %phi_in = phi %pair * [ null, %entry ], [ %b, %for ]
192  %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ]
193  %i = add i32 %phi_inspt, 1
194  %loop.cond = icmp ult i32 %i, 10
195  br i1 %loop.cond, label %for, label %end
196
197end:
198  %phi = phi %pair* [ %a, %entry], [ %phi_in, %for ]
199  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
200  %load = load i32, i32* %gep, align 4
201  ret i32 %load
202}
203
204define i32 @test_sroa_gep_phi_gep(i1 %cond) {
205; CHECK-LABEL: @test_sroa_gep_phi_gep(
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
208; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
209; CHECK:       for:
210; CHECK-NEXT:    [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]
211; CHECK-NEXT:    [[PHI:%.*]] = phi i32* [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ]
212; CHECK-NEXT:    [[I]] = add i32 [[PHI_I]], 1
213; CHECK-NEXT:    [[GEP_FOR]] = getelementptr inbounds i32, i32* [[PHI]], i32 0
214; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
215; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
216; CHECK:       end:
217; CHECK-NEXT:    [[PHI_END:%.*]] = phi i32* [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ]
218; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[PHI_END]], align 4
219; CHECK-NEXT:    ret i32 [[LOAD]]
220;
221entry:
222  %a = alloca %pair, align 4
223  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
224  br i1 %cond, label %for, label %end
225
226for:
227  %phi_i = phi i32 [ 0, %entry ], [ %i, %for ]
228  %phi = phi i32* [ %gep_a, %entry], [ %gep_for, %for ]
229  %i = add i32 %phi_i, 1
230  %gep_for = getelementptr inbounds i32, i32* %phi, i32 0
231  %loop.cond = icmp ult i32 %i, 10
232  br i1 %loop.cond, label %for, label %end
233
234end:
235  %phi_end = phi i32* [ %gep_a, %entry], [ %phi, %for ]
236  %load = load i32, i32* %phi_end, align 4
237  ret i32 %load
238}
239
240define i32 @test_sroa_invoke_phi_gep(i1 %cond) personality i32 (...)* @__gxx_personality_v0 {
241; CHECK-LABEL: @test_sroa_invoke_phi_gep(
242; CHECK-NEXT:  entry:
243; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
244; CHECK-NEXT:    br i1 [[COND:%.*]], label [[CALL:%.*]], label [[END:%.*]]
245; CHECK:       call:
246; CHECK-NEXT:    [[B:%.*]] = invoke %pair* @foo()
247; CHECK-NEXT:    to label [[END]] unwind label [[INVOKE_CATCH:%.*]]
248; CHECK:       end:
249; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[CALL]] ]
250; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i32 0, i32 1
251; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[GEP]], align 4
252; CHECK-NEXT:    ret i32 [[LOAD]]
253; CHECK:       invoke_catch:
254; CHECK-NEXT:    [[RES:%.*]] = landingpad { i8*, i32 }
255; CHECK-NEXT:    catch i8* null
256; CHECK-NEXT:    ret i32 0
257;
258entry:
259  %a = alloca %pair, align 4
260  br i1 %cond, label %call, label %end
261
262call:
263  %b = invoke %pair* @foo()
264  to label %end unwind label %invoke_catch
265
266end:
267  %phi = phi %pair* [ %a, %entry], [ %b, %call ]
268  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
269  %load = load i32, i32* %gep, align 4
270  ret i32 %load
271
272invoke_catch:
273  %res = landingpad { i8*, i32 }
274  catch i8* null
275  ret i32 0
276}
277
278define i32 @test_sroa_phi_gep_nonconst_idx(i1 %cond, i32 %idx) {
279; CHECK-LABEL: @test_sroa_phi_gep_nonconst_idx(
280; CHECK-NEXT:  entry:
281; CHECK-NEXT:    [[A:%.*]] = alloca [[PAIR:%.*]], align 4
282; CHECK-NEXT:    [[B:%.*]] = alloca [[PAIR]], align 4
283; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[A]], i32 0, i32 1
284; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[B]], i32 0, i32 1
285; CHECK-NEXT:    store i32 1, i32* [[GEP_A]], align 4
286; CHECK-NEXT:    store i32 2, i32* [[GEP_B]], align 4
287; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
288; CHECK:       if.then:
289; CHECK-NEXT:    br label [[END]]
290; CHECK:       end:
291; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ]
292; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i32 [[IDX:%.*]], i32 1
293; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[GEP]], align 4
294; CHECK-NEXT:    ret i32 [[LOAD]]
295;
296entry:
297  %a = alloca %pair, align 4
298  %b = alloca %pair, align 4
299  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
300  %gep_b = getelementptr inbounds %pair, %pair* %b, i32 0, i32 1
301  store i32 1, i32* %gep_a, align 4
302  store i32 2, i32* %gep_b, align 4
303  br i1 %cond, label %if.then, label %end
304
305if.then:
306  br label %end
307
308end:
309  %phi = phi %pair* [ %a, %entry], [ %b, %if.then ]
310  %gep = getelementptr inbounds %pair, %pair* %phi, i32 %idx, i32 1
311  %load = load i32, i32* %gep, align 4
312  ret i32 %load
313}
314
315define void @test_sroa_gep_phi_select_other_block() {
316; CHECK-LABEL: @test_sroa_gep_phi_select_other_block(
317; CHECK-NEXT:  entry:
318; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
319; CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
320; CHECK:       while.body:
321; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]
322; CHECK-NEXT:    [[SELECT]] = select i1 undef, %pair* [[PHI]], %pair* undef
323; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[WHILE_BODY]]
324; CHECK:       exit:
325; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i64 1
326; CHECK-NEXT:    unreachable
327;
328entry:
329  %alloca = alloca %pair, align 8
330  br label %while.body
331
332while.body:
333  %phi = phi %pair* [ %alloca, %entry ], [ %select, %while.body ]
334  %select = select i1 undef, %pair* %phi, %pair* undef
335  br i1 undef, label %exit, label %while.body
336
337exit:
338  %gep = getelementptr inbounds %pair, %pair* %phi, i64 1
339  unreachable
340}
341
342define void @test_sroa_gep_phi_select_same_block() {
343; CHECK-LABEL: @test_sroa_gep_phi_select_same_block(
344; CHECK-NEXT:  entry:
345; CHECK-NEXT:    [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
346; CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
347; CHECK:       while.body:
348; CHECK-NEXT:    [[PHI:%.*]] = phi %pair* [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]
349; CHECK-NEXT:    [[SELECT]] = select i1 undef, %pair* [[PHI]], %pair* undef
350; CHECK-NEXT:    [[PHI_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], %pair* [[PHI]], i64 1
351; CHECK-NEXT:    [[SELECT_SROA_SEL:%.*]] = select i1 undef, %pair* [[PHI_SROA_GEP]], %pair* poison
352; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[WHILE_BODY]]
353; CHECK:       exit:
354; CHECK-NEXT:    unreachable
355;
356entry:
357  %alloca = alloca %pair, align 8
358  br label %while.body
359
360while.body:
361  %phi = phi %pair* [ %alloca, %entry ], [ %select, %while.body ]
362  %select = select i1 undef, %pair* %phi, %pair* undef
363  %gep = getelementptr inbounds %pair, %pair* %select, i64 1
364  br i1 undef, label %exit, label %while.body
365
366exit:
367  unreachable
368}
369
370define i32 @test_sroa_gep_cast_phi_gep(i1 %cond) {
371; CHECK-LABEL: @test_sroa_gep_cast_phi_gep(
372; CHECK-NEXT:  entry:
373; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
374; CHECK-NEXT:    [[A_SROA_0_0_GEP_A_CAST_TO_FLOAT_SROA_CAST:%.*]] = bitcast i32* [[A_SROA_0]] to float*
375; CHECK-NEXT:    [[A_SROA_0_0_GEP_A_CAST_TO_FLOAT_SROA_CAST2:%.*]] = bitcast i32* [[A_SROA_0]] to float*
376; CHECK-NEXT:    [[A_SROA_0_0_GEP_SROA_CAST:%.*]] = bitcast i32* [[A_SROA_0]] to float*
377; CHECK-NEXT:    store i32 1065353216, i32* [[A_SROA_0]], align 4
378; CHECK-NEXT:    br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
379; CHECK:       for:
380; CHECK-NEXT:    [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]
381; CHECK-NEXT:    [[PHI:%.*]] = phi float* [ [[A_SROA_0_0_GEP_A_CAST_TO_FLOAT_SROA_CAST]], [[ENTRY]] ], [ [[GEP_FOR_CAST_TO_FLOAT:%.*]], [[FOR]] ]
382; CHECK-NEXT:    [[PHI_SROA_PHI:%.*]] = phi float* [ [[A_SROA_0_0_GEP_SROA_CAST]], [[ENTRY]] ], [ [[GEP_FOR_CAST_TO_FLOAT_SROA_GEP:%.*]], [[FOR]] ]
383; CHECK-NEXT:    [[I]] = add i32 [[PHI_I]], 1
384; CHECK-NEXT:    [[GEP_FOR_CAST:%.*]] = bitcast float* [[PHI_SROA_PHI]] to i32*
385; CHECK-NEXT:    [[GEP_FOR_CAST_TO_FLOAT]] = bitcast i32* [[GEP_FOR_CAST]] to float*
386; CHECK-NEXT:    [[GEP_FOR_CAST_TO_FLOAT_SROA_GEP]] = getelementptr inbounds float, float* [[GEP_FOR_CAST_TO_FLOAT]], i32 0
387; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10
388; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[FOR]], label [[END]]
389; CHECK:       end:
390; CHECK-NEXT:    [[PHI_END:%.*]] = phi float* [ [[A_SROA_0_0_GEP_A_CAST_TO_FLOAT_SROA_CAST2]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ]
391; CHECK-NEXT:    [[PHI_END_1:%.*]] = bitcast float* [[PHI_END]] to i32*
392; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[PHI_END_1]], align 4
393; CHECK-NEXT:    ret i32 [[LOAD]]
394;
395entry:
396  %a = alloca %pair, align 4
397  %gep_a = getelementptr inbounds %pair, %pair* %a, i32 0, i32 1
398  %gep_a_cast_to_float = bitcast i32* %gep_a to float*
399  store float 1.0, float* %gep_a_cast_to_float, align 4
400  br i1 %cond, label %for, label %end
401
402for:
403  %phi_i = phi i32 [ 0, %entry ], [ %i, %for ]
404  %phi = phi float* [ %gep_a_cast_to_float, %entry], [ %gep_for_cast_to_float, %for ]
405  %i = add i32 %phi_i, 1
406  %gep_for = getelementptr inbounds float, float* %phi, i32 0
407  %gep_for_cast = bitcast float* %gep_for to i32*
408  %gep_for_cast_to_float = bitcast i32* %gep_for_cast to float*
409  %loop.cond = icmp ult i32 %i, 10
410  br i1 %loop.cond, label %for, label %end
411
412end:
413  %phi_end = phi float* [ %gep_a_cast_to_float, %entry], [ %phi, %for ]
414  %phi_end.1 = bitcast float* %phi_end to i32*
415  %load = load i32, i32* %phi_end.1, align 4
416  ret i32 %load
417}
418
419define void @unreachable_term() {
420; CHECK-LABEL: @unreachable_term(
421; CHECK-NEXT:    [[A_SROA_0:%.*]] = alloca i32, align 4
422; CHECK-NEXT:    [[A_SROA_0_0_A_SROA_CAST1:%.*]] = bitcast i32* [[A_SROA_0]] to [3 x i32]*
423; CHECK-NEXT:    unreachable
424; CHECK:       bb1:
425; CHECK-NEXT:    br label [[BB1_I:%.*]]
426; CHECK:       bb1.i:
427; CHECK-NEXT:    [[PHI:%.*]] = phi [3 x i32]* [ [[A_SROA_0_0_A_SROA_CAST1]], [[BB1:%.*]] ], [ null, [[BB1_I]] ]
428; CHECK-NEXT:    [[GEP:%.*]] = getelementptr [3 x i32], [3 x i32]* [[PHI]], i64 0, i64 0
429; CHECK-NEXT:    store i32 0, i32* [[GEP]], align 1
430; CHECK-NEXT:    br i1 undef, label [[BB1_I]], label [[EXIT:%.*]]
431; CHECK:       exit:
432; CHECK-NEXT:    br label [[BB2:%.*]]
433; CHECK:       bb2:
434; CHECK-NEXT:    ret void
435;
436  %a = alloca [3 x i32], align 1
437  unreachable
438
439bb1:
440  br label %bb1.i
441
442bb1.i:
443  %phi = phi [3 x i32]* [ %a, %bb1 ], [ null, %bb1.i ]
444  %gep = getelementptr [3 x i32], [3 x i32]* %phi, i64 0, i64 0
445  store i32 0, i32* %gep, align 1
446  br i1 undef, label %bb1.i, label %exit
447
448exit:
449  br label %bb2
450
451bb2:
452  ret void
453}
454
455define void @constant_value_phi() {
456; CHECK-LABEL: @constant_value_phi(
457; CHECK-NEXT:  entry:
458; CHECK-NEXT:    br label [[LAND_LHS_TRUE_I:%.*]]
459; CHECK:       land.lhs.true.i:
460; CHECK-NEXT:    br i1 undef, label [[COND_END_I:%.*]], label [[COND_END_I]]
461; CHECK:       cond.end.i:
462; CHECK-NEXT:    unreachable
463;
464entry:
465  %s1 = alloca [3 x i16]
466  %s = alloca [3 x i16]
467  %cast = bitcast [3 x i16]* %s1 to i16*
468  br label %land.lhs.true.i
469
470land.lhs.true.i:                                  ; preds = %entry
471  br i1 undef, label %cond.end.i, label %cond.end.i
472
473cond.end.i:                                       ; preds = %land.lhs.true.i, %land.lhs.true.i
474  %.pre-phi1 = phi i16* [ %cast, %land.lhs.true.i ], [ %cast, %land.lhs.true.i ]
475  %cast2 = bitcast [3 x i16]* %s to i16*
476  call void @llvm.memcpy.p0i16.p0i16.i64(i16* %.pre-phi1, i16* %cast2, i64 3, i1 false)
477  %gep = getelementptr inbounds [3 x i16], [3 x i16]* %s, i32 0, i32 0
478  %load = load i16, i16* %gep
479  unreachable
480}
481
482define i32 @test_sroa_phi_gep_multiple_values_from_same_block(i32 %arg) {
483; CHECK-LABEL: @test_sroa_phi_gep_multiple_values_from_same_block(
484; CHECK-NEXT:  bb.1:
485; CHECK-NEXT:    switch i32 [[ARG:%.*]], label [[BB_3:%.*]] [
486; CHECK-NEXT:    i32 1, label [[BB_2:%.*]]
487; CHECK-NEXT:    i32 2, label [[BB_2]]
488; CHECK-NEXT:    i32 3, label [[BB_4:%.*]]
489; CHECK-NEXT:    i32 4, label [[BB_4]]
490; CHECK-NEXT:    ]
491; CHECK:       bb.2:
492; CHECK-NEXT:    br label [[BB_4]]
493; CHECK:       bb.3:
494; CHECK-NEXT:    br label [[BB_4]]
495; CHECK:       bb.4:
496; CHECK-NEXT:    [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[BB_3]] ], [ undef, [[BB_2]] ], [ undef, [[BB_1:%.*]] ], [ undef, [[BB_1]] ]
497; CHECK-NEXT:    ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
498;
499bb.1:
500  %a = alloca %pair, align 4
501  %b = alloca %pair, align 4
502  switch i32 %arg, label %bb.3 [
503  i32 1, label %bb.2
504  i32 2, label %bb.2
505  i32 3, label %bb.4
506  i32 4, label %bb.4
507  ]
508
509bb.2:                                                ; preds = %bb.1, %bb.1
510  br label %bb.4
511
512bb.3:                                                ; preds = %bb.1
513  br label %bb.4
514
515bb.4:                                                ; preds = %bb.1, %bb.1, %bb.3, %bb.2
516  %phi = phi %pair* [ %a, %bb.3 ], [ %a, %bb.2 ], [ %b, %bb.1 ], [ %b, %bb.1 ]
517  %gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
518  %load = load i32, i32* %gep, align 4
519  ret i32 %load
520}
521
522declare %pair* @foo()
523
524declare i32 @__gxx_personality_v0(...)
525
526declare void @llvm.memcpy.p0i16.p0i16.i64(i16* noalias nocapture writeonly, i16* noalias nocapture readonly, i64, i1 immarg)
527