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(
10 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
12 ; CHECK-NEXT: br label [[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]]
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
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
36 define i32 @test_sroa_phi_gep_non_inbound(i1 %cond) {
37 ; CHECK-LABEL: @test_sroa_phi_gep_non_inbound(
39 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
41 ; CHECK-NEXT: br label [[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]]
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
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
65 define i32 @test_sroa_phi_gep_poison(i1 %cond) {
66 ; CHECK-LABEL: @test_sroa_phi_gep_poison(
68 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
70 ; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr poison, align 4
71 ; CHECK-NEXT: br label [[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]]
77 %a = alloca %pair, align 4
78 br i1 %cond, label %if.then, label %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
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(
95 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]
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]]
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]]
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
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
119 define i32 @test_sroa_phi_gep_arg_phi_inspt(i1 %cond) {
120 ; CHECK-LABEL: @test_sroa_phi_gep_arg_phi_inspt(
122 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
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]]
129 ; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 2, [[FOR]] ]
130 ; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
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
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
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
154 define i32 @test_sroa_phi_gep_phi_inspt(i1 %cond) {
155 ; CHECK-LABEL: @test_sroa_phi_gep_phi_inspt(
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:%.*]]
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]]
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]]
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
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
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
199 define i32 @test_sroa_gep_phi_gep(i1 %cond) {
200 ; CHECK-LABEL: @test_sroa_gep_phi_gep(
202 ; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4
203 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]
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]]
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]]
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
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
230 %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]
231 %load = load i32, ptr %phi_end, align 4
235 define i32 @test_sroa_invoke_phi_gep(i1 %cond) personality ptr @__gxx_personality_v0 {
236 ; CHECK-LABEL: @test_sroa_invoke_phi_gep(
238 ; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4
239 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[CALL:%.*]], label [[END:%.*]]
241 ; CHECK-NEXT: [[B:%.*]] = invoke ptr @foo()
242 ; CHECK-NEXT: to label [[END]] unwind label [[INVOKE_CATCH:%.*]]
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
254 %a = alloca %pair, align 4
255 br i1 %cond, label %call, label %end
258 %b = invoke ptr @foo()
259 to label %end unwind label %invoke_catch
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
268 %res = landingpad { ptr, i32 }
273 define i32 @test_sroa_phi_gep_nonconst_idx(i1 %cond, i32 %idx) {
274 ; CHECK-LABEL: @test_sroa_phi_gep_nonconst_idx(
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:%.*]]
284 ; CHECK-NEXT: br label [[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]]
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
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
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(
313 ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
314 ; CHECK-NEXT: br label [[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]]
320 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1
321 ; CHECK-NEXT: unreachable
324 %alloca = alloca %pair, align 8
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
333 %gep = getelementptr inbounds %pair, ptr %phi, i64 1
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(
340 ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
341 ; CHECK-NEXT: br label [[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]]
350 ; CHECK-NEXT: ret void
353 %alloca = alloca %pair, align 8
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
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(
369 ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8
370 ; CHECK-NEXT: br label [[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]]
379 ; CHECK-NEXT: ret void
382 %alloca = alloca %pair, align 8
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
395 define i32 @test_sroa_gep_cast_phi_gep(i1 %cond) {
396 ; CHECK-LABEL: @test_sroa_gep_cast_phi_gep(
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:%.*]]
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]]
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]]
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
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
428 %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]
429 %load = load i32, ptr %phi_end, align 4
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
438 ; CHECK-NEXT: br label [[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:%.*]]
444 ; CHECK-NEXT: br label [[BB2:%.*]]
446 ; CHECK-NEXT: ret void
448 %a = alloca [3 x i32], align 1
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
466 define void @constant_value_phi(i1 %c1) {
467 ; CHECK-LABEL: @constant_value_phi(
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]]
473 ; CHECK-NEXT: unreachable
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
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(
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]]
500 ; CHECK-NEXT: br label [[BB_4]]
502 ; CHECK-NEXT: br label [[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]]
508 %a = alloca %pair, align 4
509 %b = alloca %pair, align 4
510 switch i32 %arg, label %bb.3 [
517 bb.2: ; preds = %bb.1, %bb.1
520 bb.3: ; preds = %bb.1
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
530 define i64 @test_phi_idx_mem2reg_const(i1 %arg) {
531 ; CHECK-LABEL: @test_phi_idx_mem2reg_const(
533 ; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
535 ; CHECK-NEXT: br label [[END:%.*]]
537 ; CHECK-NEXT: br label [[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
557 %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ]
558 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi
559 %load = load i64, ptr %getelementptr
563 define i64 @test_phi_idx_mem2reg_not_const(i1 %arg, i64 %idx) {
564 ; CHECK-LABEL: @test_phi_idx_mem2reg_not_const(
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:%.*]]
572 ; CHECK-NEXT: br label [[END:%.*]]
574 ; CHECK-NEXT: br label [[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
595 %phi = phi i64 [ 0, %bb1 ], [ %idx, %bb2 ]
596 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi
597 %load = load i64, ptr %getelementptr
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(
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:%.*]]
610 ; CHECK-NEXT: br label [[END:%.*]]
612 ; CHECK-NEXT: br label [[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
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
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(
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:%.*]]
650 ; CHECK-NEXT: br label [[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]]
660 br i1 %arg, label %bb2, label %bb3
664 %phi = phi i64 [ 1, %bb ], [ 2, %bb2 ]
665 %gep = getelementptr i64, ptr %alloca, i64 %phi
666 %icmp = icmp eq ptr %gep, null
670 define i32 @test_phi_mem2reg_alloca_not_in_entry_block(i1 %arg) {
671 ; CHECK-LABEL: @test_phi_mem2reg_alloca_not_in_entry_block(
673 ; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8
674 ; CHECK-NEXT: store i64 123, ptr [[ALLOCA]], align 4
675 ; CHECK-NEXT: br label [[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:%.*]]
681 ; CHECK-NEXT: br label [[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]]
690 store i64 123, ptr %alloca
693 %alloca2 = alloca i64
694 store i64 124, ptr %alloca
695 br i1 %arg, label %bb3, label %bb4
699 %phi = phi ptr [ %alloca, %bb2 ], [ %alloca2, %bb3 ]
700 %gep = getelementptr i32, ptr %phi, i64 1
701 %load = load i32, ptr %gep
705 define i64 @test_unfold_phi_duplicate_phi_entry(ptr %arg, i8 %arg1, i1 %arg2) {
706 ; CHECK-LABEL: @test_unfold_phi_duplicate_phi_entry(
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:%.*]]
712 ; CHECK-NEXT: switch i8 [[ARG1:%.*]], label [[BB4:%.*]] [
713 ; CHECK-NEXT: i8 0, label [[BB5]]
714 ; CHECK-NEXT: i8 1, label [[BB5]]
717 ; CHECK-NEXT: ret i64 0
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
728 switch i8 %arg1, label %bb4 [
733 bb4: ; preds = %bb5, %bb3
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
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: {{.*}}