xref: /llvm-project/llvm/test/Transforms/SROA/phi-gep.ll (revision 738fcbee687a50bfa83ba30daf65bab41307211a)
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
4
5%pair = type { i32, i32 }
6
7define 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]]
16;
17entry:
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
25
26if.then:
27  br label %end
28
29end:
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
34}
35
36define 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]]
45;
46entry:
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
54
55if.then:
56  br label %end
57
58end:
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
63}
64
65define 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]]
75;
76entry:
77  %a = alloca %pair, align 4
78  br i1 %cond, label %if.then, label %end
79
80if.then:
81  br label %end
82
83end:
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
88}
89
90@g = global %pair zeroinitializer, align 4
91
92define 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]]
102;
103entry:
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
108
109if.then:
110  br label %end
111
112end:
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
117}
118
119define 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]]
131;
132entry:
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
140
141for:
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
146
147end:
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
152}
153
154define 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]]
175;
176entry:
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
184
185for:
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
191
192end:
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
197}
198
199define 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]]
215;
216entry:
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
220
221for:
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
228
229end:
230  %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]
231  %load = load i32, ptr %phi_end, align 4
232  ret i32 %load
233}
234
235define 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
252;
253entry:
254  %a = alloca %pair, align 4
255  br i1 %cond, label %call, label %end
256
257call:
258  %b = invoke ptr @foo()
259  to label %end unwind label %invoke_catch
260
261end:
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
266
267invoke_catch:
268  %res = landingpad { ptr, i32 }
269  catch ptr null
270  ret i32 0
271}
272
273define 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]]
290;
291entry:
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
299
300if.then:
301  br label %end
302
303end:
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
308}
309
310define 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
322;
323entry:
324  %alloca = alloca %pair, align 8
325  br label %while.body
326
327while.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
331
332exit:
333  %gep = getelementptr inbounds %pair, ptr %phi, i64 1
334  unreachable
335}
336
337define 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
351;
352entry:
353  %alloca = alloca %pair, align 8
354  br label %while.body
355
356while.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
361
362exit:
363  ret void
364}
365
366define 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
380;
381entry:
382  %alloca = alloca %pair, align 8
383  br label %while.body
384
385while.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
390
391exit:
392  ret void
393}
394
395define 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]]
412;
413entry:
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
418
419for:
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
426
427end:
428  %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]
429  %load = load i32, ptr %phi_end, align 4
430  ret i32 %load
431}
432
433define 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
447;
448  %a = alloca [3 x i32], align 1
449  unreachable
450
451bb1:
452  br label %bb1.i
453
454bb1.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
458
459exit:
460  br label %bb2
461
462bb2:
463  ret void
464}
465
466define 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
474;
475entry:
476  %s1 = alloca [3 x i16]
477  %s = alloca [3 x i16]
478  br label %land.lhs.true.i
479
480land.lhs.true.i:                                  ; preds = %entry
481  br i1 %c1, label %cond.end.i, label %cond.end.i
482
483cond.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
488}
489
490define 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]]
506;
507bb.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  ]
516
517bb.2:                                                ; preds = %bb.1, %bb.1
518  br label %bb.4
519
520bb.3:                                                ; preds = %bb.1
521  br label %bb.4
522
523bb.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
528}
529
530define 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]]
542;
543bb:
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
549
550bb1:
551  br label %end
552
553bb2:
554  br label %end
555
556end:
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
561}
562
563define 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]]
580;
581bb:
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
587
588bb1:
589  br label %end
590
591bb2:
592  br label %end
593
594end:
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
599}
600
601define 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]]
619;
620bb:
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
626
627bb1:
628  br label %end
629
630bb2:
631  br label %end
632
633end:
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
639}
640
641define 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]]
656;
657bb:
658  call void @f()
659  %alloca = alloca i64
660  br i1 %arg, label %bb2, label %bb3
661bb2:
662  br label %bb3
663bb3:
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
668}
669
670define 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]]
687;
688bb:
689  %alloca = alloca i64
690  store i64 123, ptr %alloca
691  br label %bb2
692bb2:
693  %alloca2 = alloca i64
694  store i64 124, ptr %alloca
695  br i1 %arg, label %bb3, label %bb4
696bb3:
697  br label %bb4
698bb4:
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
703}
704
705define 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]]
722;
723bb:
724  %alloca = alloca [2 x i64], align 8
725  br i1 %arg2, label %bb5, label %bb3
726
727bb3:                                              ; preds = %bb
728  switch i8 %arg1, label %bb4 [
729  i8 0, label %bb5
730  i8 1, label %bb5
731  ]
732
733bb4:                                              ; preds = %bb5, %bb3
734  ret i64 0
735
736bb5:                                              ; 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
741}
742
743declare void @f()
744
745declare ptr @foo()
746
747declare i32 @__gxx_personality_v0(...)
748
749declare 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: {{.*}}
753