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
6 define void @test(i1 %P, ptr %Q) {
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
17 %A = load i32, ptr %Q ; <i32> [#uses=1]
18 call void @bar( i32 %A )
22 %B = load i32, ptr %Q ; <i32> [#uses=1]
23 call void @bar( i32 %B )
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 [
41 %A = load i32, ptr %Q ; <i32> [#uses=1]
42 call void @bar( i32 %A )
46 %B = load i32, ptr %Q ; <i32> [#uses=1]
47 call void @bar( i32 %B )
51 %C = load i32, ptr %Q ; <i32> [#uses=1]
52 call void @bar( i32 %C )
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:%.*]]
64 ; CHECK-NEXT: ret void
66 ; CHECK-NEXT: store i32 1, ptr [[P:%.*]], align 4
67 ; CHECK-NEXT: br label [[COMMON_RET]]
69 ; CHECK-NEXT: store i32 2, ptr [[P]], align 4
70 ; CHECK-NEXT: br label [[COMMON_RET]]
72 switch i64 %i, label %bb0 [
86 define i1 @common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr {
87 ; CHECK-LABEL: @common_instr_on_switch(
89 ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
90 ; CHECK-NEXT: ret i1 [[TMP0]]
93 switch i64 %a, label %bb0 [
99 %0 = icmp eq i64 %b, %c
102 bb1: ; preds = %start
103 %1 = icmp eq i64 %b, %c
106 bb2: ; preds = %start
107 %2 = icmp eq i64 %b, %c
110 exit: ; preds = %bb2, %bb1, %bb0
111 %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
115 define i1 @partial_common_instr_on_switch(i64 %a, i64 %b, i64 %c) unnamed_addr {
116 ; CHECK-LABEL: @partial_common_instr_on_switch(
118 ; CHECK-NEXT: switch i64 [[A:%.*]], label [[BB0:%.*]] [
119 ; CHECK-NEXT: i64 1, label [[BB1:%.*]]
120 ; CHECK-NEXT: i64 2, label [[BB2:%.*]]
123 ; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
124 ; CHECK-NEXT: br label [[EXIT:%.*]]
126 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[B]], [[C]]
127 ; CHECK-NEXT: br label [[EXIT]]
129 ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
130 ; CHECK-NEXT: br label [[EXIT]]
132 ; CHECK-NEXT: [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
133 ; CHECK-NEXT: ret i1 [[RESULT]]
136 switch i64 %a, label %bb0 [
141 bb0: ; preds = %start
142 %0 = icmp eq i64 %b, %c
145 bb1: ; preds = %start
146 %1 = icmp ne i64 %b, %c
149 bb2: ; preds = %start
150 %2 = icmp eq i64 %b, %c
153 exit: ; preds = %bb2, %bb1, %bb0
154 %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
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:%.*]]
165 ; CHECK-NEXT: ret i1 [[CMP1]]
167 ; CHECK-NEXT: call void @foo()
168 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
181 %cmp2 = icmp ugt i32 %b, %a
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:%.*]]
191 ; CHECK-NEXT: ret void
193 ; CHECK-NEXT: call void @foo()
194 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
206 %cmp2 = icmp ugt i32 %b, %a
207 br i1 %cmp2, label %if2, label %else2
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:%.*]]
222 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
223 ; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
225 ; CHECK-NEXT: [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
226 ; CHECK-NEXT: call void @foo()
227 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
241 %cmp2 = icmp ugt i32 %a, %b
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:%.*]]
250 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ [[CMP1:%.*]], [[IF]] ], [ [[CMP2:%.*]], [[ELSE]] ]
251 ; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
253 ; CHECK-NEXT: [[CMP1]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
254 ; CHECK-NEXT: call void @foo()
255 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
269 %cmp2 = icmp uge i32 %b, %a
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:%.*]]
279 ; CHECK-NEXT: ret i32 [[OP1]]
281 ; CHECK-NEXT: call void @foo()
282 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
295 %op2 = add i32 %b, %a
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:%.*]]
305 ; CHECK-NEXT: ret i32 [[OP1]]
307 ; CHECK-NEXT: call void @foo()
308 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
321 %op2 = add nsw i32 %b, %a
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:%.*]]
330 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
331 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
333 ; CHECK-NEXT: [[OP1]] = sub i32 [[A:%.*]], [[B:%.*]]
334 ; CHECK-NEXT: call void @foo()
335 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
349 %op2 = sub i32 %b, %a
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:%.*]]
358 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
359 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
361 ; CHECK-NEXT: [[OP1]] = add i32 [[A:%.*]], [[B:%.*]]
362 ; CHECK-NEXT: call void @foo()
363 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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
377 %op2 = add i32 %b, %d
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:%.*]]
387 ; CHECK-NEXT: ret i32 [[OP1]]
389 ; CHECK-NEXT: call void @foo()
390 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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)
403 %op2 = call i32 @llvm.umin(i32 %b, i32 %a)
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:%.*]]
412 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
413 ; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
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:%.*]]
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)
431 %op2 = call i32 @llvm.umax(i32 %b, i32 %a)
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:%.*]]
441 ; CHECK-NEXT: ret float [[OP1]]
443 ; CHECK-NEXT: call void @foo()
444 ; CHECK-NEXT: br label [[COMMON_RET:%.*]]
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)
457 %op2 = call float @llvm.fma(float %b, float %a, float %d)
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:%.*]]
466 ; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi float [ [[OP1:%.*]], [[IF]] ], [ [[OP2:%.*]], [[ELSE]] ]
467 ; CHECK-NEXT: ret float [[COMMON_RET_OP]]
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:%.*]]
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)
485 %op2 = call float @llvm.fma(float %a, float %d, float %b)