xref: /llvm-project/llvm/test/Transforms/LoopVectorize/unsupported_early_exit.ll (revision 5fae408d3a4c073ee43aec9906fa44ffe4026301)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S < %s -p loop-vectorize -enable-early-exit-vectorization  -force-vector-width=4 | FileCheck %s
3
4declare void @init_mem(ptr, i64);
5
6
7; The early exit (i.e. unknown exit-not-taken count) is the latch - we don't
8; support this yet.
9define i64 @early_exit_on_last_block() {
10; CHECK-LABEL: define i64 @early_exit_on_last_block() {
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
13; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
14; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
15; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
16; CHECK-NEXT:    br label [[LAND_RHS:%.*]]
17; CHECK:       loop:
18; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[SEARCH:%.*]] ], [ 3, [[ENTRY:%.*]] ]
19; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
20; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
21; CHECK-NEXT:    br i1 [[CMP1]], label [[SEARCH]], label [[FOR_END_LOOPEXIT:%.*]]
22; CHECK:       search:
23; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
24; CHECK-NEXT:    [[TMP41:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
25; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
26; CHECK-NEXT:    [[TMP42:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
27; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i8 [[TMP41]], [[TMP42]]
28; CHECK-NEXT:    br i1 [[CMP3]], label [[FOR_END_LOOPEXIT]], label [[LAND_RHS]]
29; CHECK:       loop.end:
30; CHECK-NEXT:    [[START_0_LCSSA:%.*]] = phi i64 [ 64, [[LAND_RHS]] ], [ [[INDEX]], [[SEARCH]] ]
31; CHECK-NEXT:    ret i64 [[START_0_LCSSA]]
32;
33entry:
34  %p1 = alloca [1024 x i8]
35  %p2 = alloca [1024 x i8]
36  call void @init_mem(ptr %p1, i64 1024)
37  call void @init_mem(ptr %p2, i64 1024)
38  br label %loop
39
40loop:
41  %index = phi i64 [ %index.next, %search ], [ 3, %entry ]
42  %index.next = add i64 %index, 1
43  %exitcond = icmp ne i64 %index.next, 67
44  br i1 %exitcond, label %search, label %loop.end
45
46search:
47  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
48  %ld1 = load i8, ptr %arrayidx, align 1
49  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
50  %ld2 = load i8, ptr %arrayidx1, align 1
51  %cmp3 = icmp eq i8 %ld1, %ld2
52  br i1 %cmp3, label %loop.end, label %loop
53
54loop.end:
55  %retval = phi i64 [ 64, %loop ], [ %index, %search ]
56  ret i64 %retval
57}
58
59
60; We don't currently support multiple early exits.
61define i64 @multiple_uncountable_exits() {
62; CHECK-LABEL: define i64 @multiple_uncountable_exits() {
63; CHECK-NEXT:  entry:
64; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
65; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
66; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
67; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
68; CHECK-NEXT:    br label [[SEARCH1:%.*]]
69; CHECK:       search1:
70; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
71; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
72; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
73; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
74; CHECK-NEXT:    [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
75; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[LD1]], [[LD2]]
76; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP_END:%.*]], label [[SEARCH2:%.*]]
77; CHECK:       search2:
78; CHECK-NEXT:    [[CMP2:%.*]] = icmp ult i8 [[LD1]], 34
79; CHECK-NEXT:    br i1 [[CMP2]], label [[LOOP_END]], label [[LOOP_INC]]
80; CHECK:       loop.inc:
81; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
82; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
83; CHECK-NEXT:    br i1 [[EXITCOND]], label [[SEARCH1]], label [[LOOP_END]]
84; CHECK:       loop.end:
85; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[SEARCH1]] ], [ 100, [[SEARCH2]] ], [ 43, [[LOOP_INC]] ]
86; CHECK-NEXT:    ret i64 [[RETVAL]]
87;
88entry:
89  %p1 = alloca [1024 x i8]
90  %p2 = alloca [1024 x i8]
91  call void @init_mem(ptr %p1, i64 1024)
92  call void @init_mem(ptr %p2, i64 1024)
93  br label %search1
94
95search1:
96  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
97  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
98  %ld1 = load i8, ptr %arrayidx, align 1
99  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
100  %ld2 = load i8, ptr %arrayidx1, align 1
101  %cmp1 = icmp eq i8 %ld1, %ld2
102  br i1 %cmp1, label %loop.end, label %search2
103
104search2:
105  %cmp2 = icmp ult i8 %ld1, 34
106  br i1 %cmp2, label %loop.end, label %loop.inc
107
108loop.inc:
109  %index.next = add i64 %index, 1
110  %exitcond = icmp ne i64 %index.next, 67
111  br i1 %exitcond, label %search1, label %loop.end
112
113loop.end:
114  %retval = phi i64 [ %index, %search1 ], [ 100, %search2 ], [ 43, %loop.inc ]
115  ret i64 %retval
116}
117
118
119define i64 @uncountable_exit_infinite_loop() {
120; CHECK-LABEL: define i64 @uncountable_exit_infinite_loop() {
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
123; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
124; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
125; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
126; CHECK-NEXT:    br label [[LOOP:%.*]]
127; CHECK:       loop:
128; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
129; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
130; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
131; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
132; CHECK-NEXT:    [[LD2:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
133; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i8 [[LD1]], [[LD2]]
134; CHECK-NEXT:    br i1 [[CMP3]], label [[LOOP_INC]], label [[LOOP_END:%.*]]
135; CHECK:       loop.inc:
136; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
137; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
138; CHECK-NEXT:    br label [[LOOP]]
139; CHECK:       loop.end:
140; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ]
141; CHECK-NEXT:    ret i64 [[RETVAL]]
142;
143entry:
144  %p1 = alloca [1024 x i8]
145  %p2 = alloca [1024 x i8]
146  call void @init_mem(ptr %p1, i64 1024)
147  call void @init_mem(ptr %p2, i64 1024)
148  br label %loop
149
150loop:
151  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
152  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
153  %ld1 = load i8, ptr %arrayidx, align 1
154  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
155  %ld2 = load i8, ptr %arrayidx1, align 1
156  %cmp3 = icmp eq i8 %ld1, %ld2
157  br i1 %cmp3, label %loop.inc, label %loop.end
158
159loop.inc:
160  %index.next = add i64 %index, 1
161  %exitcond = icmp ne i64 %index.next, 67
162  br label %loop
163
164loop.end:
165  %retval = phi i64 [ %index, %loop ]
166  ret i64 %retval
167}
168
169
170define i64 @loop_contains_unsafe_call() {
171; CHECK-LABEL: define i64 @loop_contains_unsafe_call() {
172; CHECK-NEXT:  entry:
173; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
174; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
175; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
176; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
177; CHECK-NEXT:    br label [[LOOP:%.*]]
178; CHECK:       loop:
179; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
180; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P1]], i64 [[INDEX]]
181; CHECK-NEXT:    [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1
182; CHECK-NEXT:    [[BAD_CALL:%.*]] = call i32 @foo(i32 [[LD1]]) #[[ATTR1:[0-9]+]]
183; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[BAD_CALL]], 34
184; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]]
185; CHECK:       loop.inc:
186; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
187; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
188; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
189; CHECK:       loop.end:
190; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ]
191; CHECK-NEXT:    ret i64 [[RETVAL]]
192;
193entry:
194  %p1 = alloca [1024 x i8]
195  %p2 = alloca [1024 x i8]
196  call void @init_mem(ptr %p1, i64 1024)
197  call void @init_mem(ptr %p2, i64 1024)
198  br label %loop
199
200loop:
201  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
202  %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index
203  %ld1 = load i32, ptr %arrayidx, align 1
204  %bad_call = call i32 @foo(i32 %ld1) #0
205  %cmp = icmp eq i32 %bad_call, 34
206  br i1 %cmp, label %loop.inc, label %loop.end
207
208loop.inc:
209  %index.next = add i64 %index, 1
210  %exitcond = icmp ne i64 %index.next, 67
211  br i1 %exitcond, label %loop, label %loop.end
212
213loop.end:
214  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
215  ret i64 %retval
216}
217
218
219define i64 @loop_contains_unsafe_div() {
220; CHECK-LABEL: define i64 @loop_contains_unsafe_div() {
221; CHECK-NEXT:  entry:
222; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
223; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
224; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
225; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
226; CHECK-NEXT:    br label [[LOOP:%.*]]
227; CHECK:       loop:
228; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
229; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
230; CHECK-NEXT:    [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1
231; CHECK-NEXT:    [[DIV:%.*]] = udiv i32 20000, [[LD1]]
232; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[DIV]], 1
233; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]]
234; CHECK:       loop.inc:
235; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
236; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
237; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
238; CHECK:       loop.end:
239; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ]
240; CHECK-NEXT:    ret i64 [[RETVAL]]
241;
242entry:
243  %p1 = alloca [1024 x i8]
244  %p2 = alloca [1024 x i8]
245  call void @init_mem(ptr %p1, i64 1024)
246  call void @init_mem(ptr %p2, i64 1024)
247  br label %loop
248
249loop:
250  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
251  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
252  %ld1 = load i32, ptr %arrayidx, align 1
253  %div = udiv i32 20000, %ld1
254  %cmp = icmp eq i32 %div, 1
255  br i1 %cmp, label %loop.inc, label %loop.end
256
257loop.inc:
258  %index.next = add i64 %index, 1
259  %exitcond = icmp ne i64 %index.next, 67
260  br i1 %exitcond, label %loop, label %loop.end
261
262loop.end:
263  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
264  ret i64 %retval
265}
266
267
268define i64 @loop_contains_store(ptr %dest) {
269; CHECK-LABEL: define i64 @loop_contains_store(
270; CHECK-SAME: ptr [[DEST:%.*]]) {
271; CHECK-NEXT:  entry:
272; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
273; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
274; CHECK-NEXT:    br label [[LOOP:%.*]]
275; CHECK:       loop:
276; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
277; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[P1]], i64 [[INDEX]]
278; CHECK-NEXT:    [[LD1:%.*]] = load i32, ptr [[ARRAYIDX]], align 1
279; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[DEST]], i64 [[INDEX]]
280; CHECK-NEXT:    store i32 [[LD1]], ptr [[ARRAYIDX2]], align 4
281; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[LD1]], 1
282; CHECK-NEXT:    br i1 [[CMP]], label [[LOOP_INC]], label [[LOOP_END:%.*]]
283; CHECK:       loop.inc:
284; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
285; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
286; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
287; CHECK:       loop.end:
288; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ]
289; CHECK-NEXT:    ret i64 [[RETVAL]]
290;
291entry:
292  %p1 = alloca [1024 x i8]
293  call void @init_mem(ptr %p1, i64 1024)
294  br label %loop
295
296loop:
297  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
298  %arrayidx = getelementptr inbounds i32, ptr %p1, i64 %index
299  %ld1 = load i32, ptr %arrayidx, align 1
300  %arrayidx2 = getelementptr inbounds i32, ptr %dest, i64 %index
301  store i32 %ld1, ptr %arrayidx2, align 4
302  %cmp = icmp eq i32 %ld1, 1
303  br i1 %cmp, label %loop.inc, label %loop.end
304
305loop.inc:
306  %index.next = add i64 %index, 1
307  %exitcond = icmp ne i64 %index.next, 67
308  br i1 %exitcond, label %loop, label %loop.end
309
310loop.end:
311  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
312  ret i64 %retval
313}
314
315
316define i64 @uncountable_exit_in_conditional_block(ptr %mask) {
317; CHECK-LABEL: define i64 @uncountable_exit_in_conditional_block(
318; CHECK-SAME: ptr [[MASK:%.*]]) {
319; CHECK-NEXT:  entry:
320; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
321; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
322; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
323; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
324; CHECK-NEXT:    br label [[LOOP:%.*]]
325; CHECK:       loop:
326; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
327; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[MASK]], i64 [[INDEX]]
328; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
329; CHECK-NEXT:    [[CMP1:%.*]] = icmp ne i8 [[LD1]], 0
330; CHECK-NEXT:    br i1 [[CMP1]], label [[LOOP_SEARCH:%.*]], label [[LOOP_INC]]
331; CHECK:       loop.search:
332; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
333; CHECK-NEXT:    [[LD2:%.*]] = load i8, ptr [[ARRAYIDX2]], align 1
334; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
335; CHECK-NEXT:    [[LD3:%.*]] = load i8, ptr [[ARRAYIDX3]], align 1
336; CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[LD2]], [[LD3]]
337; CHECK-NEXT:    br i1 [[CMP2]], label [[LOOP_INC]], label [[LOOP_END:%.*]]
338; CHECK:       loop.inc:
339; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
340; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
341; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
342; CHECK:       loop.end:
343; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP_SEARCH]] ], [ 67, [[LOOP_INC]] ]
344; CHECK-NEXT:    ret i64 [[RETVAL]]
345;
346entry:
347  %p1 = alloca [1024 x i8]
348  %p2 = alloca [1024 x i8]
349  call void @init_mem(ptr %p1, i64 1024)
350  call void @init_mem(ptr %p2, i64 1024)
351  br label %loop
352
353loop:
354  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
355  %arrayidx1 = getelementptr inbounds i8, ptr %mask, i64 %index
356  %ld1 = load i8, ptr %arrayidx1, align 1
357  %cmp1 = icmp ne i8 %ld1, 0
358  br i1 %cmp1, label %loop.search, label %loop.inc
359
360loop.search:
361  %arrayidx2 = getelementptr inbounds i8, ptr %p1, i64 %index
362  %ld2 = load i8, ptr %arrayidx2, align 1
363  %arrayidx3 = getelementptr inbounds i8, ptr %p2, i64 %index
364  %ld3 = load i8, ptr %arrayidx3, align 1
365  %cmp2 = icmp eq i8 %ld2, %ld3
366  br i1 %cmp2, label %loop.inc, label %loop.end
367
368loop.inc:
369  %index.next = add i64 %index, 1
370  %exitcond = icmp ne i64 %index.next, 67
371  br i1 %exitcond, label %loop, label %loop.end
372
373loop.end:
374  %retval = phi i64 [ %index, %loop.search ], [ 67, %loop.inc ]
375  ret i64 %retval
376}
377
378
379define i64 @same_exit_block_pre_inc_use1_with_reduction() {
380; CHECK-LABEL: define i64 @same_exit_block_pre_inc_use1_with_reduction() {
381; CHECK-NEXT:  entry:
382; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
383; CHECK-NEXT:    [[P2:%.*]] = alloca [1024 x i8], align 1
384; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
385; CHECK-NEXT:    call void @init_mem(ptr [[P2]], i64 1024)
386; CHECK-NEXT:    br label [[LAND_RHS:%.*]]
387; CHECK:       loop:
388; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
389; CHECK-NEXT:    [[RED:%.*]] = phi i64 [ [[RED_NEXT:%.*]], [[FOR_INC]] ], [ 0, [[ENTRY]] ]
390; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
391; CHECK-NEXT:    [[TMP38:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
392; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, ptr [[P2]], i64 [[INDEX]]
393; CHECK-NEXT:    [[TMP39:%.*]] = load i8, ptr [[ARRAYIDX1]], align 1
394; CHECK-NEXT:    [[LD2_ZEXT:%.*]] = zext i8 [[TMP39]] to i64
395; CHECK-NEXT:    [[RED_NEXT]] = add i64 [[RED]], [[LD2_ZEXT]]
396; CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i8 [[TMP38]], [[TMP39]]
397; CHECK-NEXT:    br i1 [[CMP3]], label [[FOR_INC]], label [[FOR_END_LOOPEXIT:%.*]]
398; CHECK:       loop.inc:
399; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
400; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
401; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LAND_RHS]], label [[FOR_END_LOOPEXIT]]
402; CHECK:       loop.end:
403; CHECK-NEXT:    [[RED_NEXT_LCSSA:%.*]] = phi i64 [ [[RED_NEXT]], [[FOR_INC]] ], [ [[RED_NEXT]], [[LAND_RHS]] ]
404; CHECK-NEXT:    [[FINAL_IND:%.*]] = phi i64 [ [[INDEX]], [[LAND_RHS]] ], [ 67, [[FOR_INC]] ]
405; CHECK-NEXT:    [[START_0_LCSSA:%.*]] = add i64 [[RED_NEXT_LCSSA]], [[FINAL_IND]]
406; CHECK-NEXT:    ret i64 [[START_0_LCSSA]]
407;
408entry:
409  %p1 = alloca [1024 x i8]
410  %p2 = alloca [1024 x i8]
411  call void @init_mem(ptr %p1, i64 1024)
412  call void @init_mem(ptr %p2, i64 1024)
413  br label %loop
414
415loop:
416  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
417  %red = phi i64 [ %red.next, %loop.inc ], [ 0, %entry ]
418  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
419  %ld1 = load i8, ptr %arrayidx, align 1
420  %arrayidx1 = getelementptr inbounds i8, ptr %p2, i64 %index
421  %ld2 = load i8, ptr %arrayidx1, align 1
422  %ld2.zext = zext i8 %ld2 to i64
423  %red.next = add i64 %red, %ld2.zext
424  %cmp3 = icmp eq i8 %ld1, %ld2
425  br i1 %cmp3, label %loop.inc, label %loop.end
426
427loop.inc:
428  %index.next = add i64 %index, 1
429  %exitcond = icmp ne i64 %index.next, 67
430  br i1 %exitcond, label %loop, label %loop.end
431
432loop.end:
433  %final.ind = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
434  %retval = add i64 %red.next, %final.ind
435  ret i64 %retval
436}
437
438
439define i64 @uncountable_exit_has_multiple_outside_successors() {
440; CHECK-LABEL: define i64 @uncountable_exit_has_multiple_outside_successors() {
441; CHECK-NEXT:  entry:
442; CHECK-NEXT:    [[P1:%.*]] = alloca [1024 x i8], align 1
443; CHECK-NEXT:    call void @init_mem(ptr [[P1]], i64 1024)
444; CHECK-NEXT:    br label [[LOOP:%.*]]
445; CHECK:       loop:
446; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ [[INDEX_NEXT:%.*]], [[LOOP_INC:%.*]] ], [ 3, [[ENTRY:%.*]] ]
447; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 [[INDEX]]
448; CHECK-NEXT:    [[LD1:%.*]] = load i8, ptr [[ARRAYIDX]], align 1
449; CHECK-NEXT:    switch i8 [[LD1]], label [[LOOP_INC]] [
450; CHECK-NEXT:      i8 2, label [[LOOP_END:%.*]]
451; CHECK-NEXT:      i8 3, label [[LOOP_SURPRISE:%.*]]
452; CHECK-NEXT:    ]
453; CHECK:       loop.inc:
454; CHECK-NEXT:    [[INDEX_NEXT]] = add i64 [[INDEX]], 1
455; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i64 [[INDEX_NEXT]], 67
456; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[LOOP_END]]
457; CHECK:       loop.surprise:
458; CHECK-NEXT:    ret i64 3
459; CHECK:       loop.end:
460; CHECK-NEXT:    [[RETVAL:%.*]] = phi i64 [ [[INDEX]], [[LOOP]] ], [ 67, [[LOOP_INC]] ]
461; CHECK-NEXT:    ret i64 [[RETVAL]]
462;
463entry:
464  %p1 = alloca [1024 x i8]
465  call void @init_mem(ptr %p1, i64 1024)
466  br label %loop
467
468loop:
469  %index = phi i64 [ %index.next, %loop.inc ], [ 3, %entry ]
470  %arrayidx = getelementptr inbounds i8, ptr %p1, i64 %index
471  %ld1 = load i8, ptr %arrayidx, align 1
472  switch i8 %ld1, label %loop.inc [
473  i8 2, label %loop.end
474  i8 3, label %loop.surprise
475  ]
476
477loop.inc:
478  %index.next = add i64 %index, 1
479  %exitcond = icmp ne i64 %index.next, 67
480  br i1 %exitcond, label %loop, label %loop.end
481
482loop.surprise:
483  ret i64 3
484
485loop.end:
486  %retval = phi i64 [ %index, %loop ], [ 67, %loop.inc ]
487  ret i64 %retval
488}
489
490
491declare i32 @foo(i32) readonly
492declare <vscale x 4 x i32> @foo_vec(<vscale x 4 x i32>)
493
494attributes #0 = { "vector-function-abi-variant"="_ZGVsNxv_foo(foo_vec)" }
495