xref: /llvm-project/llvm/test/Transforms/SimplifyCFG/assume.ll (revision bb3763e497d94b061aa9d625fc542d16da9cae6d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
3
4define void @assume_false_to_unreachable1() {
5; CHECK-LABEL: @assume_false_to_unreachable1(
6; CHECK-NEXT:    unreachable
7;
8  call void @llvm.assume(i1 0)
9  ret void
10
11}
12
13define void @assume_undef_to_unreachable() {
14; CHECK-LABEL: @assume_undef_to_unreachable(
15; CHECK-NEXT:    unreachable
16;
17  call void @llvm.assume(i1 undef)
18  ret void
19
20}
21
22define i32 @speculate_block_with_assume_basic(i1 %c, i32 %x) {
23; CHECK-LABEL: @speculate_block_with_assume_basic(
24; CHECK-NEXT:  entry:
25; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 1, i32 0
26; CHECK-NEXT:    ret i32 [[SPEC_SELECT]]
27;
28entry:
29  br i1 %c, label %if, label %join
30
31if:
32  %cmp = icmp ne i32 %x, 0
33  call void @llvm.assume(i1 %cmp)
34  br label %join
35
36join:
37  %phi = phi i32 [ 0, %entry ], [ 1, %if ]
38  ret i32 %phi
39}
40
41define i32 @speculate_block_with_assume_extra_instr(i1 %c, i32 %x) {
42; CHECK-LABEL: @speculate_block_with_assume_extra_instr(
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X:%.*]], 1
45; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 [[ADD]], i32 0
46; CHECK-NEXT:    ret i32 [[SPEC_SELECT]]
47;
48entry:
49  br i1 %c, label %if, label %join
50
51if:
52  %add = add i32 %x, 1
53  %cmp = icmp ne i32 %add, 0
54  call void @llvm.assume(i1 %cmp)
55  br label %join
56
57join:
58  %phi = phi i32 [ 0, %entry ], [ %add, %if ]
59  ret i32 %phi
60}
61
62; We only allow speculating one instruction. Here %add and %add2 are used by
63; the assume, but not ephemeral, because they are also used by %phi.
64define i32 @speculate_block_with_assume_extra_instrs_too_many(i1 %c, i32 %x) {
65; CHECK-LABEL: @speculate_block_with_assume_extra_instrs_too_many(
66; CHECK-NEXT:  entry:
67; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[JOIN:%.*]]
68; CHECK:       if:
69; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X:%.*]], 1
70; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD]], 1
71; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[ADD2]], 0
72; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
73; CHECK-NEXT:    br label [[JOIN]]
74; CHECK:       join:
75; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD2]], [[IF]] ]
76; CHECK-NEXT:    ret i32 [[PHI]]
77;
78entry:
79  br i1 %c, label %if, label %join
80
81if:
82  %add = add i32 %x, 1
83  %add2 = add i32 %add, 1
84  %cmp = icmp ne i32 %add2, 0
85  call void @llvm.assume(i1 %cmp)
86  br label %join
87
88join:
89  %phi = phi i32 [ 0, %entry ], [ %add2, %if ]
90  ret i32 %phi
91}
92
93define i32 @speculate_block_with_assume_extra_instrs_okay(i1 %c, i32 %x) {
94; CHECK-LABEL: @speculate_block_with_assume_extra_instrs_okay(
95; CHECK-NEXT:  entry:
96; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[X:%.*]], 1
97; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 [[ADD]], i32 0
98; CHECK-NEXT:    ret i32 [[SPEC_SELECT]]
99;
100entry:
101  br i1 %c, label %if, label %join
102
103if:
104  %add = add i32 %x, 1
105  %add2 = add i32 %add, 1
106  %cmp = icmp ne i32 %add2, 0
107  call void @llvm.assume(i1 %cmp)
108  br label %join
109
110join:
111  %phi = phi i32 [ 0, %entry ], [ %add, %if ]
112  ret i32 %phi
113}
114
115define i32 @speculate_block_with_assume_operand_bundle(i1 %c, ptr %p) {
116; CHECK-LABEL: @speculate_block_with_assume_operand_bundle(
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i32 1, i32 0
119; CHECK-NEXT:    ret i32 [[SPEC_SELECT]]
120;
121entry:
122  br i1 %c, label %if, label %join
123
124if:
125  call void @llvm.assume(i1 true) ["nonnull"(ptr %p)]
126  br label %join
127
128join:
129  %phi = phi i32 [ 0, %entry ], [ 1, %if ]
130  ret i32 %phi
131}
132
133define void @empty_block_with_assume(i1 %c, i32 %x) {
134; CHECK-LABEL: @empty_block_with_assume(
135; CHECK-NEXT:  entry:
136; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
137; CHECK:       if:
138; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X:%.*]], 0
139; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
140; CHECK-NEXT:    br label [[JOIN:%.*]]
141; CHECK:       else:
142; CHECK-NEXT:    call void @dummy()
143; CHECK-NEXT:    br label [[JOIN]]
144; CHECK:       join:
145; CHECK-NEXT:    ret void
146;
147entry:
148  br i1 %c, label %if, label %else
149
150if:
151  %cmp = icmp ne i32 %x, 0
152  call void @llvm.assume(i1 %cmp)
153  br label %join
154
155else:
156  call void @dummy()
157  br label %join
158
159join:
160  ret void
161}
162
163define void @not_empty_block_with_assume(i1 %c) {
164; CHECK-LABEL: @not_empty_block_with_assume(
165; CHECK-NEXT:  entry:
166; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
167; CHECK:       if:
168; CHECK-NEXT:    [[X:%.*]] = call i32 @may_have_side_effect()
169; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i32 [[X]], 0
170; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
171; CHECK-NEXT:    br label [[JOIN:%.*]]
172; CHECK:       else:
173; CHECK-NEXT:    call void @dummy()
174; CHECK-NEXT:    br label [[JOIN]]
175; CHECK:       join:
176; CHECK-NEXT:    ret void
177;
178entry:
179  br i1 %c, label %if, label %else
180
181if:
182  %x = call i32 @may_have_side_effect()
183  %cmp = icmp ne i32 %x, 0
184  call void @llvm.assume(i1 %cmp)
185  br label %join
186
187else:
188  call void @dummy()
189  br label %join
190
191join:
192  ret void
193}
194
195declare void @dummy()
196declare i32 @may_have_side_effect()
197declare void @llvm.assume(i1) nounwind
198
199