1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -simplifycfg < %s | FileCheck %s
3
4declare void @llvm.experimental.guard(i1, ...)
5
6define i32 @f_0(i1 %c) {
7; CHECK-LABEL: @f_0(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
10; CHECK-NEXT:    unreachable
11;
12entry:
13  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
14  ret i32 10
15}
16
17define i32 @f_1(i1 %c) {
18; Demonstrate that we (intentionally) do not simplify a guard on undef
19; CHECK-LABEL: @f_1(
20; CHECK-NEXT:  entry:
21; CHECK-NEXT:    br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
22; CHECK:       true:
23; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ]
24; CHECK-NEXT:    ret i32 10
25; CHECK:       false:
26; CHECK-NEXT:    ret i32 20
27;
28
29entry:
30  br i1 %c, label %true, label %false
31
32true:
33  call void(i1, ...) @llvm.experimental.guard(i1 undef) [ "deopt"() ]
34  ret i32 10
35
36false:
37  ret i32 20
38}
39
40define i32 @f_2(i1 %c, i32* %buf) {
41; CHECK-LABEL: @f_2(
42; CHECK-NEXT:  entry:
43; CHECK-NEXT:    br i1 [[C:%.*]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]]
44; CHECK:       guard_block:
45; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
46; CHECK-NEXT:    unreachable
47; CHECK:       merge_block:
48; CHECK-NEXT:    ret i32 50
49;
50entry:
51  br i1 %c, label %guard_block, label %merge_block
52
53guard_block:
54  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
55  %val = load i32, i32* %buf
56  br label %merge_block
57
58merge_block:
59  %to.return = phi i32 [ %val, %guard_block ], [ 50, %entry ]
60  ret i32 %to.return
61
62}
63
64define i32 @f_3(i1* %c, i32* %buf) {
65; CHECK-LABEL: @f_3(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    [[C0:%.*]] = load volatile i1, i1* [[C:%.*]]
68; CHECK-NEXT:    br i1 [[C0]], label [[GUARD_BLOCK:%.*]], label [[MERGE_BLOCK:%.*]]
69; CHECK:       guard_block:
70; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
71; CHECK-NEXT:    unreachable
72; CHECK:       merge_block:
73; CHECK-NEXT:    [[C1:%.*]] = load volatile i1, i1* [[C]]
74; CHECK-NEXT:    [[DOT:%.*]] = select i1 [[C1]], i32 50, i32 100
75; CHECK-NEXT:    ret i32 [[DOT]]
76;
77entry:
78  %c0 = load volatile i1, i1* %c
79  br i1 %c0, label %guard_block, label %merge_block
80
81guard_block:
82  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
83  %val = load i32, i32* %buf
84  %c2 = load volatile i1, i1* %c
85  br i1 %c2, label %left, label %right
86
87merge_block:
88  %c1 = load volatile i1, i1* %c
89  br i1 %c1, label %left, label %right
90
91left:
92  %val.left = phi i32 [ %val, %guard_block ], [ 50, %merge_block ]
93  ret i32 %val.left
94
95right:
96  %val.right = phi i32 [ %val, %guard_block ], [ 100, %merge_block ]
97  ret i32 %val.right
98
99
100}
101