xref: /llvm-project/llvm/test/Transforms/LoopUnroll/AArch64/apple-unrolling-multi-exit.ll (revision 3007f31e7458442cafb7fbd7f5c8b7228b5bd98e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt -p loop-unroll -mcpu=apple-m1 -S %s | FileCheck --check-prefix=APPLE %s
3; RUN: opt -p loop-unroll -mcpu=apple-m2 -S %s | FileCheck --check-prefix=APPLE %s
4; RUN: opt -p loop-unroll -mcpu=apple-m3 -S %s | FileCheck --check-prefix=APPLE %s
5; RUN: opt -p loop-unroll -mcpu=apple-m4 -S %s | FileCheck --check-prefix=APPLE %s
6; RUN: opt -p loop-unroll -mcpu=cortex-a57 -S %s | FileCheck --check-prefix=OTHER %s
7
8target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
9target triple = "arm64-apple-macosx15.0.0"
10
11define i1 @multi_2_exit_find_i8_loop(ptr %vec, i8 %tgt) {
12; APPLE-LABEL: define i1 @multi_2_exit_find_i8_loop(
13; APPLE-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0:[0-9]+]] {
14; APPLE-NEXT:  [[ENTRY:.*]]:
15; APPLE-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
16; APPLE-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1
17; APPLE-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
18; APPLE-NEXT:    br label %[[LOOP_HEADER:.*]]
19; APPLE:       [[LOOP_HEADER]]:
20; APPLE-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
21; APPLE-NEXT:    [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8
22; APPLE-NEXT:    [[C_1:%.*]] = icmp eq i8 [[L]], [[TGT]]
23; APPLE-NEXT:    br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
24; APPLE:       [[LOOP_LATCH]]:
25; APPLE-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1
26; APPLE-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
27; APPLE-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
28; APPLE:       [[EXIT]]:
29; APPLE-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
30; APPLE-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
31; APPLE-NEXT:    ret i1 [[C_3]]
32;
33; OTHER-LABEL: define i1 @multi_2_exit_find_i8_loop(
34; OTHER-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0:[0-9]+]] {
35; OTHER-NEXT:  [[ENTRY:.*]]:
36; OTHER-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
37; OTHER-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1
38; OTHER-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
39; OTHER-NEXT:    br label %[[LOOP_HEADER:.*]]
40; OTHER:       [[LOOP_HEADER]]:
41; OTHER-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
42; OTHER-NEXT:    [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8
43; OTHER-NEXT:    [[C_1:%.*]] = icmp eq i8 [[L]], [[TGT]]
44; OTHER-NEXT:    br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
45; OTHER:       [[LOOP_LATCH]]:
46; OTHER-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1
47; OTHER-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
48; OTHER-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
49; OTHER:       [[EXIT]]:
50; OTHER-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
51; OTHER-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
52; OTHER-NEXT:    ret i1 [[C_3]]
53;
54entry:
55  %start = load ptr, ptr %vec, align 8
56  %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 1
57  %end = load ptr, ptr %gep.end, align 8
58  br label %loop.header
59
60loop.header:
61  %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ]
62  %l = load i8, ptr %ptr.iv, align 8
63  %c.1 = icmp eq i8 %l, %tgt
64  br i1 %c.1, label %exit, label %loop.latch
65
66loop.latch:
67  %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 1
68  %c.2 = icmp eq ptr %ptr.iv.next, %end
69  br i1 %c.2, label %exit, label %loop.header
70
71exit:
72  %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ]
73  %c.3 = icmp eq ptr %res, %end
74  ret i1 %c.3
75}
76
77
78define i1 @multi_2_exit_find_ptr_loop(ptr %vec, ptr %tgt) {
79; APPLE-LABEL: define i1 @multi_2_exit_find_ptr_loop(
80; APPLE-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]]) #[[ATTR0]] {
81; APPLE-NEXT:  [[ENTRY:.*]]:
82; APPLE-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
83; APPLE-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ]
84; APPLE-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8
85; APPLE-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
86; APPLE-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
87; APPLE-NEXT:    br label %[[LOOP_HEADER:.*]]
88; APPLE:       [[LOOP_HEADER]]:
89; APPLE-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
90; APPLE-NEXT:    [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8
91; APPLE-NEXT:    [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]]
92; APPLE-NEXT:    br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
93; APPLE:       [[LOOP_LATCH]]:
94; APPLE-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8
95; APPLE-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
96; APPLE-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
97; APPLE:       [[EXIT]]:
98; APPLE-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
99; APPLE-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
100; APPLE-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
101; APPLE-NEXT:    ret i1 [[C_3]]
102;
103; OTHER-LABEL: define i1 @multi_2_exit_find_ptr_loop(
104; OTHER-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]]) #[[ATTR0]] {
105; OTHER-NEXT:  [[ENTRY:.*]]:
106; OTHER-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
107; OTHER-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ]
108; OTHER-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8
109; OTHER-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
110; OTHER-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
111; OTHER-NEXT:    br label %[[LOOP_HEADER:.*]]
112; OTHER:       [[LOOP_HEADER]]:
113; OTHER-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
114; OTHER-NEXT:    [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8
115; OTHER-NEXT:    [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]]
116; OTHER-NEXT:    br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
117; OTHER:       [[LOOP_LATCH]]:
118; OTHER-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8
119; OTHER-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
120; OTHER-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
121; OTHER:       [[EXIT]]:
122; OTHER-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
123; OTHER-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
124; OTHER-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
125; OTHER-NEXT:    ret i1 [[C_3]]
126;
127entry:
128  %start = load ptr, ptr %vec, align 8
129  call void @llvm.assume(i1 true) [ "align"(ptr %start, i64 8) ]
130  %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 8
131  %end = load ptr, ptr %gep.end, align 8
132  call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ]
133  br label %loop.header
134
135loop.header:
136  %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ]
137  %l = load ptr, ptr %ptr.iv, align 8
138  %c.1 = icmp eq ptr %l, %tgt
139  br i1 %c.1, label %exit, label %loop.latch
140
141loop.latch:
142  %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 8
143  %c.2 = icmp eq ptr %ptr.iv.next, %end
144  br i1 %c.2, label %exit, label %loop.header
145
146exit:
147  %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ]
148  call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ]
149  %c.3 = icmp eq ptr %res, %end
150  ret i1 %c.3
151}
152
153define i1 @multi_2_exit_find_i8_loop_too_large(ptr %vec, i8 %tgt) {
154; APPLE-LABEL: define i1 @multi_2_exit_find_i8_loop_too_large(
155; APPLE-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] {
156; APPLE-NEXT:  [[ENTRY:.*]]:
157; APPLE-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
158; APPLE-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1
159; APPLE-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
160; APPLE-NEXT:    br label %[[LOOP_HEADER:.*]]
161; APPLE:       [[LOOP_HEADER]]:
162; APPLE-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
163; APPLE-NEXT:    [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8
164; APPLE-NEXT:    [[UDIV:%.*]] = udiv i8 [[L]], [[TGT]]
165; APPLE-NEXT:    [[UDIV_2:%.*]] = udiv i8 [[UDIV]], 10
166; APPLE-NEXT:    [[C_1:%.*]] = icmp eq i8 [[UDIV_2]], 2
167; APPLE-NEXT:    br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
168; APPLE:       [[LOOP_LATCH]]:
169; APPLE-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1
170; APPLE-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
171; APPLE-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
172; APPLE:       [[EXIT]]:
173; APPLE-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
174; APPLE-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
175; APPLE-NEXT:    ret i1 [[C_3]]
176;
177; OTHER-LABEL: define i1 @multi_2_exit_find_i8_loop_too_large(
178; OTHER-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] {
179; OTHER-NEXT:  [[ENTRY:.*]]:
180; OTHER-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
181; OTHER-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1
182; OTHER-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
183; OTHER-NEXT:    br label %[[LOOP_HEADER:.*]]
184; OTHER:       [[LOOP_HEADER]]:
185; OTHER-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
186; OTHER-NEXT:    [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8
187; OTHER-NEXT:    [[UDIV:%.*]] = udiv i8 [[L]], [[TGT]]
188; OTHER-NEXT:    [[UDIV_2:%.*]] = udiv i8 [[UDIV]], 10
189; OTHER-NEXT:    [[C_1:%.*]] = icmp eq i8 [[UDIV_2]], 2
190; OTHER-NEXT:    br i1 [[C_1]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
191; OTHER:       [[LOOP_LATCH]]:
192; OTHER-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1
193; OTHER-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
194; OTHER-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
195; OTHER:       [[EXIT]]:
196; OTHER-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
197; OTHER-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
198; OTHER-NEXT:    ret i1 [[C_3]]
199;
200entry:
201  %start = load ptr, ptr %vec, align 8
202  %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 1
203  %end = load ptr, ptr %gep.end, align 8
204  br label %loop.header
205
206loop.header:
207  %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ]
208  %l = load i8, ptr %ptr.iv, align 8
209  %udiv = udiv i8 %l, %tgt
210  %udiv.2 = udiv i8 %udiv, 10
211  %c.1 = icmp eq i8 %udiv.2, 2
212  br i1 %c.1, label %exit, label %loop.latch
213
214loop.latch:
215  %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 1
216  %c.2 = icmp eq ptr %ptr.iv.next, %end
217  br i1 %c.2, label %exit, label %loop.header
218
219exit:
220  %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ]
221  %c.3 = icmp eq ptr %res, %end
222  ret i1 %c.3
223}
224define i1 @multi_3_exit_find_ptr_loop(ptr %vec, ptr %tgt, ptr %tgt2) {
225; APPLE-LABEL: define i1 @multi_3_exit_find_ptr_loop(
226; APPLE-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]], ptr [[TGT2:%.*]]) #[[ATTR0]] {
227; APPLE-NEXT:  [[ENTRY:.*]]:
228; APPLE-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
229; APPLE-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ]
230; APPLE-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8
231; APPLE-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
232; APPLE-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
233; APPLE-NEXT:    br label %[[LOOP_HEADER:.*]]
234; APPLE:       [[LOOP_HEADER]]:
235; APPLE-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
236; APPLE-NEXT:    [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8
237; APPLE-NEXT:    [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]]
238; APPLE-NEXT:    [[C_2:%.*]] = icmp eq ptr [[L]], [[TGT2]]
239; APPLE-NEXT:    [[OR_COND:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]]
240; APPLE-NEXT:    br i1 [[OR_COND]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
241; APPLE:       [[LOOP_LATCH]]:
242; APPLE-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8
243; APPLE-NEXT:    [[C_3:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
244; APPLE-NEXT:    br i1 [[C_3]], label %[[EXIT]], label %[[LOOP_HEADER]]
245; APPLE:       [[EXIT]]:
246; APPLE-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
247; APPLE-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
248; APPLE-NEXT:    [[C_4:%.*]] = icmp eq ptr [[RES]], [[END]]
249; APPLE-NEXT:    ret i1 [[C_4]]
250;
251; OTHER-LABEL: define i1 @multi_3_exit_find_ptr_loop(
252; OTHER-SAME: ptr [[VEC:%.*]], ptr [[TGT:%.*]], ptr [[TGT2:%.*]]) #[[ATTR0]] {
253; OTHER-NEXT:  [[ENTRY:.*]]:
254; OTHER-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
255; OTHER-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[START]], i64 8) ]
256; OTHER-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 8
257; OTHER-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
258; OTHER-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
259; OTHER-NEXT:    br label %[[LOOP_HEADER:.*]]
260; OTHER:       [[LOOP_HEADER]]:
261; OTHER-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
262; OTHER-NEXT:    [[L:%.*]] = load ptr, ptr [[PTR_IV]], align 8
263; OTHER-NEXT:    [[C_1:%.*]] = icmp eq ptr [[L]], [[TGT]]
264; OTHER-NEXT:    [[C_2:%.*]] = icmp eq ptr [[L]], [[TGT2]]
265; OTHER-NEXT:    [[OR_COND:%.*]] = select i1 [[C_1]], i1 true, i1 [[C_2]]
266; OTHER-NEXT:    br i1 [[OR_COND]], label %[[EXIT:.*]], label %[[LOOP_LATCH]]
267; OTHER:       [[LOOP_LATCH]]:
268; OTHER-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 8
269; OTHER-NEXT:    [[C_3:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
270; OTHER-NEXT:    br i1 [[C_3]], label %[[EXIT]], label %[[LOOP_HEADER]]
271; OTHER:       [[EXIT]]:
272; OTHER-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
273; OTHER-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[END]], i64 8) ]
274; OTHER-NEXT:    [[C_4:%.*]] = icmp eq ptr [[RES]], [[END]]
275; OTHER-NEXT:    ret i1 [[C_4]]
276;
277entry:
278  %start = load ptr, ptr %vec, align 8
279  call void @llvm.assume(i1 true) [ "align"(ptr %start, i64 8) ]
280  %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 8
281  %end = load ptr, ptr %gep.end, align 8
282  call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ]
283  br label %loop.header
284
285loop.header:
286  %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ]
287  %l = load ptr, ptr %ptr.iv, align 8
288  %c.1 = icmp eq ptr %l, %tgt
289  br i1 %c.1, label %exit, label %then
290
291then:
292  %c.2 = icmp eq ptr %l, %tgt2
293  br i1 %c.2, label %exit, label %loop.latch
294
295loop.latch:
296  %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 8
297  %c.3 = icmp eq ptr %ptr.iv.next, %end
298  br i1 %c.3, label %exit, label %loop.header
299
300exit:
301  %res = phi ptr [ %ptr.iv, %loop.header ], [ %ptr.iv, %then], [ %end, %loop.latch ]
302  call void @llvm.assume(i1 true) [ "align"(ptr %end, i64 8) ]
303  %c.4 = icmp eq ptr %res, %end
304  ret i1 %c.4
305}
306
307define i1 @multi_3_exit_find_i8_loop_switch(ptr %vec, i8 %tgt) {
308; APPLE-LABEL: define i1 @multi_3_exit_find_i8_loop_switch(
309; APPLE-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] {
310; APPLE-NEXT:  [[ENTRY:.*]]:
311; APPLE-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
312; APPLE-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1
313; APPLE-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
314; APPLE-NEXT:    br label %[[LOOP_HEADER:.*]]
315; APPLE:       [[LOOP_HEADER]]:
316; APPLE-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
317; APPLE-NEXT:    [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8
318; APPLE-NEXT:    switch i8 [[L]], label %[[LOOP_LATCH]] [
319; APPLE-NEXT:      i8 0, label %[[EXIT_1:.*]]
320; APPLE-NEXT:      i8 1, label %[[EXIT_2:.*]]
321; APPLE-NEXT:      i8 2, label %[[EXIT:.*]]
322; APPLE-NEXT:    ]
323; APPLE:       [[LOOP_LATCH]]:
324; APPLE-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1
325; APPLE-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
326; APPLE-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
327; APPLE:       [[EXIT]]:
328; APPLE-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
329; APPLE-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
330; APPLE-NEXT:    ret i1 [[C_3]]
331; APPLE:       [[EXIT_1]]:
332; APPLE-NEXT:    ret i1 false
333; APPLE:       [[EXIT_2]]:
334; APPLE-NEXT:    ret i1 true
335;
336; OTHER-LABEL: define i1 @multi_3_exit_find_i8_loop_switch(
337; OTHER-SAME: ptr [[VEC:%.*]], i8 [[TGT:%.*]]) #[[ATTR0]] {
338; OTHER-NEXT:  [[ENTRY:.*]]:
339; OTHER-NEXT:    [[START:%.*]] = load ptr, ptr [[VEC]], align 8
340; OTHER-NEXT:    [[GEP_END:%.*]] = getelementptr inbounds nuw i8, ptr [[VEC]], i64 1
341; OTHER-NEXT:    [[END:%.*]] = load ptr, ptr [[GEP_END]], align 8
342; OTHER-NEXT:    br label %[[LOOP_HEADER:.*]]
343; OTHER:       [[LOOP_HEADER]]:
344; OTHER-NEXT:    [[PTR_IV:%.*]] = phi ptr [ [[PTR_IV_NEXT:%.*]], %[[LOOP_LATCH:.*]] ], [ [[START]], %[[ENTRY]] ]
345; OTHER-NEXT:    [[L:%.*]] = load i8, ptr [[PTR_IV]], align 8
346; OTHER-NEXT:    switch i8 [[L]], label %[[LOOP_LATCH]] [
347; OTHER-NEXT:      i8 0, label %[[EXIT_1:.*]]
348; OTHER-NEXT:      i8 1, label %[[EXIT_2:.*]]
349; OTHER-NEXT:      i8 2, label %[[EXIT:.*]]
350; OTHER-NEXT:    ]
351; OTHER:       [[LOOP_LATCH]]:
352; OTHER-NEXT:    [[PTR_IV_NEXT]] = getelementptr inbounds nuw i8, ptr [[PTR_IV]], i64 1
353; OTHER-NEXT:    [[C_2:%.*]] = icmp eq ptr [[PTR_IV_NEXT]], [[END]]
354; OTHER-NEXT:    br i1 [[C_2]], label %[[EXIT]], label %[[LOOP_HEADER]]
355; OTHER:       [[EXIT]]:
356; OTHER-NEXT:    [[RES:%.*]] = phi ptr [ [[PTR_IV]], %[[LOOP_HEADER]] ], [ [[END]], %[[LOOP_LATCH]] ]
357; OTHER-NEXT:    [[C_3:%.*]] = icmp eq ptr [[RES]], [[END]]
358; OTHER-NEXT:    ret i1 [[C_3]]
359; OTHER:       [[EXIT_1]]:
360; OTHER-NEXT:    ret i1 false
361; OTHER:       [[EXIT_2]]:
362; OTHER-NEXT:    ret i1 true
363;
364entry:
365  %start = load ptr, ptr %vec, align 8
366  %gep.end = getelementptr inbounds nuw i8, ptr %vec, i64 1
367  %end = load ptr, ptr %gep.end, align 8
368  br label %loop.header
369
370loop.header:
371  %ptr.iv = phi ptr [ %ptr.iv.next, %loop.latch ], [ %start, %entry ]
372  %l = load i8, ptr %ptr.iv, align 8
373  switch i8 %l, label %loop.latch [
374  i8 0, label %exit.1
375  i8 1, label %exit.2
376  i8 2, label %exit ]
377
378loop.latch:
379  %ptr.iv.next = getelementptr inbounds nuw i8, ptr %ptr.iv, i64 1
380  %c.2 = icmp eq ptr %ptr.iv.next, %end
381  br i1 %c.2, label %exit, label %loop.header
382
383exit:
384  %res = phi ptr [ %ptr.iv, %loop.header ], [ %end, %loop.latch ]
385  %c.3 = icmp eq ptr %res, %end
386  ret i1 %c.3
387
388exit.1:
389  ret i1 0
390
391exit.2:
392  ret i1 1
393}
394
395declare void @llvm.assume(i1 noundef)
396