1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts -S | FileCheck %s
3 ; RUN: opt < %s -passes='simplifycfg<sink-common-insts>' -S | FileCheck %s
5 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
6 target triple = "x86_64-pc-linux-gnu"
8 define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
11 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS:%.*]], [[BLKSB:%.*]]
12 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA:%.*]]
13 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA]], [[NBLKS]]
14 ; CHECK-NEXT: [[CMP2_SINK:%.*]] = select i1 [[FLAG:%.*]], i1 [[CMP]], i1 [[CMP2]]
15 ; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8
16 ; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL3]], 0
17 ; CHECK-NEXT: ret i1 [[TOBOOL4]]
20 br i1 %flag, label %if.then, label %if.else
23 %cmp = icmp uge i32 %blksA, %nblks
24 %frombool1 = zext i1 %cmp to i8
28 %add = add i32 %nblks, %blksB
29 %cmp2 = icmp ule i32 %add, %blksA
30 %frombool3 = zext i1 %cmp2 to i8
34 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ]
35 %tobool4 = icmp ne i8 %obeys.0, 0
39 define zeroext i1 @test2(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
40 ; CHECK-LABEL: @test2(
42 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS:%.*]], [[BLKSB:%.*]]
43 ; CHECK-NEXT: [[ADD_SINK:%.*]] = select i1 [[FLAG:%.*]], i32 [[NBLKS]], i32 [[ADD]]
44 ; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[ADD_SINK]]
45 ; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8
46 ; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL3]], 0
47 ; CHECK-NEXT: ret i1 [[TOBOOL4]]
50 br i1 %flag, label %if.then, label %if.else
53 %cmp = icmp uge i32 %blksA, %nblks
54 %frombool1 = zext i1 %cmp to i8
58 %add = add i32 %nblks, %blksB
59 %cmp2 = icmp uge i32 %blksA, %add
60 %frombool3 = zext i1 %cmp2 to i8
64 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ]
65 %tobool4 = icmp ne i8 %obeys.0, 0
69 declare i32 @foo(i32, i32) nounwind readnone
71 define i32 @test3(i1 zeroext %flag, i32 %x, i32 %y) {
72 ; CHECK-LABEL: @test3(
74 ; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]
75 ; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0:[0-9]+]]
76 ; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]]
77 ; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Y1]]
78 ; CHECK-NEXT: ret i32 [[RET]]
81 br i1 %flag, label %if.then, label %if.else
84 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone
85 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone
89 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone
90 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone
94 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ]
95 %yy = phi i32 [ %y0, %if.then ], [ %y1, %if.else ]
96 %ret = add i32 %xx, %yy
101 define i32 @test4(i1 zeroext %flag, i32 %x, i32* %y) {
102 ; CHECK-LABEL: @test4(
104 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7
105 ; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], [[DOT]]
106 ; CHECK-NEXT: store i32 [[B]], i32* [[Y:%.*]], align 4
107 ; CHECK-NEXT: ret i32 1
110 br i1 %flag, label %if.then, label %if.else
114 store i32 %a, i32* %y
119 store i32 %b, i32* %y
127 define i32 @test5(i1 zeroext %flag, i32 %x, i32* %y) {
128 ; CHECK-LABEL: @test5(
130 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
132 ; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 5
133 ; CHECK-NEXT: store volatile i32 [[A]], i32* [[Y:%.*]], align 4
134 ; CHECK-NEXT: br label [[IF_END:%.*]]
136 ; CHECK-NEXT: [[B:%.*]] = add i32 [[X]], 7
137 ; CHECK-NEXT: store i32 [[B]], i32* [[Y]], align 4
138 ; CHECK-NEXT: br label [[IF_END]]
140 ; CHECK-NEXT: ret i32 1
143 br i1 %flag, label %if.then, label %if.else
147 store volatile i32 %a, i32* %y
152 store i32 %b, i32* %y
160 define i32 @test6(i1 zeroext %flag, i32 %x, i32* %y) {
161 ; CHECK-LABEL: @test6(
163 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7
164 ; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], [[DOT]]
165 ; CHECK-NEXT: store volatile i32 [[B]], i32* [[Y:%.*]], align 4
166 ; CHECK-NEXT: ret i32 1
169 br i1 %flag, label %if.then, label %if.else
173 store volatile i32 %a, i32* %y
178 store volatile i32 %b, i32* %y
186 define i32 @test7(i1 zeroext %flag, i32 %x, i32* %y) {
187 ; CHECK-LABEL: @test7(
189 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7
190 ; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4
191 ; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], [[DOT]]
192 ; CHECK-NEXT: store volatile i32 [[B]], i32* [[Y]], align 4
193 ; CHECK-NEXT: ret i32 1
196 br i1 %flag, label %if.then, label %if.else
199 %z = load volatile i32, i32* %y
201 store volatile i32 %a, i32* %y
205 %w = load volatile i32, i32* %y
207 store volatile i32 %b, i32* %y
215 ; %z and %w are in different blocks. We shouldn't sink the add because
216 ; there may be intervening memory instructions.
217 define i32 @test8(i1 zeroext %flag, i32 %x, i32* %y) {
218 ; CHECK-LABEL: @test8(
220 ; CHECK-NEXT: [[Z:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4
221 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
223 ; CHECK-NEXT: [[A:%.*]] = add i32 [[Z]], 5
224 ; CHECK-NEXT: br label [[IF_END:%.*]]
226 ; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y]], align 4
227 ; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], 7
228 ; CHECK-NEXT: br label [[IF_END]]
230 ; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[B]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ]
231 ; CHECK-NEXT: store volatile i32 [[B_SINK]], i32* [[Y]], align 4
232 ; CHECK-NEXT: ret i32 1
235 %z = load volatile i32, i32* %y
236 br i1 %flag, label %if.then, label %if.else
240 store volatile i32 %a, i32* %y
244 %w = load volatile i32, i32* %y
246 store volatile i32 %b, i32* %y
254 ; The extra store in %if.then means %z and %w are not equivalent.
255 define i32 @test9(i1 zeroext %flag, i32 %x, i32* %y, i32* %p) {
256 ; CHECK-LABEL: @test9(
258 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
260 ; CHECK-NEXT: store i32 7, i32* [[P:%.*]], align 4
261 ; CHECK-NEXT: [[Z:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4
262 ; CHECK-NEXT: store i32 6, i32* [[P]], align 4
263 ; CHECK-NEXT: [[A:%.*]] = add i32 [[Z]], 5
264 ; CHECK-NEXT: br label [[IF_END:%.*]]
266 ; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y]], align 4
267 ; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], 7
268 ; CHECK-NEXT: br label [[IF_END]]
270 ; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[B]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ]
271 ; CHECK-NEXT: store volatile i32 [[B_SINK]], i32* [[Y]], align 4
272 ; CHECK-NEXT: ret i32 1
275 br i1 %flag, label %if.then, label %if.else
279 %z = load volatile i32, i32* %y
282 store volatile i32 %a, i32* %y
286 %w = load volatile i32, i32* %y
288 store volatile i32 %b, i32* %y
296 %struct.anon = type { i32, i32 }
298 ; The GEP indexes a struct type so cannot have a variable last index.
299 define i32 @test10(i1 zeroext %flag, i32 %x, i32* %y, %struct.anon* %s) {
300 ; CHECK-LABEL: @test10(
302 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
304 ; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[X:%.*]], 5
305 ; CHECK-NEXT: [[GEPA:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[S:%.*]], i32 0, i32 0
306 ; CHECK-NEXT: br label [[IF_END:%.*]]
308 ; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[X]], 6
309 ; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[S]], i32 0, i32 1
310 ; CHECK-NEXT: br label [[IF_END]]
312 ; CHECK-NEXT: [[GEPB_SINK:%.*]] = phi i32* [ [[GEPB]], [[IF_ELSE]] ], [ [[GEPA]], [[IF_THEN]] ]
313 ; CHECK-NEXT: store volatile i32 [[X]], i32* [[GEPB_SINK]], align 4
314 ; CHECK-NEXT: ret i32 1
317 br i1 %flag, label %if.then, label %if.else
320 %dummy = add i32 %x, 5
321 %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 0
322 store volatile i32 %x, i32* %gepa
326 %dummy1 = add i32 %x, 6
327 %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
328 store volatile i32 %x, i32* %gepb
336 ; The shufflevector's mask operand cannot be merged in a PHI.
337 define i32 @test11(i1 zeroext %flag, i32 %w, <2 x i32> %x, <2 x i32> %y) {
338 ; CHECK-LABEL: @test11(
340 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
342 ; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5
343 ; CHECK-NEXT: [[SV1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 0, i32 1>
344 ; CHECK-NEXT: br label [[IF_END:%.*]]
346 ; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6
347 ; CHECK-NEXT: [[SV2:%.*]] = shufflevector <2 x i32> [[X]], <2 x i32> [[Y]], <2 x i32> <i32 1, i32 0>
348 ; CHECK-NEXT: br label [[IF_END]]
350 ; CHECK-NEXT: [[P:%.*]] = phi <2 x i32> [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ]
351 ; CHECK-NEXT: ret i32 1
354 br i1 %flag, label %if.then, label %if.else
357 %dummy = add i32 %w, 5
358 %sv1 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 0, i32 1>
362 %dummy1 = add i32 %w, 6
363 %sv2 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 1, i32 0>
367 %p = phi <2 x i32> [ %sv1, %if.then ], [ %sv2, %if.else ]
372 ; We can't common an intrinsic!
373 define i32 @test12(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) {
374 ; CHECK-LABEL: @test12(
376 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
378 ; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5
379 ; CHECK-NEXT: [[SV1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false)
380 ; CHECK-NEXT: br label [[IF_END:%.*]]
382 ; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6
383 ; CHECK-NEXT: [[SV2:%.*]] = call i32 @llvm.cttz.i32(i32 [[X]], i1 false)
384 ; CHECK-NEXT: br label [[IF_END]]
386 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ]
387 ; CHECK-NEXT: ret i32 1
390 br i1 %flag, label %if.then, label %if.else
393 %dummy = add i32 %w, 5
394 %sv1 = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
398 %dummy1 = add i32 %w, 6
399 %sv2 = call i32 @llvm.cttz.i32(i32 %x, i1 false)
403 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ]
407 declare i32 @llvm.ctlz.i32(i32 %x, i1 immarg) readnone
408 declare i32 @llvm.cttz.i32(i32 %x, i1 immarg) readnone
411 ; The TBAA metadata should be properly combined.
412 define i32 @test13(i1 zeroext %flag, i32 %x, i32* %y) {
413 ; CHECK-LABEL: @test13(
415 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7
416 ; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4
417 ; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], [[DOT]]
418 ; CHECK-NEXT: store volatile i32 [[B]], i32* [[Y]], align 4, !tbaa [[TBAA4:![0-9]+]]
419 ; CHECK-NEXT: ret i32 1
422 br i1 %flag, label %if.then, label %if.else
425 %z = load volatile i32, i32* %y
427 store volatile i32 %a, i32* %y, !tbaa !3
431 %w = load volatile i32, i32* %y
433 store volatile i32 %b, i32* %y, !tbaa !4
440 !0 = !{ !"an example type tree" }
442 !2 = !{ !"float", !0 }
443 !3 = !{ !"const float", !2, i64 0 }
444 !4 = !{ !"special float", !2, i64 1 }
447 ; The call should be commoned.
448 define i32 @test13a(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) {
449 ; CHECK-LABEL: @test13a(
451 ; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]
452 ; CHECK-NEXT: [[SV2:%.*]] = call i32 @bar(i32 [[X_Y]])
453 ; CHECK-NEXT: ret i32 1
456 br i1 %flag, label %if.then, label %if.else
459 %sv1 = call i32 @bar(i32 %x)
463 %sv2 = call i32 @bar(i32 %y)
467 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ]
470 declare i32 @bar(i32)
473 ; The load should be commoned.
474 define i32 @test14(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, %struct.anon* %s) {
475 ; CHECK-LABEL: @test14(
477 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 1, i32 4
478 ; CHECK-NEXT: [[DOT2:%.*]] = select i1 [[FLAG]], i32 56, i32 57
479 ; CHECK-NEXT: [[DUMMY2:%.*]] = add i32 [[X:%.*]], [[DOT]]
480 ; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[S:%.*]], i32 0, i32 1
481 ; CHECK-NEXT: [[SV2:%.*]] = load i32, i32* [[GEPB]], align 4
482 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[SV2]], [[DOT2]]
483 ; CHECK-NEXT: ret i32 1
486 br i1 %flag, label %if.then, label %if.else
489 %dummy = add i32 %x, 1
490 %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
491 %sv1 = load i32, i32* %gepa
492 %cmp1 = icmp eq i32 %sv1, 56
496 %dummy2 = add i32 %x, 4
497 %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
498 %sv2 = load i32, i32* %gepb
499 %cmp2 = icmp eq i32 %sv2, 57
500 call void @llvm.dbg.value(metadata i32 0, metadata !9, metadata !DIExpression()), !dbg !11
504 %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ]
508 declare void @llvm.dbg.value(metadata, metadata, metadata)
509 !llvm.module.flags = !{!5, !6}
512 !5 = !{i32 2, !"Dwarf Version", i32 4}
513 !6 = !{i32 2, !"Debug Info Version", i32 3}
514 !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !10)
515 !8 = distinct !DISubprogram(name: "foo", unit: !7)
516 !9 = !DILocalVariable(name: "b", line: 1, arg: 2, scope: !8)
517 !10 = !DIFile(filename: "a.c", directory: "a/b")
518 !11 = !DILocation(line: 1, column: 14, scope: !8)
521 ; The load should be commoned.
522 define i32 @test15(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, %struct.anon* %s) {
523 ; CHECK-LABEL: @test15(
525 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
527 ; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[X:%.*]], 1
528 ; CHECK-NEXT: [[GEPA:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[S:%.*]], i32 0, i32 0
529 ; CHECK-NEXT: br label [[IF_END:%.*]]
531 ; CHECK-NEXT: [[DUMMY2:%.*]] = add i32 [[X]], 4
532 ; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[S]], i32 0, i32 1
533 ; CHECK-NEXT: br label [[IF_END]]
535 ; CHECK-NEXT: [[GEPB_SINK:%.*]] = phi i32* [ [[GEPB]], [[IF_ELSE]] ], [ [[GEPA]], [[IF_THEN]] ]
536 ; CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ 57, [[IF_ELSE]] ], [ 56, [[IF_THEN]] ]
537 ; CHECK-NEXT: [[SV2:%.*]] = load i32, i32* [[GEPB_SINK]], align 4
538 ; CHECK-NEXT: [[EXT2:%.*]] = zext i32 [[SV2]] to i64
539 ; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i64 [[EXT2]], [[DOTSINK]]
540 ; CHECK-NEXT: ret i32 1
543 br i1 %flag, label %if.then, label %if.else
546 %dummy = add i32 %x, 1
547 %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 0
548 %sv1 = load i32, i32* %gepa
549 %ext1 = zext i32 %sv1 to i64
550 %cmp1 = icmp eq i64 %ext1, 56
554 %dummy2 = add i32 %x, 4
555 %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1
556 %sv2 = load i32, i32* %gepb
557 %ext2 = zext i32 %sv2 to i64
558 %cmp2 = icmp eq i64 %ext2, 57
562 %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ]
567 define zeroext i1 @test_crash(i1 zeroext %flag, i32* %i4, i32* %m, i32* %n) {
568 ; CHECK-LABEL: @test_crash(
570 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
572 ; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[I4:%.*]], align 4
573 ; CHECK-NEXT: br label [[IF_END:%.*]]
575 ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[M:%.*]], align 4
576 ; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[N:%.*]], align 4
577 ; CHECK-NEXT: br label [[IF_END]]
579 ; CHECK-NEXT: [[TMP4_SINK:%.*]] = phi i32 [ [[TMP4]], [[IF_ELSE]] ], [ -1, [[IF_THEN]] ]
580 ; CHECK-NEXT: [[TMP3_SINK:%.*]] = phi i32 [ [[TMP3]], [[IF_ELSE]] ], [ [[TMP1]], [[IF_THEN]] ]
581 ; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP3_SINK]], [[TMP4_SINK]]
582 ; CHECK-NEXT: store i32 [[TMP5]], i32* [[I4]], align 4
583 ; CHECK-NEXT: ret i1 true
586 br i1 %flag, label %if.then, label %if.else
589 %tmp1 = load i32, i32* %i4
590 %tmp2 = add i32 %tmp1, -1
591 store i32 %tmp2, i32* %i4
595 %tmp3 = load i32, i32* %m
596 %tmp4 = load i32, i32* %n
597 %tmp5 = add i32 %tmp3, %tmp4
598 store i32 %tmp5, i32* %i4
605 ; No checks for test_crash - just ensure it doesn't crash!
607 define zeroext i1 @test16(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) {
608 ; CHECK-LABEL: @test16(
610 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
612 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
613 ; CHECK-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[CMP]] to i8
614 ; CHECK-NEXT: br label [[IF_END:%.*]]
616 ; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END]]
618 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]]
619 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]]
620 ; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8
621 ; CHECK-NEXT: br label [[IF_END]]
623 ; CHECK-NEXT: [[OBEYS_0:%.*]] = phi i8 [ [[FROMBOOL1]], [[IF_THEN]] ], [ [[FROMBOOL3]], [[IF_THEN2]] ], [ 0, [[IF_ELSE]] ]
624 ; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[OBEYS_0]], 0
625 ; CHECK-NEXT: ret i1 [[TOBOOL4]]
628 br i1 %flag, label %if.then, label %if.else
631 %cmp = icmp uge i32 %blksA, %nblks
632 %frombool1 = zext i1 %cmp to i8
636 br i1 %flag2, label %if.then2, label %if.end
639 %add = add i32 %nblks, %blksB
640 %cmp2 = icmp ule i32 %add, %blksA
641 %frombool3 = zext i1 %cmp2 to i8
645 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %if.else ]
646 %tobool4 = icmp ne i8 %obeys.0, 0
651 define zeroext i1 @test16a(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks, i8* %p) {
652 ; CHECK-LABEL: @test16a(
654 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
656 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
657 ; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]]
659 ; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END:%.*]]
661 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]]
662 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]]
663 ; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]]
664 ; CHECK: if.end.sink.split:
665 ; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ]
666 ; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8
667 ; CHECK-NEXT: store i8 [[FROMBOOL3]], i8* [[P:%.*]], align 1
668 ; CHECK-NEXT: br label [[IF_END]]
670 ; CHECK-NEXT: ret i1 true
673 br i1 %flag, label %if.then, label %if.else
676 %cmp = icmp uge i32 %blksA, %nblks
677 %frombool1 = zext i1 %cmp to i8
678 store i8 %frombool1, i8* %p
682 br i1 %flag2, label %if.then2, label %if.end
685 %add = add i32 %nblks, %blksB
686 %cmp2 = icmp ule i32 %add, %blksA
687 %frombool3 = zext i1 %cmp2 to i8
688 store i8 %frombool3, i8* %p
696 define zeroext i1 @test17(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
697 ; CHECK-LABEL: @test17(
699 ; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_END:%.*]] [
700 ; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]]
701 ; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]]
704 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
705 ; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]]
707 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]]
708 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]]
709 ; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]]
710 ; CHECK: if.end.sink.split:
711 ; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ]
712 ; CHECK-NEXT: [[FROMBOOL3:%.*]] = call i8 @i1toi8(i1 [[CMP2_SINK]])
713 ; CHECK-NEXT: br label [[IF_END]]
715 ; CHECK-NEXT: [[OBEYS_0:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[FROMBOOL3]], [[IF_END_SINK_SPLIT]] ]
716 ; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[OBEYS_0]], 0
717 ; CHECK-NEXT: ret i1 [[TOBOOL4]]
720 switch i32 %flag, label %if.end [
721 i32 0, label %if.then
722 i32 1, label %if.then2
726 %cmp = icmp uge i32 %blksA, %nblks
727 %frombool1 = call i8 @i1toi8(i1 %cmp)
731 %add = add i32 %nblks, %blksB
732 %cmp2 = icmp ule i32 %add, %blksA
733 %frombool3 = call i8 @i1toi8(i1 %cmp2)
737 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %entry ]
738 %tobool4 = icmp ne i8 %obeys.0, 0
741 declare i8 @i1toi8(i1)
747 define zeroext i1 @test18(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) {
748 ; CHECK-LABEL: @test18(
750 ; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_THEN3:%.*]] [
751 ; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]]
752 ; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]]
755 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
756 ; CHECK-NEXT: br label [[IF_END:%.*]]
758 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]]
759 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]]
760 ; CHECK-NEXT: br label [[IF_END]]
762 ; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[NBLKS]], [[BLKSA]]
763 ; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[ADD2]], [[BLKSA]]
764 ; CHECK-NEXT: br label [[IF_END]]
766 ; CHECK-NEXT: [[CMP3_SINK:%.*]] = phi i1 [ [[CMP3]], [[IF_THEN3]] ], [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ]
767 ; CHECK-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[CMP3_SINK]] to i8
768 ; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL4]], 0
769 ; CHECK-NEXT: ret i1 [[TOBOOL4]]
772 switch i32 %flag, label %if.then3 [
773 i32 0, label %if.then
774 i32 1, label %if.then2
778 %cmp = icmp uge i32 %blksA, %nblks
779 %frombool1 = zext i1 %cmp to i8
783 %add = add i32 %nblks, %blksB
784 %cmp2 = icmp ule i32 %add, %blksA
785 %frombool3 = zext i1 %cmp2 to i8
789 %add2 = add i32 %nblks, %blksA
790 %cmp3 = icmp ule i32 %add2, %blksA
791 %frombool4 = zext i1 %cmp3 to i8
795 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ %frombool4, %if.then3 ]
796 %tobool4 = icmp ne i8 %obeys.0, 0
801 define i32 @test_pr30188(i1 zeroext %flag, i32 %x) {
802 ; CHECK-LABEL: @test_pr30188(
804 ; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4
805 ; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4
806 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
808 ; CHECK-NEXT: store i32 [[X:%.*]], i32* [[Y]], align 4
809 ; CHECK-NEXT: br label [[IF_END:%.*]]
811 ; CHECK-NEXT: store i32 [[X]], i32* [[Z]], align 4
812 ; CHECK-NEXT: br label [[IF_END]]
814 ; CHECK-NEXT: ret i32 1
819 br i1 %flag, label %if.then, label %if.else
822 store i32 %x, i32* %y
826 store i32 %x, i32* %z
834 define i32 @test_pr30188a(i1 zeroext %flag, i32 %x) {
835 ; CHECK-LABEL: @test_pr30188a(
837 ; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4
838 ; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4
839 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
841 ; CHECK-NEXT: call void @g()
842 ; CHECK-NEXT: [[ONE:%.*]] = load i32, i32* [[Y]], align 4
843 ; CHECK-NEXT: [[TWO:%.*]] = add i32 [[ONE]], 2
844 ; CHECK-NEXT: store i32 [[TWO]], i32* [[Y]], align 4
845 ; CHECK-NEXT: br label [[IF_END:%.*]]
847 ; CHECK-NEXT: [[THREE:%.*]] = load i32, i32* [[Z]], align 4
848 ; CHECK-NEXT: [[FOUR:%.*]] = add i32 [[THREE]], 2
849 ; CHECK-NEXT: store i32 [[FOUR]], i32* [[Y]], align 4
850 ; CHECK-NEXT: br label [[IF_END]]
852 ; CHECK-NEXT: ret i32 1
857 br i1 %flag, label %if.then, label %if.else
861 %one = load i32, i32* %y
862 %two = add i32 %one, 2
863 store i32 %two, i32* %y
867 %three = load i32, i32* %z
868 %four = add i32 %three, 2
869 store i32 %four, i32* %y
877 ; The phi is confusing - both add instructions are used by it, but
878 ; not on their respective unconditional arcs. It should not be
880 define void @test_pr30292(i1 %cond, i1 %cond2, i32 %a, i32 %b) {
881 ; CHECK-LABEL: @test_pr30292(
883 ; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], 1
884 ; CHECK-NEXT: br label [[SUCC:%.*]]
886 ; CHECK-NEXT: call void @g()
887 ; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[A]], 1
888 ; CHECK-NEXT: br label [[SUCC]]
890 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ], [ [[ADD2]], [[TWO:%.*]] ]
891 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[TWO]], label [[SUCC]]
894 %add1 = add i32 %a, 1
898 br i1 %cond, label %two, label %succ
902 %add2 = add i32 %a, 1
906 %p = phi i32 [ 0, %entry ], [ %add1, %one ], [ %add2, %two ]
912 define zeroext i1 @test_pr30244(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) {
913 ; CHECK-LABEL: @test_pr30244(
915 ; CHECK-NEXT: [[P:%.*]] = alloca i8, align 1
916 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
918 ; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]]
919 ; CHECK-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[CMP]] to i8
920 ; CHECK-NEXT: store i8 [[FROMBOOL1]], i8* [[P]], align 1
921 ; CHECK-NEXT: br label [[IF_END:%.*]]
923 ; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END]]
925 ; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]]
926 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]]
927 ; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8
928 ; CHECK-NEXT: store i8 [[FROMBOOL3]], i8* [[P]], align 1
929 ; CHECK-NEXT: br label [[IF_END]]
931 ; CHECK-NEXT: ret i1 true
935 br i1 %flag, label %if.then, label %if.else
938 %cmp = icmp uge i32 %blksA, %nblks
939 %frombool1 = zext i1 %cmp to i8
940 store i8 %frombool1, i8* %p
944 br i1 %flag2, label %if.then2, label %if.end
947 %add = add i32 %nblks, %blksB
948 %cmp2 = icmp ule i32 %add, %blksA
949 %frombool3 = zext i1 %cmp2 to i8
950 store i8 %frombool3, i8* %p
958 define i32 @test_pr30373a(i1 zeroext %flag, i32 %x, i32 %y) {
959 ; CHECK-LABEL: @test_pr30373a(
961 ; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]
962 ; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0]]
963 ; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]]
964 ; CHECK-NEXT: [[Z1:%.*]] = lshr i32 [[Y1]], 8
965 ; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Z1]]
966 ; CHECK-NEXT: ret i32 [[RET]]
969 br i1 %flag, label %if.then, label %if.else
972 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone
973 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone
974 %z0 = lshr i32 %y0, 8
978 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone
979 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone
980 %z1 = lshr exact i32 %y1, 8
984 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ]
985 %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ]
986 %ret = add i32 %xx, %yy
991 define i32 @test_pr30373b(i1 zeroext %flag, i32 %x, i32 %y) {
992 ; CHECK-LABEL: @test_pr30373b(
994 ; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]
995 ; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0]]
996 ; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]]
997 ; CHECK-NEXT: [[Z1:%.*]] = lshr i32 [[Y1]], 8
998 ; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Z1]]
999 ; CHECK-NEXT: ret i32 [[RET]]
1002 br i1 %flag, label %if.then, label %if.else
1005 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone
1006 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone
1007 %z0 = lshr exact i32 %y0, 8
1011 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone
1012 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone
1013 %z1 = lshr i32 %y1, 8
1017 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ]
1018 %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ]
1019 %ret = add i32 %xx, %yy
1025 ; FIXME: Should turn into select
1026 define float @allow_intrinsic_remove_constant(i1 zeroext %flag, float %w, float %x, float %y) {
1027 ; CHECK-LABEL: @allow_intrinsic_remove_constant(
1028 ; CHECK-NEXT: entry:
1029 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1031 ; CHECK-NEXT: [[DUMMY:%.*]] = fadd float [[W:%.*]], 4.000000e+00
1032 ; CHECK-NEXT: [[SV1:%.*]] = call float @llvm.fma.f32(float [[DUMMY]], float 2.000000e+00, float 1.000000e+00)
1033 ; CHECK-NEXT: br label [[IF_END:%.*]]
1035 ; CHECK-NEXT: [[DUMMY1:%.*]] = fadd float [[W]], 8.000000e+00
1036 ; CHECK-NEXT: [[SV2:%.*]] = call float @llvm.fma.f32(float 2.000000e+00, float [[DUMMY1]], float 1.000000e+00)
1037 ; CHECK-NEXT: br label [[IF_END]]
1039 ; CHECK-NEXT: [[P:%.*]] = phi float [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ]
1040 ; CHECK-NEXT: ret float [[P]]
1043 br i1 %flag, label %if.then, label %if.else
1046 %dummy = fadd float %w, 4.0
1047 %sv1 = call float @llvm.fma.f32(float %dummy, float 2.0, float 1.0)
1051 %dummy1 = fadd float %w, 8.0
1052 %sv2 = call float @llvm.fma.f32(float 2.0, float %dummy1, float 1.0)
1056 %p = phi float [ %sv1, %if.then ], [ %sv2, %if.else ]
1060 declare float @llvm.fma.f32(float, float, float)
1062 define i32 @no_remove_constant_immarg(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) {
1063 ; CHECK-LABEL: @no_remove_constant_immarg(
1064 ; CHECK-NEXT: entry:
1065 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1067 ; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5
1068 ; CHECK-NEXT: [[SV1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true)
1069 ; CHECK-NEXT: br label [[IF_END:%.*]]
1071 ; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6
1072 ; CHECK-NEXT: [[SV2:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X]], i1 false)
1073 ; CHECK-NEXT: br label [[IF_END]]
1075 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ]
1076 ; CHECK-NEXT: ret i32 1
1079 br i1 %flag, label %if.then, label %if.else
1082 %dummy = add i32 %w, 5
1083 %sv1 = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
1087 %dummy1 = add i32 %w, 6
1088 %sv2 = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
1092 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ]
1096 declare void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture readonly, i64, i1)
1098 ; Make sure a memcpy size isn't replaced with a variable
1099 define void @no_replace_memcpy_size(i1 zeroext %flag, i8 addrspace(1)* %dst, i8 addrspace(1)* %src) {
1100 ; CHECK-LABEL: @no_replace_memcpy_size(
1101 ; CHECK-NEXT: entry:
1102 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1104 ; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* [[DST:%.*]], i8 addrspace(1)* [[SRC:%.*]], i64 1024, i1 false)
1105 ; CHECK-NEXT: br label [[IF_END:%.*]]
1107 ; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* [[DST]], i8 addrspace(1)* [[SRC]], i64 4096, i1 false)
1108 ; CHECK-NEXT: br label [[IF_END]]
1110 ; CHECK-NEXT: ret void
1113 br i1 %flag, label %if.then, label %if.else
1116 call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 1024, i1 false)
1120 call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 4096, i1 false)
1127 declare void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture readonly, i64, i1)
1129 ; Make sure a memmove size isn't replaced with a variable
1130 define void @no_replace_memmove_size(i1 zeroext %flag, i8 addrspace(1)* %dst, i8 addrspace(1)* %src) {
1131 ; CHECK-LABEL: @no_replace_memmove_size(
1132 ; CHECK-NEXT: entry:
1133 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1135 ; CHECK-NEXT: call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* [[DST:%.*]], i8 addrspace(1)* [[SRC:%.*]], i64 1024, i1 false)
1136 ; CHECK-NEXT: br label [[IF_END:%.*]]
1138 ; CHECK-NEXT: call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* [[DST]], i8 addrspace(1)* [[SRC]], i64 4096, i1 false)
1139 ; CHECK-NEXT: br label [[IF_END]]
1141 ; CHECK-NEXT: ret void
1144 br i1 %flag, label %if.then, label %if.else
1147 call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 1024, i1 false)
1151 call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 4096, i1 false)
1158 declare void @llvm.memset.p1i8.i64(i8 addrspace(1)* nocapture, i8, i64, i1)
1160 ; Make sure a memset size isn't replaced with a variable
1161 define void @no_replace_memset_size(i1 zeroext %flag, i8 addrspace(1)* %dst) {
1162 ; CHECK-LABEL: @no_replace_memset_size(
1163 ; CHECK-NEXT: entry:
1164 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1166 ; CHECK-NEXT: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* [[DST:%.*]], i8 0, i64 1024, i1 false)
1167 ; CHECK-NEXT: br label [[IF_END:%.*]]
1169 ; CHECK-NEXT: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* [[DST]], i8 0, i64 4096, i1 false)
1170 ; CHECK-NEXT: br label [[IF_END]]
1172 ; CHECK-NEXT: ret void
1175 br i1 %flag, label %if.then, label %if.else
1178 call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %dst, i8 0, i64 1024, i1 false)
1182 call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %dst, i8 0, i64 4096, i1 false)
1189 ; Check that simplifycfg doesn't sink and merge inline-asm instructions.
1191 define i32 @test_inline_asm1(i32 %c, i32 %r6) {
1192 ; CHECK-LABEL: @test_inline_asm1(
1193 ; CHECK-NEXT: entry:
1194 ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C:%.*]], 0
1195 ; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
1197 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 [[R6:%.*]], i32 8)
1198 ; CHECK-NEXT: br label [[IF_END:%.*]]
1200 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 [[R6]], i32 6)
1201 ; CHECK-NEXT: br label [[IF_END]]
1203 ; CHECK-NEXT: [[R6_ADDR_0:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ]
1204 ; CHECK-NEXT: ret i32 [[R6_ADDR_0]]
1207 %tobool = icmp eq i32 %c, 0
1208 br i1 %tobool, label %if.else, label %if.then
1211 %0 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8)
1215 %1 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6)
1219 %r6.addr.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ]
1224 declare i32 @call_target()
1226 define void @test_operand_bundles(i1 %cond, i32* %ptr) {
1227 ; CHECK-LABEL: @test_operand_bundles(
1228 ; CHECK-NEXT: entry:
1229 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]]
1231 ; CHECK-NEXT: [[VAL0:%.*]] = call i32 @call_target() [ "deopt"(i32 10) ]
1232 ; CHECK-NEXT: br label [[MERGE:%.*]]
1234 ; CHECK-NEXT: [[VAL1:%.*]] = call i32 @call_target() [ "deopt"(i32 20) ]
1235 ; CHECK-NEXT: br label [[MERGE]]
1237 ; CHECK-NEXT: [[VAL1_SINK:%.*]] = phi i32 [ [[VAL1]], [[RIGHT]] ], [ [[VAL0]], [[LEFT]] ]
1238 ; CHECK-NEXT: store i32 [[VAL1_SINK]], i32* [[PTR:%.*]], align 4
1239 ; CHECK-NEXT: ret void
1242 br i1 %cond, label %left, label %right
1245 %val0 = call i32 @call_target() [ "deopt"(i32 10) ]
1246 store i32 %val0, i32* %ptr
1250 %val1 = call i32 @call_target() [ "deopt"(i32 20) ]
1251 store i32 %val1, i32* %ptr
1259 %TP = type {i32, i32}
1261 define i32 @test_insertvalue(i1 zeroext %flag, %TP %P) {
1262 ; CHECK-LABEL: @test_insertvalue(
1263 ; CHECK-NEXT: entry:
1264 ; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 0, i32 1
1265 ; CHECK-NEXT: [[I2:%.*]] = insertvalue [[TP:%.*]] [[P:%.*]], i32 [[DOT]], 0
1266 ; CHECK-NEXT: ret i32 1
1269 br i1 %flag, label %if.then, label %if.else
1272 %i1 = insertvalue %TP %P, i32 0, 0
1276 %i2 = insertvalue %TP %P, i32 1, 0
1280 %i = phi %TP [%i1, %if.then], [%i2, %if.else]
1286 declare void @baz(i32)
1288 define void @test_sink_void_calls(i32 %x) {
1289 ; CHECK-LABEL: @test_sink_void_calls(
1290 ; CHECK-NEXT: entry:
1291 ; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [
1292 ; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
1293 ; CHECK-NEXT: i32 1, label [[BB1:%.*]]
1294 ; CHECK-NEXT: i32 2, label [[BB2:%.*]]
1295 ; CHECK-NEXT: i32 3, label [[BB3:%.*]]
1296 ; CHECK-NEXT: i32 4, label [[BB4:%.*]]
1299 ; CHECK-NEXT: br label [[RETURN]]
1301 ; CHECK-NEXT: br label [[RETURN]]
1303 ; CHECK-NEXT: br label [[RETURN]]
1305 ; CHECK-NEXT: br label [[RETURN]]
1307 ; CHECK-NEXT: unreachable
1309 ; CHECK-NEXT: [[DOTSINK:%.*]] = phi i32 [ 90, [[BB4]] ], [ 78, [[BB3]] ], [ 56, [[BB2]] ], [ 34, [[BB1]] ], [ 12, [[ENTRY:%.*]] ]
1310 ; CHECK-NEXT: call void @baz(i32 [[DOTSINK]])
1311 ; CHECK-NEXT: ret void
1314 switch i32 %x, label %default [
1322 call void @baz(i32 12)
1325 call void @baz(i32 34)
1328 call void @baz(i32 56)
1331 call void @baz(i32 78)
1334 call void @baz(i32 90)
1341 ; Check that the calls get sunk to the return block.
1342 ; We would previously not sink calls without uses, see PR41259.
1345 define i32 @test_not_sink_lifetime_marker(i1 zeroext %flag, i32 %x) {
1346 ; CHECK-LABEL: @test_not_sink_lifetime_marker(
1347 ; CHECK-NEXT: entry:
1348 ; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4
1349 ; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4
1350 ; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
1352 ; CHECK-NEXT: [[Y_CAST:%.*]] = bitcast i32* [[Y]] to i8*
1353 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[Y_CAST]])
1354 ; CHECK-NEXT: br label [[IF_END:%.*]]
1356 ; CHECK-NEXT: [[Z_CAST:%.*]] = bitcast i32* [[Z]] to i8*
1357 ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[Z_CAST]])
1358 ; CHECK-NEXT: br label [[IF_END]]
1360 ; CHECK-NEXT: ret i32 1
1365 br i1 %flag, label %if.then, label %if.else
1368 %y.cast = bitcast i32* %y to i8*
1369 call void @llvm.lifetime.end.p0i8(i64 4, i8* %y.cast)
1373 %z.cast = bitcast i32* %z to i8*
1374 call void @llvm.lifetime.end.p0i8(i64 4, i8* %z.cast)
1381 define void @direct_caller(i1 %c) {
1382 ; CHECK-LABEL: @direct_caller(
1383 ; CHECK-NEXT: br i1 [[C:%.*]], label [[CALL_FOO:%.*]], label [[CALL_BAR:%.*]]
1385 ; CHECK-NEXT: call void @direct_callee()
1386 ; CHECK-NEXT: br label [[END:%.*]]
1388 ; CHECK-NEXT: call void @direct_callee2()
1389 ; CHECK-NEXT: br label [[END]]
1391 ; CHECK-NEXT: ret void
1393 br i1 %c, label %call_foo, label %call_bar
1396 call void @direct_callee()
1400 call void @direct_callee2()
1407 define void @indirect_caller(i1 %c, i32 %v, void (i32)* %foo, void (i32)* %bar) {
1408 ; CHECK-LABEL: @indirect_caller(
1410 ; CHECK-NEXT: [[FOO_BAR:%.*]] = select i1 [[C:%.*]], void (i32)* [[FOO:%.*]], void (i32)* [[BAR:%.*]]
1411 ; CHECK-NEXT: tail call void [[FOO_BAR]](i32 [[V:%.*]])
1412 ; CHECK-NEXT: ret void
1414 br i1 %c, label %call_foo, label %call_bar
1417 tail call void %foo(i32 %v)
1421 tail call void %bar(i32 %v)
1428 define void @maybe_indirect_caller(void ()* %fun) {
1429 ; CHECK-LABEL: @maybe_indirect_caller(
1430 ; CHECK-NEXT: [[C:%.*]] = icmp eq void ()* [[FUN:%.*]], @direct_callee
1431 ; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE_DIRECT_TARG:%.*]], label [[IF_FALSE_ORIG_INDIRECT:%.*]]
1432 ; CHECK: if.true.direct_targ:
1433 ; CHECK-NEXT: tail call void @direct_callee()
1434 ; CHECK-NEXT: br label [[IF_END_ICP:%.*]]
1435 ; CHECK: if.false.orig_indirect:
1436 ; CHECK-NEXT: tail call void [[FUN]]()
1437 ; CHECK-NEXT: br label [[IF_END_ICP]]
1438 ; CHECK: if.end.icp:
1439 ; CHECK-NEXT: ret void
1441 %c = icmp eq void ()* %fun, @direct_callee
1442 br i1 %c, label %if.true.direct_targ, label %if.false.orig_indirect
1444 if.true.direct_targ:
1445 tail call void @direct_callee()
1446 br label %if.end.icp
1448 if.false.orig_indirect:
1449 tail call void %fun()
1450 br label %if.end.icp
1455 define void @maybe_indirect_caller2(void ()* %fun) {
1456 ; CHECK-LABEL: @maybe_indirect_caller2(
1457 ; CHECK-NEXT: [[C:%.*]] = icmp eq void ()* [[FUN:%.*]], @direct_callee
1458 ; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE_DIRECT_TARG:%.*]], label [[IF_FALSE_ORIG_INDIRECT:%.*]]
1459 ; CHECK: if.false.orig_indirect:
1460 ; CHECK-NEXT: tail call void [[FUN]]()
1461 ; CHECK-NEXT: br label [[IF_END_ICP:%.*]]
1462 ; CHECK: if.true.direct_targ:
1463 ; CHECK-NEXT: tail call void @direct_callee()
1464 ; CHECK-NEXT: br label [[IF_END_ICP]]
1465 ; CHECK: if.end.icp:
1466 ; CHECK-NEXT: ret void
1468 %c = icmp eq void ()* %fun, @direct_callee
1469 br i1 %c, label %if.true.direct_targ, label %if.false.orig_indirect
1471 if.false.orig_indirect:
1472 tail call void %fun()
1473 br label %if.end.icp
1475 if.true.direct_targ:
1476 tail call void @direct_callee()
1477 br label %if.end.icp
1482 declare void @direct_callee()
1483 declare void @direct_callee2()
1484 declare void @direct_callee3()
1486 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
1487 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
1489 define void @creating_too_many_phis(i1 %cond, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) {
1490 ; CHECK-LABEL: @creating_too_many_phis(
1491 ; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]]
1493 ; CHECK-NEXT: [[V0:%.*]] = add i32 [[A:%.*]], [[B:%.*]]
1494 ; CHECK-NEXT: [[V1:%.*]] = add i32 [[V0]], [[C:%.*]]
1495 ; CHECK-NEXT: [[V2:%.*]] = add i32 [[D:%.*]], [[E:%.*]]
1496 ; CHECK-NEXT: [[R3:%.*]] = add i32 [[V1]], [[V2]]
1497 ; CHECK-NEXT: br label [[END:%.*]]
1499 ; CHECK-NEXT: [[V4:%.*]] = add i32 [[A]], [[B]]
1500 ; CHECK-NEXT: [[V5:%.*]] = add i32 [[V4]], [[C]]
1501 ; CHECK-NEXT: [[V6:%.*]] = add i32 [[G:%.*]], [[H:%.*]]
1502 ; CHECK-NEXT: [[R7:%.*]] = add i32 [[V5]], [[V6]]
1503 ; CHECK-NEXT: br label [[END]]
1505 ; CHECK-NEXT: [[R7_SINK:%.*]] = phi i32 [ [[R7]], [[BB1]] ], [ [[R3]], [[BB0]] ]
1506 ; CHECK-NEXT: call void @use32(i32 [[R7_SINK]])
1507 ; CHECK-NEXT: ret void
1509 br i1 %cond, label %bb0, label %bb1
1512 %v0 = add i32 %a, %b
1513 %v1 = add i32 %v0, %c
1514 %v2 = add i32 %d, %e
1515 %r3 = add i32 %v1, %v2
1516 call void @use32(i32 %r3)
1520 %v4 = add i32 %a, %b
1521 %v5 = add i32 %v4, %c
1522 %v6 = add i32 %g, %h
1523 %r7 = add i32 %v5, %v6
1524 call void @use32(i32 %r7)
1530 declare void @use32(i32)
1532 define void @multiple_cond_preds(i1 %c0, i1 %c1, i1 %c2) {
1533 ; CHECK-LABEL: @multiple_cond_preds(
1534 ; CHECK-NEXT: dispatch0:
1535 ; CHECK-NEXT: br i1 [[C0:%.*]], label [[DISPATCH1:%.*]], label [[DISPATCH2:%.*]]
1537 ; CHECK-NEXT: call void @direct_callee2()
1538 ; CHECK-NEXT: br i1 [[C1:%.*]], label [[END_SINK_SPLIT:%.*]], label [[END:%.*]]
1540 ; CHECK-NEXT: call void @direct_callee3()
1541 ; CHECK-NEXT: br i1 [[C2:%.*]], label [[END_SINK_SPLIT]], label [[END]]
1542 ; CHECK: end.sink.split:
1543 ; CHECK-NEXT: call void @direct_callee()
1544 ; CHECK-NEXT: br label [[END]]
1546 ; CHECK-NEXT: ret void
1549 br i1 %c0, label %dispatch1, label %dispatch2
1552 call void @direct_callee2()
1553 br i1 %c1, label %uncond_pred0, label %end
1556 call void @direct_callee3()
1557 br i1 %c2, label %uncond_pred1, label %end
1560 call void @direct_callee()
1564 call void @direct_callee()