xref: /llvm-project/llvm/test/Transforms/LoopVectorize/early_exit_legality.ll (revision b0697dc1de1f6fbc0f3c192e5420203c8afe3f99)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; REQUIRES: asserts
3; RUN: opt -S < %s -p loop-vectorize -debug-only=loop-vectorize -enable-early-exit-vectorization -force-vector-width=4 -disable-output 2>&1 | FileCheck %s
4
5declare void @init_mem(ptr, i64);
6
7; == SOME LEGAL EXAMPLES ==
8
9; The form of the induction variables requires SCEV predicates.
10define i32 @diff_exit_block_needs_scev_check(i32 %end) {
11; CHECK-LABEL: LV: Checking a loop in 'diff_exit_block_needs_scev_check'
12; CHECK:       Found an early exit loop with symbolic max backedge taken count: (-1 + (1 umax (zext i10 (trunc i32 %end to i10) to i32)))<nsw>
13; CHECK-NEXT:  LV: We can vectorize this loop!
14; CHECK-NOT:   LV: Not vectorizing:
15entry:
16  %p1 = alloca [1024 x i32]
17  %p2 = alloca [1024 x i32]
18  call void @init_mem(ptr %p1, i64 1024)
19  call void @init_mem(ptr %p2, i64 1024)
20  %end.clamped = and i32 %end, 1023
21  br label %for.body
22
23for.body:
24  %ind = phi i8 [ %ind.next, %for.inc ], [ 0, %entry ]
25  %gep.ind = phi i64 [ %gep.ind.next, %for.inc ], [ 0, %entry ]
26  %arrayidx1 = getelementptr inbounds i32, ptr %p1, i64 %gep.ind
27  %0 = load i32, ptr %arrayidx1, align 4
28  %arrayidx2 = getelementptr inbounds i32, ptr %p2, i64 %gep.ind
29  %1 = load i32, ptr %arrayidx2, align 4
30  %cmp.early = icmp eq i32 %0, %1
31  br i1 %cmp.early, label %found, label %for.inc
32
33for.inc:
34  %ind.next = add i8 %ind, 1
35  %conv = zext i8 %ind.next to i32
36  %gep.ind.next = add i64 %gep.ind, 1
37  %cmp = icmp ult i32 %conv, %end.clamped
38  br i1 %cmp, label %for.body, label %exit
39
40found:
41  ret i32 1
42
43exit:
44  ret i32 0
45}
46
47
48define i64 @same_exit_block_pre_inc_use1() {
49; CHECK-LABEL: LV: Checking a loop in 'same_exit_block_pre_inc_use1'
50; CHECK:       LV: Found an early exit loop with symbolic max backedge taken count: 63
51; CHECK-NEXT:  LV: We can vectorize this loop!
52; CHECK:  LV: Not vectorizing: Some exit values in loop with uncountable exit not supported yet.
53entry:
54  %p1 = alloca [1024 x i8]
55  %p2 = alloca [1024 x i8]
56  call void @init_mem(ptr %p1, i64 1024)
57  call void @init_mem(ptr %p2, i64 1024)
58  br label %loop
59
60loop:
61  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
62  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
63  %ld1 = load i8, ptr %arrayidx, align 1
64  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
65  %ld2 = load i8, ptr %arrayidx1, align 1
66  %cmp3 = icmp eq i8 %ld1, %ld2
67  br i1 %cmp3, label %loop.inc, label %loop.end
68
69loop.inc:
70  %index.next = add i64 %index, 1
71  %exitcond = icmp ne i64 %index.next, 67
72  br i1 %exitcond, label %loop, label %loop.end
73
74loop.end:
75  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
76  ret i64 %retval
77}
78
79
80define i64 @loop_contains_safe_call() {
81; CHECK-LABEL: LV: Checking a loop in 'loop_contains_safe_call'
82; CHECK:       LV: Found an early exit loop with symbolic max backedge taken count: 63
83; CHECK-NEXT:  LV: We can vectorize this loop!
84entry:
85  %p1 = alloca [1024 x i8]
86  %p2 = alloca [1024 x i8]
87  call void @init_mem(ptr %p1, i64 1024)
88  call void @init_mem(ptr %p2, i64 1024)
89  br label %loop
90
91loop:
92  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
93  %arrayidx = getelementptr inbounds float, ptr %p1, i64 %index
94  %ld1 = load float, ptr %arrayidx, align 1
95  %sqrt = tail call fast float @llvm.sqrt.f32(float %ld1)
96  %cmp = fcmp fast ult float %sqrt, 3.0e+00
97  br i1 %cmp, label %loop.inc, label %loop.end
98
99loop.inc:
100  %index.next = add i64 %index, 1
101  %exitcond = icmp ne i64 %index.next, 67
102  br i1 %exitcond, label %loop, label %loop.end
103
104loop.end:
105  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
106  ret i64 %retval
107}
108
109
110define i64 @loop_contains_safe_div() {
111; CHECK-LABEL: LV: Checking a loop in 'loop_contains_safe_div'
112; CHECK:       LV: Found an early exit loop with symbolic max backedge taken count: 63
113; CHECK-NEXT:  LV: We can vectorize this loop!
114entry:
115  %p1 = alloca [1024 x i8]
116  %p2 = alloca [1024 x i8]
117  call void @init_mem(ptr %p1, i64 1024)
118  call void @init_mem(ptr %p2, i64 1024)
119  br label %loop
120
121loop:
122  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
123  %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index
124  %ld1 = load i32, ptr %arrayidx, align 1
125  %div = udiv i32 %ld1, 20000
126  %cmp = icmp eq i32 %div, 1
127  br i1 %cmp, label %loop.inc, label %loop.end
128
129loop.inc:
130  %index.next = add i64 %index, 1
131  %exitcond = icmp ne i64 %index.next, 67
132  br i1 %exitcond, label %loop, label %loop.end
133
134loop.end:
135  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
136  ret i64 %retval
137}
138
139
140define i64 @loop_contains_load_after_early_exit(ptr dereferenceable(1024) align(8) %p2) {
141; CHECK-LABEL: LV: Checking a loop in 'loop_contains_load_after_early_exit'
142; CHECK:       LV: Found an early exit loop with symbolic max backedge taken count: 63
143; CHECK-NEXT:  LV: We can vectorize this loop!
144; CHECK:       LV: Not vectorizing: Some exit values in loop with uncountable exit not supported yet.
145entry:
146  %p1 = alloca [1024 x i8]
147  call void @init_mem(ptr %p1, i64 1024)
148  br label %loop
149
150loop:
151  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
152  %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index
153  %ld1 = load i32, ptr %arrayidx, align 1
154  %cmp = icmp eq i32 %ld1, 1
155  br i1 %cmp, label %loop.inc, label %loop.end
156
157loop.inc:
158  %arrayidx2 = getelementptr inbounds i64, ptr %p2, i64 %index
159  %ld2 = load i64, ptr %arrayidx2, align 8
160  %index.next = add i64 %index, 1
161  %exitcond = icmp ne i64 %index.next, 67
162  br i1 %exitcond, label %loop, label %loop.end
163
164loop.end:
165  %retval = phi i64 [ %index, %loop ], [ %ld2, %loop.inc ]
166  ret i64 %retval
167}
168
169
170define i64 @one_uncountable_two_countable_same_exit_phi_of_consts() {
171; CHECK-LABEL: LV: Checking a loop in 'one_uncountable_two_countable_same_exit_phi_of_consts'
172; CHECK:       LV: Found an early exit loop with symbolic max backedge taken count: 61
173; CHECK-NEXT:  LV: We can vectorize this loop!
174; CHECK-NEXT:  LV: Not vectorizing: Auto-vectorization of early exit loops requiring a scalar epilogue is unsupported.
175entry:
176  %p1 = alloca [1024 x i8]
177  %p2 = alloca [1024 x i8]
178  call void @init_mem(ptr %p1, i64 1024)
179  call void @init_mem(ptr %p2, i64 1024)
180  br label %loop
181
182loop:
183  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
184  %cmp1 = icmp ne i64 %index, 64
185  br i1 %cmp1, label %search, label %loop.end
186
187search:
188  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
189  %ld1 = load i8, ptr %arrayidx, align 1
190  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
191  %ld2 = load i8, ptr %arrayidx1, align 1
192  %cmp3 = icmp eq i8 %ld1, %ld2
193  br i1 %cmp3, label %loop.end, label %loop.inc
194
195loop.inc:
196  %index.next = add i64 %index, 1
197  %exitcond = icmp ne i64 %index.next, 128
198  br i1 %exitcond, label %loop, label %loop.end
199
200loop.end:
201  %retval = phi i64 [ 0, %loop ], [ 1, %search ], [ 0, %loop.inc ]
202  ret i64 %retval
203}
204
205
206; == SOME ILLEGAL EXAMPLES ==
207
208
209define i64 @same_exit_block_pre_inc_use1_too_small_allocas() {
210; CHECK-LABEL: LV: Checking a loop in 'same_exit_block_pre_inc_use1_too_small_allocas'
211; CHECK:       LV: Not vectorizing: Loop may fault.
212entry:
213  %p1 = alloca [42 x i8]
214  %p2 = alloca [42 x i8]
215  call void @init_mem(ptr %p1, i64 1024)
216  call void @init_mem(ptr %p2, i64 1024)
217  br label %loop
218
219loop:
220  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
221  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
222  %ld1 = load i8, ptr %arrayidx, align 1
223  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
224  %ld2 = load i8, ptr %arrayidx1, align 1
225  %cmp3 = icmp eq i8 %ld1, %ld2
226  br i1 %cmp3, label %loop.inc, label %loop.end
227
228loop.inc:
229  %index.next = add i64 %index, 1
230  %exitcond = icmp ne i64 %index.next, 67
231  br i1 %exitcond, label %loop, label %loop.end
232
233loop.end:
234  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
235  ret i64 %retval
236}
237
238
239define i64 @same_exit_block_pre_inc_use1_too_small_deref_ptrs(ptr dereferenceable(42) %p1, ptr dereferenceable(42) %p2) {
240; CHECK-LABEL: LV: Checking a loop in 'same_exit_block_pre_inc_use1_too_small_deref_ptrs'
241; CHECK:       LV: Not vectorizing: Loop may fault.
242entry:
243  br label %loop
244
245loop:
246  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
247  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
248  %ld1 = load i8, ptr %arrayidx, align 1
249  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
250  %ld2 = load i8, ptr %arrayidx1, align 1
251  %cmp3 = icmp eq i8 %ld1, %ld2
252  br i1 %cmp3, label %loop.inc, label %loop.end
253
254loop.inc:
255  %index.next = add i64 %index, 1
256  %exitcond = icmp ne i64 %index.next, 67
257  br i1 %exitcond, label %loop, label %loop.end
258
259loop.end:
260  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
261  ret i64 %retval
262}
263
264
265define i64 @same_exit_block_pre_inc_use1_unknown_ptrs(ptr %p1, ptr %p2) {
266; CHECK-LABEL: LV: Checking a loop in 'same_exit_block_pre_inc_use1_unknown_ptrs'
267; CHECK:       LV: Not vectorizing: Loop may fault.
268entry:
269  br label %loop
270
271loop:
272  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
273  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
274  %ld1 = load i8, ptr %arrayidx, align 1
275  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
276  %ld2 = load i8, ptr %arrayidx1, align 1
277  %cmp3 = icmp eq i8 %ld1, %ld2
278  br i1 %cmp3, label %loop.inc, label %loop.end
279
280loop.inc:
281  %index.next = add i64 %index, 1
282  %exitcond = icmp ne i64 %index.next, 67
283  br i1 %exitcond, label %loop, label %loop.end
284
285loop.end:
286  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
287  ret i64 %retval
288}
289
290
291; The early exit (i.e. unknown exit-not-taken count) is the latch - we don't
292; support this yet.
293define i64 @uncountable_exit_on_last_block() {
294; CHECK-LABEL: LV: Checking a loop in 'uncountable_exit_on_last_block'
295; CHECK:       LV: Not vectorizing: Early exit is not the latch predecessor.
296entry:
297  %p1 = alloca [1024 x i8]
298  %p2 = alloca [1024 x i8]
299  call void @init_mem(ptr %p1, i64 1024)
300  call void @init_mem(ptr %p2, i64 1024)
301  br label %loop
302
303loop:
304  %index = phi i64 [ %index.next, %search ], [ 3, %entry ]
305  %index.next = add i64 %index, 1
306  %exitcond = icmp ne i64 %index.next, 67
307  br i1 %exitcond, label %search, label %loop.end
308
309search:
310  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
311  %ld1 = load i8, ptr %arrayidx, align 1
312  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
313  %ld2 = load i8, ptr %arrayidx1, align 1
314  %cmp3 = icmp eq i8 %ld1, %ld2
315  br i1 %cmp3, label %loop.end, label %loop
316
317loop.end:
318  %retval = phi i64 [ 64, %loop ], [ %index, %search ]
319  ret i64 %retval
320}
321
322
323; We don't currently support multiple uncountable early exits.
324define i64 @multiple_uncountable_exits() {
325; CHECK-LABEL: LV: Checking a loop in 'multiple_uncountable_exits'
326; CHECK:       LV: Not vectorizing: Loop has too many uncountable exits.
327entry:
328  %p1 = alloca [1024 x i8]
329  %p2 = alloca [1024 x i8]
330  call void @init_mem(ptr %p1, i64 1024)
331  call void @init_mem(ptr %p2, i64 1024)
332  br label %search1
333
334search1:
335  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
336  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
337  %ld1 = load i8, ptr %arrayidx, align 1
338  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
339  %ld2 = load i8, ptr %arrayidx1, align 1
340  %cmp1 = icmp eq i8 %ld1, %ld2
341  br i1 %cmp1, label %loop.end, label %search2
342
343search2:
344  %cmp2 = icmp ult i8 %ld1, 34
345  br i1 %cmp2, label %loop.end, label %loop.inc
346
347loop.inc:
348  %index.next = add i64 %index, 1
349  %exitcond = icmp ne i64 %index.next, 67
350  br i1 %exitcond, label %search1, label %loop.end
351
352loop.end:
353  %retval = phi i64 [ %index, %search1 ], [ 100, %search2 ], [ 43, %loop.inc ]
354  ret i64 %retval
355}
356
357
358define i64 @uncountable_exit_infinite_loop() {
359; CHECK-LABEL: LV: Checking a loop in 'uncountable_exit_infinite_loop'
360; CHECK:       LV: Not vectorizing: Cannot vectorize uncountable loop.
361entry:
362  %p1 = alloca [1024 x i8]
363  %p2 = alloca [1024 x i8]
364  call void @init_mem(ptr %p1, i64 1024)
365  call void @init_mem(ptr %p2, i64 1024)
366  br label %loop
367
368loop:
369  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
370  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
371  %ld1 = load i8, ptr %arrayidx, align 1
372  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
373  %ld2 = load i8, ptr %arrayidx1, align 1
374  %cmp3 = icmp eq i8 %ld1, %ld2
375  br i1 %cmp3, label %loop.inc, label %loop.end
376
377loop.inc:
378  %index.next = add i64 %index, 1
379  %exitcond = icmp ne i64 %index.next, 67
380  br label %loop
381
382loop.end:
383  %retval = phi i64 [ %index, %loop ]
384  ret i64 %retval
385}
386
387
388define i64 @loop_contains_unsafe_call() {
389; CHECK-LABEL: LV: Checking a loop in 'loop_contains_unsafe_call'
390; CHECK:       LV: Not vectorizing: Early exit loop contains operations that cannot be speculatively executed.
391entry:
392  %p1 = alloca [1024 x i8]
393  %p2 = alloca [1024 x i8]
394  call void @init_mem(ptr %p1, i64 1024)
395  call void @init_mem(ptr %p2, i64 1024)
396  br label %loop
397
398loop:
399  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
400  %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index
401  %ld1 = load i32, ptr %arrayidx, align 1
402  %bad_call = call i32 @foo(i32 %ld1) #0
403  %cmp = icmp eq i32 %bad_call, 34
404  br i1 %cmp, label %loop.inc, label %loop.end
405
406loop.inc:
407  %index.next = add i64 %index, 1
408  %exitcond = icmp ne i64 %index.next, 67
409  br i1 %exitcond, label %loop, label %loop.end
410
411loop.end:
412  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
413  ret i64 %retval
414}
415
416
417define i64 @loop_contains_unsafe_div() {
418; CHECK-LABEL: LV: Checking a loop in 'loop_contains_unsafe_div'
419; CHECK:       LV: Not vectorizing: Early exit loop contains operations that cannot be speculatively executed.
420entry:
421  %p1 = alloca [1024 x i8]
422  %p2 = alloca [1024 x i8]
423  call void @init_mem(ptr %p1, i64 1024)
424  call void @init_mem(ptr %p2, i64 1024)
425  br label %loop
426
427loop:
428  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
429  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
430  %ld1 = load i32, ptr %arrayidx, align 1
431  %div = udiv i32 20000, %ld1
432  %cmp = icmp eq i32 %div, 1
433  br i1 %cmp, label %loop.inc, label %loop.end
434
435loop.inc:
436  %index.next = add i64 %index, 1
437  %exitcond = icmp ne i64 %index.next, 67
438  br i1 %exitcond, label %loop, label %loop.end
439
440loop.end:
441  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
442  ret i64 %retval
443}
444
445
446define i64 @loop_contains_store(ptr %dest) {
447; CHECK-LABEL: LV: Checking a loop in 'loop_contains_store'
448; CHECK:       LV: Not vectorizing: Writes to memory unsupported in early exit loops
449entry:
450  %p1 = alloca [1024 x i8]
451  call void @init_mem(ptr %p1, i64 1024)
452  br label %loop
453
454loop:
455  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
456  %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index
457  %ld1 = load i32, ptr %arrayidx, align 1
458  %arrayidx2 = getelementptr inbounds i32, ptr %dest, i64 %index
459  store i32 %ld1, ptr %arrayidx2, align 4
460  %cmp = icmp eq i32 %ld1, 1
461  br i1 %cmp, label %loop.inc, label %loop.end
462
463loop.inc:
464  %index.next = add i64 %index, 1
465  %exitcond = icmp ne i64 %index.next, 67
466  br i1 %exitcond, label %loop, label %loop.end
467
468loop.end:
469  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
470  ret i64 %retval
471}
472
473
474define i64 @uncountable_exit_in_conditional_block(ptr %mask) {
475; CHECK-LABEL: LV: Checking a loop in 'uncountable_exit_in_conditional_block'
476; CHECK:       LV: Not vectorizing: Early exit is not the latch predecessor.
477entry:
478  %p1 = alloca [1024 x i8]
479  %p2 = alloca [1024 x i8]
480  call void @init_mem(ptr %p1, i64 1024)
481  call void @init_mem(ptr %p2, i64 1024)
482  br label %loop
483
484loop:
485  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
486  %arrayidx1 = getelementptr inbounds i8, ptr %mask, i64 %index
487  %ld1 = load i8, ptr %arrayidx1, align 1
488  %cmp1 = icmp ne i8 %ld1, 0
489  br i1 %cmp1, label %loop.search, label %loop.inc
490
491loop.search:
492  %arrayidx2 = getelementptr inbounds i8, ptr %p1, i64 %index
493  %ld2 = load i8, ptr %arrayidx2, align 1
494  %arrayidx3 = getelementptr inbounds i8, ptr %p2, i64 %index
495  %ld3 = load i8, ptr %arrayidx3, align 1
496  %cmp2 = icmp eq i8 %ld2, %ld3
497  br i1 %cmp2, label %loop.inc, label %loop.end
498
499loop.inc:
500  %index.next = add i64 %index, 1
501  %exitcond = icmp ne i64 %index.next, 67
502  br i1 %exitcond, label %loop, label %loop.end
503
504loop.end:
505  %retval = phi i64 [ %index, %loop.search ], [ 67, %loop.inc ]
506  ret i64 %retval
507}
508
509
510define i64 @same_exit_block_pre_inc_use1_with_reduction() {
511; CHECK-LABEL: LV: Checking a loop in 'same_exit_block_pre_inc_use1_with_reduction'
512; CHECK:       LV: Not vectorizing: Found reductions or recurrences in early-exit loop.
513entry:
514  %p1 = alloca [1024 x i8]
515  %p2 = alloca [1024 x i8]
516  call void @init_mem(ptr %p1, i64 1024)
517  call void @init_mem(ptr %p2, i64 1024)
518  br label %loop
519
520loop:
521  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
522  %red = phi i64 [ %red.next, %loop.inc ], [ 0, %entry ]
523  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
524  %ld1 = load i8, ptr %arrayidx, align 1
525  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
526  %ld2 = load i8, ptr %arrayidx1, align 1
527  %ld2.zext = zext i8 %ld2 to i64
528  %red.next = add i64 %red, %ld2.zext
529  %cmp3 = icmp eq i8 %ld1, %ld2
530  br i1 %cmp3, label %loop.inc, label %loop.end
531
532loop.inc:
533  %index.next = add i64 %index, 1
534  %exitcond = icmp ne i64 %index.next, 67
535  br i1 %exitcond, label %loop, label %loop.end
536
537loop.end:
538  %final.ind = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
539  %retval = add i64 %red.next, %final.ind
540  ret i64 %retval
541}
542
543
544define i64 @uncountable_exit_has_multiple_outside_successors() {
545; CHECK-LABEL: LV: Checking a loop in 'uncountable_exit_has_multiple_outside_successors'
546; CHECK:       LV: Not vectorizing: Loop contains an unsupported switch
547entry:
548  %p1 = alloca [1024 x i8]
549  call void @init_mem(ptr %p1, i64 1024)
550  br label %loop
551
552loop:
553  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
554  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
555  %ld1 = load i8, ptr %arrayidx, align 1
556  switch i8 %ld1, label %loop.inc [
557  i8 2, label %loop.end
558  i8 3, label %loop.surprise
559  ]
560
561loop.inc:
562  %index.next = add i64 %index, 1
563  %exitcond = icmp ne i64 %index.next, 67
564  br i1 %exitcond, label %loop, label %loop.end
565
566loop.surprise:
567  ret i64 3
568
569loop.end:
570  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
571  ret i64 %retval
572}
573
574
575declare i32 @foo(i32) readonly
576declare <vscale x 4 x i32> @foo_vec(<vscale x 4 x i32>)
577
578attributes #0 = { "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vec)" }
579