[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / SimplifyCFG / hoist-common-code.ll
blob8ce94d1cf5b4e7093e14b69230429e1227142526
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S -hoist-common-insts=true | FileCheck %s
4 declare void @bar(i32)
6 define void @test(i1 %P, ptr %Q) {
7 ; CHECK-LABEL: @test(
8 ; CHECK-NEXT:  common.ret:
9 ; CHECK-NEXT:    store i32 1, ptr [[Q:%.*]], align 4
10 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[Q]], align 4
11 ; CHECK-NEXT:    call void @bar(i32 [[A]])
12 ; CHECK-NEXT:    ret void
14   br i1 %P, label %T, label %F
15 T:              ; preds = %0
16   store i32 1, ptr %Q
17   %A = load i32, ptr %Q               ; <i32> [#uses=1]
18   call void @bar( i32 %A )
19   ret void
20 F:              ; preds = %0
21   store i32 1, ptr %Q
22   %B = load i32, ptr %Q               ; <i32> [#uses=1]
23   call void @bar( i32 %B )
24   ret void
27 define void @test_switch(i64 %i, ptr %Q) {
28 ; CHECK-LABEL: @test_switch(
29 ; CHECK-NEXT:  common.ret:
30 ; CHECK-NEXT:    store i32 1, ptr [[Q:%.*]], align 4
31 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[Q]], align 4
32 ; CHECK-NEXT:    call void @bar(i32 [[A]])
33 ; CHECK-NEXT:    ret void
35   switch i64 %i, label %bb0 [
36   i64 1, label %bb1
37   i64 2, label %bb2
38   ]
39 bb0:              ; preds = %0
40   store i32 1, ptr %Q
41   %A = load i32, ptr %Q               ; <i32> [#uses=1]
42   call void @bar( i32 %A )
43   ret void
44 bb1:              ; preds = %0
45   store i32 1, ptr %Q
46   %B = load i32, ptr %Q               ; <i32> [#uses=1]
47   call void @bar( i32 %B )
48   ret void
49 bb2:              ; preds = %0
50   store i32 1, ptr %Q
51   %C = load i32, ptr %Q               ; <i32> [#uses=1]
52   call void @bar( i32 %C )
53   ret void
56 ; We ensure that we examine all instructions during each iteration to confirm the presence of a terminating one.
57 define void @test_switch_reach_terminator(i64 %i, ptr %p) {
58 ; CHECK-LABEL: @test_switch_reach_terminator(
59 ; CHECK-NEXT:    switch i64 [[I:%.*]], label [[BB0:%.*]] [
60 ; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
61 ; CHECK-NEXT:      i64 2, label [[COMMON_RET:%.*]]
62 ; CHECK-NEXT:    ]
63 ; CHECK:       common.ret:
64 ; CHECK-NEXT:    ret void
65 ; CHECK:       bb0:
66 ; CHECK-NEXT:    store i32 1, ptr [[P:%.*]], align 4
67 ; CHECK-NEXT:    br label [[COMMON_RET]]
68 ; CHECK:       bb1:
69 ; CHECK-NEXT:    store i32 2, ptr [[P]], align 4
70 ; CHECK-NEXT:    br label [[COMMON_RET]]
72   switch i64 %i, label %bb0 [
73   i64 1, label %bb1
74   i64 2, label %bb2
75   ]
76 bb0:              ; preds = %0
77   store i32 1, ptr %p
78   ret void
79 bb1:              ; preds = %0
80   store i32 2, ptr %p
81   ret void
82 bb2:              ; preds = %0
83   ret void
86 define i1 @common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr {
87 ; CHECK-LABEL: @common_instr_on_switch(
88 ; CHECK-NEXT:  start:
89 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
90 ; CHECK-NEXT:    ret i1 [[TMP0]]
92 start:
93   switch i64 %a, label %bb0 [
94   i64 1, label %bb1
95   i64 2, label %bb2
96   ]
98 bb0:                                              ; preds = %start
99   %0 = icmp eq i64 %b, %c
100   br label %exit
102 bb1:                                              ; preds = %start
103   %1 = icmp eq i64 %b, %c
104   br label %exit
106 bb2:                                              ; preds = %start
107   %2 = icmp eq i64 %b, %c
108   br label %exit
110 exit:                                             ; preds = %bb2, %bb1, %bb0
111   %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
112   ret i1 %result
115 define i1 @partial_common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr {
116 ; CHECK-LABEL: @partial_common_instr_on_switch(
117 ; CHECK-NEXT:  start:
118 ; CHECK-NEXT:    switch i64 [[A:%.*]], label [[BB0:%.*]] [
119 ; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
120 ; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
121 ; CHECK-NEXT:    ]
122 ; CHECK:       bb0:
123 ; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
124 ; CHECK-NEXT:    br label [[EXIT:%.*]]
125 ; CHECK:       bb1:
126 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[B]], [[C]]
127 ; CHECK-NEXT:    br label [[EXIT]]
128 ; CHECK:       bb2:
129 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
130 ; CHECK-NEXT:    br label [[EXIT]]
131 ; CHECK:       exit:
132 ; CHECK-NEXT:    [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
133 ; CHECK-NEXT:    ret i1 [[RESULT]]
135 start:
136   switch i64 %a, label %bb0 [
137   i64 1, label %bb1
138   i64 2, label %bb2
139   ]
141 bb0:                                              ; preds = %start
142   %0 = icmp eq i64 %b, %c
143   br label %exit
145 bb1:                                              ; preds = %start
146   %1 = icmp ne i64 %b, %c
147   br label %exit
149 bb2:                                              ; preds = %start
150   %2 = icmp eq i64 %b, %c
151   br label %exit
153 exit:                                             ; preds = %bb2, %bb1, %bb0
154   %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
155   ret i1 %result
158 declare void @foo()
160 define i1 @test_icmp_simple(i1 %c, i32 %a, i32 %b) {
161 ; CHECK-LABEL: @test_icmp_simple(
162 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
163 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
164 ; CHECK:       common.ret:
165 ; CHECK-NEXT:    ret i1 [[CMP1]]
166 ; CHECK:       if:
167 ; CHECK-NEXT:    call void @foo()
168 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
169 ; CHECK:       else:
170 ; CHECK-NEXT:    call void @bar()
171 ; CHECK-NEXT:    br label [[COMMON_RET]]
173   br i1 %c, label %if, label %else
176   %cmp1 = icmp ult i32 %a, %b
177   call void @foo()
178   ret i1 %cmp1
180 else:
181   %cmp2 = icmp ugt i32 %b, %a
182   call void @bar()
183   ret i1 %cmp2
186 define void @test_icmp_complex(i1 %c, i32 %a, i32 %b) {
187 ; CHECK-LABEL: @test_icmp_complex(
188 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
189 ; CHECK-NEXT:    br i1 [[CMP1]], label [[IF2:%.*]], label [[ELSE2:%.*]]
190 ; CHECK:       common.ret:
191 ; CHECK-NEXT:    ret void
192 ; CHECK:       if2:
193 ; CHECK-NEXT:    call void @foo()
194 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
195 ; CHECK:       else2:
196 ; CHECK-NEXT:    call void @bar()
197 ; CHECK-NEXT:    br label [[COMMON_RET]]
199   br i1 %c, label %if, label %else
202   %cmp1 = icmp ult i32 %a, %b
203   br i1 %cmp1, label %if2, label %else2
205 else:
206   %cmp2 = icmp ugt i32 %b, %a
207   br i1 %cmp2, label %if2, label %else2
209 if2:
210   call void @foo()
211   ret void
213 else2:
214   call void @bar()
215   ret void
218 define i1 @test_icmp_wrong_operands(i1 %c, i32 %a, i32 %b) {
219 ; CHECK-LABEL: @test_icmp_wrong_operands(
220 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
221 ; CHECK:       common.ret:
222 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
223 ; CHECK-NEXT:    ret i1 [[COMMON_RET_OP]]
224 ; CHECK:       if:
225 ; CHECK-NEXT:    [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
226 ; CHECK-NEXT:    call void @foo()
227 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
228 ; CHECK:       else:
229 ; CHECK-NEXT:    [[CMP2]] = icmp ugt i32 [[A]], [[B]]
230 ; CHECK-NEXT:    call void @bar()
231 ; CHECK-NEXT:    br label [[COMMON_RET]]
233   br i1 %c, label %if, label %else
236   %cmp1 = icmp ult i32 %a, %b
237   call void @foo()
238   ret i1 %cmp1
240 else:
241   %cmp2 = icmp ugt i32 %a, %b
242   call void @bar()
243   ret i1 %cmp2
246 define i1 @test_icmp_wrong_pred(i1 %c, i32 %a, i32 %b) {
247 ; CHECK-LABEL: @test_icmp_wrong_pred(
248 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
249 ; CHECK:       common.ret:
250 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
251 ; CHECK-NEXT:    ret i1 [[COMMON_RET_OP]]
252 ; CHECK:       if:
253 ; CHECK-NEXT:    [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
254 ; CHECK-NEXT:    call void @foo()
255 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
256 ; CHECK:       else:
257 ; CHECK-NEXT:    [[CMP2]] = icmp uge i32 [[B]], [[A]]
258 ; CHECK-NEXT:    call void @bar()
259 ; CHECK-NEXT:    br label [[COMMON_RET]]
261   br i1 %c, label %if, label %else
264   %cmp1 = icmp ult i32 %a, %b
265   call void @foo()
266   ret i1 %cmp1
268 else:
269   %cmp2 = icmp uge i32 %b, %a
270   call void @bar()
271   ret i1 %cmp2
274 define i32 @test_binop(i1 %c, i32 %a, i32 %b) {
275 ; CHECK-LABEL: @test_binop(
276 ; CHECK-NEXT:    [[OP1:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
277 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
278 ; CHECK:       common.ret:
279 ; CHECK-NEXT:    ret i32 [[OP1]]
280 ; CHECK:       if:
281 ; CHECK-NEXT:    call void @foo()
282 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
283 ; CHECK:       else:
284 ; CHECK-NEXT:    call void @bar()
285 ; CHECK-NEXT:    br label [[COMMON_RET]]
287   br i1 %c, label %if, label %else
290   %op1 = add i32 %a, %b
291   call void @foo()
292   ret i32 %op1
294 else:
295   %op2 = add i32 %b, %a
296   call void @bar()
297   ret i32 %op2
300 define i32 @test_binop_flags(i1 %c, i32 %a, i32 %b) {
301 ; CHECK-LABEL: @test_binop_flags(
302 ; CHECK-NEXT:    [[OP1:%.*]] = add nsw i32 [[A:%.*]], [[B:%.*]]
303 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
304 ; CHECK:       common.ret:
305 ; CHECK-NEXT:    ret i32 [[OP1]]
306 ; CHECK:       if:
307 ; CHECK-NEXT:    call void @foo()
308 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
309 ; CHECK:       else:
310 ; CHECK-NEXT:    call void @bar()
311 ; CHECK-NEXT:    br label [[COMMON_RET]]
313   br i1 %c, label %if, label %else
316   %op1 = add nuw nsw i32 %a, %b
317   call void @foo()
318   ret i32 %op1
320 else:
321   %op2 = add nsw i32 %b, %a
322   call void @bar()
323   ret i32 %op2
326 define i32 @test_binop_not_commutative(i1 %c, i32 %a, i32 %b) {
327 ; CHECK-LABEL: @test_binop_not_commutative(
328 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
329 ; CHECK:       common.ret:
330 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
331 ; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
332 ; CHECK:       if:
333 ; CHECK-NEXT:    [[OP1]] = sub i32 [[A:%.*]], [[B:%.*]]
334 ; CHECK-NEXT:    call void @foo()
335 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
336 ; CHECK:       else:
337 ; CHECK-NEXT:    [[OP2]] = sub i32 [[B]], [[A]]
338 ; CHECK-NEXT:    call void @bar()
339 ; CHECK-NEXT:    br label [[COMMON_RET]]
341   br i1 %c, label %if, label %else
344   %op1 = sub i32 %a, %b
345   call void @foo()
346   ret i32 %op1
348 else:
349   %op2 = sub i32 %b, %a
350   call void @bar()
351   ret i32 %op2
354 define i32 @test_binop_wrong_ops(i1 %c, i32 %a, i32 %b, i32 %d) {
355 ; CHECK-LABEL: @test_binop_wrong_ops(
356 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
357 ; CHECK:       common.ret:
358 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
359 ; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
360 ; CHECK:       if:
361 ; CHECK-NEXT:    [[OP1]] = add i32 [[A:%.*]], [[B:%.*]]
362 ; CHECK-NEXT:    call void @foo()
363 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
364 ; CHECK:       else:
365 ; CHECK-NEXT:    [[OP2]] = add i32 [[B]], [[D:%.*]]
366 ; CHECK-NEXT:    call void @bar()
367 ; CHECK-NEXT:    br label [[COMMON_RET]]
369   br i1 %c, label %if, label %else
372   %op1 = add i32 %a, %b
373   call void @foo()
374   ret i32 %op1
376 else:
377   %op2 = add i32 %b, %d
378   call void @bar()
379   ret i32 %op2
382 define i32 @test_intrin(i1 %c, i32 %a, i32 %b) {
383 ; CHECK-LABEL: @test_intrin(
384 ; CHECK-NEXT:    [[OP1:%.*]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 [[B:%.*]])
385 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
386 ; CHECK:       common.ret:
387 ; CHECK-NEXT:    ret i32 [[OP1]]
388 ; CHECK:       if:
389 ; CHECK-NEXT:    call void @foo()
390 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
391 ; CHECK:       else:
392 ; CHECK-NEXT:    call void @bar()
393 ; CHECK-NEXT:    br label [[COMMON_RET]]
395   br i1 %c, label %if, label %else
398   %op1 = call i32 @llvm.umin(i32 %a, i32 %b)
399   call void @foo()
400   ret i32 %op1
402 else:
403   %op2 = call i32 @llvm.umin(i32 %b, i32 %a)
404   call void @bar()
405   ret i32 %op2
408 define i32 @test_intrin_not_same(i1 %c, i32 %a, i32 %b) {
409 ; CHECK-LABEL: @test_intrin_not_same(
410 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
411 ; CHECK:       common.ret:
412 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
413 ; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
414 ; CHECK:       if:
415 ; CHECK-NEXT:    [[OP1]] = call i32 @llvm.umin.i32(i32 [[A:%.*]], i32 [[B:%.*]])
416 ; CHECK-NEXT:    call void @foo()
417 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
418 ; CHECK:       else:
419 ; CHECK-NEXT:    [[OP2]] = call i32 @llvm.umax.i32(i32 [[B]], i32 [[A]])
420 ; CHECK-NEXT:    call void @bar()
421 ; CHECK-NEXT:    br label [[COMMON_RET]]
423   br i1 %c, label %if, label %else
426   %op1 = call i32 @llvm.umin(i32 %a, i32 %b)
427   call void @foo()
428   ret i32 %op1
430 else:
431   %op2 = call i32 @llvm.umax(i32 %b, i32 %a)
432   call void @bar()
433   ret i32 %op2
436 define float @test_intrin_3arg(i1 %c, float %a, float %b, float %d) {
437 ; CHECK-LABEL: @test_intrin_3arg(
438 ; CHECK-NEXT:    [[OP1:%.*]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[D:%.*]])
439 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
440 ; CHECK:       common.ret:
441 ; CHECK-NEXT:    ret float [[OP1]]
442 ; CHECK:       if:
443 ; CHECK-NEXT:    call void @foo()
444 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
445 ; CHECK:       else:
446 ; CHECK-NEXT:    call void @bar()
447 ; CHECK-NEXT:    br label [[COMMON_RET]]
449   br i1 %c, label %if, label %else
452   %op1 = call float @llvm.fma(float %a, float %b, float %d)
453   call void @foo()
454   ret float %op1
456 else:
457   %op2 = call float @llvm.fma(float %b, float %a, float %d)
458   call void @bar()
459   ret float %op2
462 define float @test_intrin_3arg_wrong_args_commuted(i1 %c, float %a, float %b, float %d) {
463 ; CHECK-LABEL: @test_intrin_3arg_wrong_args_commuted(
464 ; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
465 ; CHECK:       common.ret:
466 ; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi float [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
467 ; CHECK-NEXT:    ret float [[COMMON_RET_OP]]
468 ; CHECK:       if:
469 ; CHECK-NEXT:    [[OP1]] = call float @llvm.fma.f32(float [[A:%.*]], float [[B:%.*]], float [[D:%.*]])
470 ; CHECK-NEXT:    call void @foo()
471 ; CHECK-NEXT:    br label [[COMMON_RET:%.*]]
472 ; CHECK:       else:
473 ; CHECK-NEXT:    [[OP2]] = call float @llvm.fma.f32(float [[A]], float [[D]], float [[B]])
474 ; CHECK-NEXT:    call void @bar()
475 ; CHECK-NEXT:    br label [[COMMON_RET]]
477   br i1 %c, label %if, label %else
480   %op1 = call float @llvm.fma(float %a, float %b, float %d)
481   call void @foo()
482   ret float %op1
484 else:
485   %op2 = call float @llvm.fma(float %a, float %d, float %b)
486   call void @bar()
487   ret float %op2