Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / SimpleLoopUnswitch / implicit-null-checks.ll
blob94ad65738804a45781651749f6ecff1c8b529ad0
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes='simple-loop-unswitch<nontrivial>' -S < %s | FileCheck %s
3 ; RUN: opt -passes='loop(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s
5 declare void @may_exit()
6 declare void @throw_npe()
8 ; It is illegal to preserve make_implicit notion of the condition being
9 ; unswitched because we may exit loop before we reach the condition, so
10 ; there is no guarantee that following implicit branch always means getting
11 ; to throw_npe block.
12 define i32 @test_should_drop_make_implicit(ptr %p1, ptr %p2) {
13 ; CHECK-LABEL: @test_should_drop_make_implicit(
14 ; CHECK-NEXT:  entry:
15 ; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[P2:%.*]], null
16 ; CHECK-NEXT:    [[NULL_CHECK_FR:%.*]] = freeze i1 [[NULL_CHECK]]
17 ; CHECK-NEXT:    br i1 [[NULL_CHECK_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
18 ; CHECK:       entry.split.us:
19 ; CHECK-NEXT:    br label [[LOOP_US:%.*]]
20 ; CHECK:       loop.us:
21 ; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ]
22 ; CHECK-NEXT:    [[X_US:%.*]] = load i32, ptr [[P1:%.*]], align 4
23 ; CHECK-NEXT:    [[SIDE_EXIT_COND_US:%.*]] = icmp eq i32 [[X_US]], 0
24 ; CHECK-NEXT:    br i1 [[SIDE_EXIT_COND_US]], label [[SIDE_EXIT_SPLIT_US:%.*]], label [[NULL_CHECK_BLOCK_US:%.*]]
25 ; CHECK:       null_check_block.us:
26 ; CHECK-NEXT:    br label [[THROW_NPE_SPLIT_US:%.*]]
27 ; CHECK:       side_exit.split.us:
28 ; CHECK-NEXT:    br label [[SIDE_EXIT:%.*]]
29 ; CHECK:       throw_npe.split.us:
30 ; CHECK-NEXT:    br label [[THROW_NPE:%.*]]
31 ; CHECK:       entry.split:
32 ; CHECK-NEXT:    br label [[LOOP:%.*]]
33 ; CHECK:       loop:
34 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
35 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P1]], align 4
36 ; CHECK-NEXT:    [[SIDE_EXIT_COND:%.*]] = icmp eq i32 [[X]], 0
37 ; CHECK-NEXT:    br i1 [[SIDE_EXIT_COND]], label [[SIDE_EXIT_SPLIT:%.*]], label [[NULL_CHECK_BLOCK:%.*]]
38 ; CHECK:       null_check_block:
39 ; CHECK-NEXT:    br label [[BACKEDGE]]
40 ; CHECK:       backedge:
41 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
42 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 10000
43 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
44 ; CHECK:       side_exit.split:
45 ; CHECK-NEXT:    br label [[SIDE_EXIT]]
46 ; CHECK:       side_exit:
47 ; CHECK-NEXT:    ret i32 0
48 ; CHECK:       throw_npe:
49 ; CHECK-NEXT:    call void @throw_npe()
50 ; CHECK-NEXT:    unreachable
51 ; CHECK:       exit:
52 ; CHECK-NEXT:    [[X_LCSSA2:%.*]] = phi i32 [ [[X]], [[BACKEDGE]] ]
53 ; CHECK-NEXT:    ret i32 [[X_LCSSA2]]
55 entry:
56   %null_check = icmp eq ptr %p2, null
57   br label %loop
58 loop:
59   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
60   %x = load i32, ptr %p1
61   %side_exit_cond = icmp eq i32 %x, 0
62   br i1 %side_exit_cond, label %side_exit, label %null_check_block
64 null_check_block:
65   br i1 %null_check, label %throw_npe, label %backedge, !make.implicit !0
67 backedge:
68   %iv.next = add i32 %iv,1
69   %loop_cond = icmp slt i32 %iv.next, 10000
70   br i1 %loop_cond, label %loop, label %exit
72 side_exit:
73   ret i32 0
75 throw_npe:
76   call void @throw_npe()
77   unreachable
79 exit:
80   ret i32 %x
83 ; Here make.implicit notion may be preserved because we always get to throw_npe
84 ; after following true branch. This is a trivial unswitch.
85 define i32 @test_may_keep_make_implicit_trivial(ptr %p1, ptr %p2) {
86 ; CHECK-LABEL: @test_may_keep_make_implicit_trivial(
87 ; CHECK-NEXT:  entry:
88 ; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[P2:%.*]], null
89 ; CHECK-NEXT:    br i1 [[NULL_CHECK]], label [[THROW_NPE:%.*]], label [[ENTRY_SPLIT:%.*]], !make.implicit !0
90 ; CHECK:       entry.split:
91 ; CHECK-NEXT:    br label [[LOOP:%.*]]
92 ; CHECK:       loop:
93 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
94 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P1:%.*]], align 4
95 ; CHECK-NEXT:    [[SIDE_EXIT_COND:%.*]] = icmp eq i32 [[X]], 0
96 ; CHECK-NEXT:    br label [[SIDE_EXIT_BLOCK:%.*]]
97 ; CHECK:       side_exit_block:
98 ; CHECK-NEXT:    br i1 [[SIDE_EXIT_COND]], label [[SIDE_EXIT:%.*]], label [[BACKEDGE]]
99 ; CHECK:       backedge:
100 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
101 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 10000
102 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
103 ; CHECK:       side_exit:
104 ; CHECK-NEXT:    ret i32 0
105 ; CHECK:       throw_npe:
106 ; CHECK-NEXT:    call void @throw_npe()
107 ; CHECK-NEXT:    unreachable
108 ; CHECK:       exit:
109 ; CHECK-NEXT:    [[X_LCSSA2:%.*]] = phi i32 [ [[X]], [[BACKEDGE]] ]
110 ; CHECK-NEXT:    ret i32 [[X_LCSSA2]]
112 entry:
113   %null_check = icmp eq ptr %p2, null
114   br label %loop
115 loop:
116   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
117   %x = load i32, ptr %p1
118   %side_exit_cond = icmp eq i32 %x, 0
119   br i1 %null_check, label %throw_npe, label %side_exit_block, !make.implicit !0
121 side_exit_block:
122   br i1 %side_exit_cond, label %side_exit, label %backedge
124 backedge:
125   %iv.next = add i32 %iv,1
126   %loop_cond = icmp slt i32 %iv.next, 10000
127   br i1 %loop_cond, label %loop, label %exit
129 side_exit:
130   ret i32 0
132 throw_npe:
133   call void @throw_npe()
134   unreachable
136 exit:
137   ret i32 %x
140 define i32 @test_may_keep_make_implicit_non_trivial(ptr %p1, ptr %p2) {
141 ; CHECK-LABEL: @test_may_keep_make_implicit_non_trivial(
142 ; CHECK-NEXT:  entry:
143 ; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[P2:%.*]], null
144 ; CHECK-NEXT:    br i1 [[NULL_CHECK]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]], !make.implicit !0
145 ; CHECK:       entry.split.us:
146 ; CHECK-NEXT:    br label [[LOOP_US:%.*]]
147 ; CHECK:       loop.us:
148 ; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ]
149 ; CHECK-NEXT:    [[X_US:%.*]] = load i32, ptr [[P1:%.*]], align 4
150 ; CHECK-NEXT:    [[INNER_BLOCK_COND_US:%.*]] = icmp eq i32 [[X_US]], 0
151 ; CHECK-NEXT:    br i1 [[INNER_BLOCK_COND_US]], label [[INNER_BLOCK_US:%.*]], label [[NULL_CHECK_BLOCK_US:%.*]]
152 ; CHECK:       inner_block.us:
153 ; CHECK-NEXT:    br label [[NULL_CHECK_BLOCK_US]]
154 ; CHECK:       null_check_block.us:
155 ; CHECK-NEXT:    br label [[THROW_NPE_SPLIT_US:%.*]]
156 ; CHECK:       throw_npe.split.us:
157 ; CHECK-NEXT:    br label [[THROW_NPE:%.*]]
158 ; CHECK:       entry.split:
159 ; CHECK-NEXT:    br label [[LOOP:%.*]]
160 ; CHECK:       loop:
161 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
162 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P1]], align 4
163 ; CHECK-NEXT:    [[INNER_BLOCK_COND:%.*]] = icmp eq i32 [[X]], 0
164 ; CHECK-NEXT:    br i1 [[INNER_BLOCK_COND]], label [[INNER_BLOCK:%.*]], label [[NULL_CHECK_BLOCK:%.*]]
165 ; CHECK:       inner_block:
166 ; CHECK-NEXT:    br label [[NULL_CHECK_BLOCK]]
167 ; CHECK:       null_check_block:
168 ; CHECK-NEXT:    br label [[BACKEDGE]]
169 ; CHECK:       backedge:
170 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
171 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 10000
172 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
173 ; CHECK:       throw_npe:
174 ; CHECK-NEXT:    call void @throw_npe()
175 ; CHECK-NEXT:    unreachable
176 ; CHECK:       exit:
177 ; CHECK-NEXT:    [[X_LCSSA1:%.*]] = phi i32 [ [[X]], [[BACKEDGE]] ]
178 ; CHECK-NEXT:    ret i32 [[X_LCSSA1]]
180 entry:
181   %null_check = icmp eq ptr %p2, null
182   br label %loop
183 loop:
184   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
185   %x = load i32, ptr %p1
186   %inner_block_cond = icmp eq i32 %x, 0
187   br i1 %inner_block_cond, label %inner_block, label %null_check_block
189 inner_block:
190   br label %null_check_block
192 null_check_block:
193   br i1 %null_check, label %throw_npe, label %backedge, !make.implicit !0
195 backedge:
196   %iv.next = add i32 %iv,1
197   %loop_cond = icmp slt i32 %iv.next, 10000
198   br i1 %loop_cond, label %loop, label %exit
200 throw_npe:
201   call void @throw_npe()
202   unreachable
204 exit:
205   ret i32 %x
208 ; Here make.implicit notion should be dropped because of exiting call.
209 define i32 @test_should_drop_make_implicit_exiting_call(ptr %p1, ptr %p2) {
210 ; CHECK-LABEL: @test_should_drop_make_implicit_exiting_call(
211 ; CHECK-NEXT:  entry:
212 ; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[P2:%.*]], null
213 ; CHECK-NEXT:    [[NULL_CHECK_FR:%.*]] = freeze i1 [[NULL_CHECK]]
214 ; CHECK-NEXT:    br i1 [[NULL_CHECK_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
215 ; CHECK:       entry.split.us:
216 ; CHECK-NEXT:    br label [[LOOP_US:%.*]]
217 ; CHECK:       loop.us:
218 ; CHECK-NEXT:    [[IV_US:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT_US]] ]
219 ; CHECK-NEXT:    call void @may_exit()
220 ; CHECK-NEXT:    [[X_US:%.*]] = load i32, ptr [[P1:%.*]], align 4
221 ; CHECK-NEXT:    [[SIDE_EXIT_COND_US:%.*]] = icmp eq i32 [[X_US]], 0
222 ; CHECK-NEXT:    br label [[THROW_NPE_SPLIT_US:%.*]]
223 ; CHECK:       throw_npe.split.us:
224 ; CHECK-NEXT:    br label [[THROW_NPE:%.*]]
225 ; CHECK:       entry.split:
226 ; CHECK-NEXT:    br label [[LOOP:%.*]]
227 ; CHECK:       loop:
228 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
229 ; CHECK-NEXT:    call void @may_exit()
230 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P1]], align 4
231 ; CHECK-NEXT:    [[SIDE_EXIT_COND:%.*]] = icmp eq i32 [[X]], 0
232 ; CHECK-NEXT:    br label [[BACKEDGE]]
233 ; CHECK:       backedge:
234 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
235 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 10000
236 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
237 ; CHECK:       throw_npe:
238 ; CHECK-NEXT:    call void @throw_npe()
239 ; CHECK-NEXT:    unreachable
240 ; CHECK:       exit:
241 ; CHECK-NEXT:    [[X_LCSSA1:%.*]] = phi i32 [ [[X]], [[BACKEDGE]] ]
242 ; CHECK-NEXT:    ret i32 [[X_LCSSA1]]
244 entry:
245   %null_check = icmp eq ptr %p2, null
246   br label %loop
247 loop:
248   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
249   call void @may_exit()
250   %x = load i32, ptr %p1
251   %side_exit_cond = icmp eq i32 %x, 0
252   br i1 %null_check, label %throw_npe, label %backedge, !make.implicit !0
254 backedge:
255   %iv.next = add i32 %iv,1
256   %loop_cond = icmp slt i32 %iv.next, 10000
257   br i1 %loop_cond, label %loop, label %exit
259 throw_npe:
260   call void @throw_npe()
261   unreachable
263 exit:
264   ret i32 %x
267 ; Here exiting call goes after the null check, so make.implicit may be preserved.
268 define i32 @test_may_keep_make_implicit_exiting_call(ptr %p1, ptr %p2) {
269 ; CHECK-LABEL: @test_may_keep_make_implicit_exiting_call(
270 ; CHECK-NEXT:  entry:
271 ; CHECK-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[P2:%.*]], null
272 ; CHECK-NEXT:    br i1 [[NULL_CHECK]], label [[THROW_NPE:%.*]], label [[ENTRY_SPLIT:%.*]], !make.implicit !0
273 ; CHECK:       entry.split:
274 ; CHECK-NEXT:    br label [[LOOP:%.*]]
275 ; CHECK:       loop:
276 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY_SPLIT]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
277 ; CHECK-NEXT:    [[X:%.*]] = load i32, ptr [[P1:%.*]], align 4
278 ; CHECK-NEXT:    [[SIDE_EXIT_COND:%.*]] = icmp eq i32 [[X]], 0
279 ; CHECK-NEXT:    br label [[BACKEDGE]]
280 ; CHECK:       backedge:
281 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
282 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 10000
283 ; CHECK-NEXT:    call void @may_exit()
284 ; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
285 ; CHECK:       throw_npe:
286 ; CHECK-NEXT:    call void @throw_npe()
287 ; CHECK-NEXT:    unreachable
288 ; CHECK:       exit:
289 ; CHECK-NEXT:    [[X_LCSSA1:%.*]] = phi i32 [ [[X]], [[BACKEDGE]] ]
290 ; CHECK-NEXT:    ret i32 [[X_LCSSA1]]
292 entry:
293   %null_check = icmp eq ptr %p2, null
294   br label %loop
295 loop:
296   %iv = phi i32 [0, %entry], [%iv.next, %backedge]
297   %x = load i32, ptr %p1
298   %side_exit_cond = icmp eq i32 %x, 0
299   br i1 %null_check, label %throw_npe, label %backedge, !make.implicit !0
301 backedge:
302   %iv.next = add i32 %iv,1
303   %loop_cond = icmp slt i32 %iv.next, 10000
304   call void @may_exit()
305   br i1 %loop_cond, label %loop, label %exit
307 throw_npe:
308   call void @throw_npe()
309   unreachable
311 exit:
312   ret i32 %x
315 !0 = !{}