xref: /llvm-project/llvm/test/Transforms/LoopVectorize/first-order-recurrence-chains-vplan.ll (revision 7f3428d3ed71d87a2088b77b6cab9f3d86544234)
1; REQUIRES: asserts
2
3; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -debug-only=loop-vectorize -disable-output -S %s 2>&1 | FileCheck %s
4
5define void @test_chained_first_order_recurrences_1(ptr %ptr) {
6; CHECK-LABEL: 'test_chained_first_order_recurrences_1'
7; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
8; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
9; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
10; CHECK-NEXT: Live-in ir<1000> = original trip-count
11; CHECK-EMPTY:
12; CHECK-NEXT: ir-bb<entry>:
13; CHECK-NEXT: Successor(s): vector.ph
14; CHECK-EMPTY:
15; CHECK-NEXT: vector.ph:
16; CHECK-NEXT: Successor(s): vector loop
17; CHECK-EMPTY:
18; CHECK-NEXT: <x1> vector loop: {
19; CHECK-NEXT:   vector.body:
20; CHECK-NEXT:     EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION
21; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.1> = phi ir<22>, ir<%for.1.next>
22; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.2> = phi ir<33>, vp<[[FOR1_SPLICE:%.+]]>
23; CHECK-NEXT:     vp<[[STEPS:%.+]]>    = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>
24; CHECK-NEXT:     CLONE ir<%gep.ptr> = getelementptr inbounds ir<%ptr>, vp<[[STEPS]]>
25; CHECK-NEXT:     vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%gep.ptr>
26; CHECK-NEXT:     WIDEN ir<%for.1.next> = load vp<[[VEC_PTR]]>
27; CHECK-NEXT:     EMIT vp<[[FOR1_SPLICE]]> = first-order splice ir<%for.1>, ir<%for.1.next>
28; CHECK-NEXT:     EMIT vp<[[FOR2_SPLICE:%.+]]> = first-order splice ir<%for.2>, vp<[[FOR1_SPLICE]]>
29; CHECK-NEXT:     WIDEN ir<%add> = add vp<[[FOR1_SPLICE]]>, vp<[[FOR2_SPLICE]]>
30; CHECK-NEXT:     vp<[[VEC_PTR2:%.+]]> = vector-pointer ir<%gep.ptr>
31; CHECK-NEXT:     WIDEN store vp<[[VEC_PTR2]]>, ir<%add>
32; CHECK-NEXT:     EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
33; CHECK-NEXT:     EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VTC]]>
34; CHECK-NEXT:   No successors
35; CHECK-NEXT: }
36; CHECK-NEXT: Successor(s): middle.block
37; CHECK-EMPTY:
38; CHECK-NEXT: middle.block:
39; CHECK-NEXT:    EMIT vp<[[RESUME_1:%.+]]> = extract-from-end ir<%for.1.next>, ir<1>
40; CHECK-NEXT:    EMIT vp<[[RESUME_2:%.+]]>.1 = extract-from-end vp<[[FOR1_SPLICE]]>, ir<1>
41; CHECK-NEXT:    EMIT vp<[[CMP:%.+]]> = icmp eq ir<1000>, vp<[[VTC]]>
42; CHECK-NEXT:    EMIT branch-on-cond vp<[[CMP]]>
43; CHECK-NEXT:  Successor(s): ir-bb<exit>, scalar.ph
44; CHECK-EMPTY:
45; CHECK-NEXT:  scalar.ph
46; CHECK-NEXT:    EMIT vp<[[RESUME_1_P:%.*]]> = resume-phi vp<[[RESUME_1]]>, ir<22>
47; CHECK-NEXT:    EMIT vp<[[RESUME_2_P:%.*]]>.1 = resume-phi vp<[[RESUME_2]]>.1, ir<33>
48; CHECK-NEXT:    EMIT vp<[[RESUME_IV:%.*]]> = resume-phi vp<[[VTC]]>, ir<0>
49; CHECK-NEXT:  Successor(s): ir-bb<loop>
50; CHECK-EMPTY:
51; CHECK-NEXT:  ir-bb<loop>:
52; CHECK-NEXT:    IR   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ] (extra operand: vp<[[RESUME_1_P]]> from scalar.ph)
53; CHECK-NEXT:    IR   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ] (extra operand: vp<[[RESUME_2_P]]>.1 from scalar.ph)
54; CHECK-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] (extra operand: vp<[[RESUME_IV]]> from scalar.ph)
55; CHECK:         IR   %exitcond.not = icmp eq i64 %iv.next, 1000
56; CHECK-NEXT:  No successors
57; CHECK-EMPTY:
58; CHECK-NEXT:  ir-bb<exit>
59; CHECK-NEXT:  No successors
60; CHECK-NEXT: }
61;
62entry:
63  br label %loop
64
65loop:
66  %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
67  %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
68  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
69  %iv.next = add nuw nsw i64 %iv, 1
70  %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
71  %for.1.next = load i16, ptr %gep.ptr, align 2
72  %add = add i16 %for.1, %for.2
73  store i16 %add, ptr %gep.ptr
74  %exitcond.not = icmp eq i64 %iv.next, 1000
75  br i1 %exitcond.not, label %exit, label %loop
76
77exit:
78  ret void
79}
80
81define void @test_chained_first_order_recurrences_3(ptr %ptr) {
82; CHECK-LABEL: 'test_chained_first_order_recurrences_3'
83; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
84; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
85; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
86; CHECK-NEXT: Live-in ir<1000> = original trip-count
87; CHECK-EMPTY:
88; CHECK-NEXT: ir-bb<entry>:
89; CHECK-NEXT: Successor(s): vector.ph
90; CHECK-EMPTY:
91; CHECK-NEXT: vector.ph:
92; CHECK-NEXT: Successor(s): vector loop
93; CHECK-EMPTY:
94; CHECK-NEXT: <x1> vector loop: {
95; CHECK-NEXT:   vector.body:
96; CHECK-NEXT:     EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION
97; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.1> = phi ir<22>, ir<%for.1.next>
98; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.2> = phi ir<33>, vp<[[FOR1_SPLICE:%.+]]>
99; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.3> = phi ir<33>, vp<[[FOR2_SPLICE:%.+]]>
100; CHECK-NEXT:     vp<[[STEPS:%.+]]>    = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>
101; CHECK-NEXT:     CLONE ir<%gep.ptr> = getelementptr inbounds ir<%ptr>, vp<[[STEPS]]>
102; CHECK-NEXT:     vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%gep.ptr>
103; CHECK-NEXT:     WIDEN ir<%for.1.next> = load vp<[[VEC_PTR]]>
104; CHECK-NEXT:     EMIT vp<[[FOR1_SPLICE]]> = first-order splice ir<%for.1>, ir<%for.1.next>
105; CHECK-NEXT:     EMIT vp<[[FOR2_SPLICE]]> = first-order splice ir<%for.2>, vp<[[FOR1_SPLICE]]>
106; CHECK-NEXT:     EMIT vp<[[FOR3_SPLICE:%.+]]> = first-order splice ir<%for.3>, vp<[[FOR2_SPLICE]]>
107; CHECK-NEXT:     WIDEN ir<%add.1> = add vp<[[FOR1_SPLICE]]>, vp<[[FOR2_SPLICE]]>
108; CHECK-NEXT:     WIDEN ir<%add.2> = add ir<%add.1>, vp<[[FOR3_SPLICE]]>
109; CHECK-NEXT:     vp<[[VEC_PTR2:%.+]]> = vector-pointer ir<%gep.ptr>
110; CHECK-NEXT:     WIDEN store vp<[[VEC_PTR2]]>, ir<%add.2>
111; CHECK-NEXT:     EMIT vp<[[CAN_IV_NEXT:%.+]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
112; CHECK-NEXT:     EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VTC]]>
113; CHECK-NEXT:   No successors
114; CHECK-NEXT: }
115; CHECK-NEXT: Successor(s): middle.block
116; CHECK-EMPTY:
117; CHECK-NEXT: middle.block:
118; CHECK-NEXT:    EMIT vp<[[RESUME_1:%.+]]> = extract-from-end ir<%for.1.next>, ir<1>
119; CHECK-NEXT:    EMIT vp<[[RESUME_2:%.+]]>.1 = extract-from-end vp<[[FOR1_SPLICE]]>, ir<1>
120; CHECK-NEXT:    EMIT vp<[[RESUME_3:%.+]]>.2 = extract-from-end vp<[[FOR2_SPLICE]]>, ir<1>
121; CHECK-NEXT:    EMIT vp<[[CMP:%.+]]> = icmp eq ir<1000>, vp<[[VTC]]>
122; CHECK-NEXT:    EMIT branch-on-cond vp<[[CMP]]>
123; CHECK-NEXT:  Successor(s): ir-bb<exit>, scalar.ph
124; CHECK-EMPTY:
125; CHECK-NEXT:  scalar.ph
126; CHECK-NEXT:    EMIT vp<[[RESUME_1_P:%.*]]> = resume-phi vp<[[RESUME_1]]>, ir<22>
127; CHECK-NEXT:    EMIT vp<[[RESUME_2_P:%.*]]>.1 = resume-phi vp<[[RESUME_2]]>.1, ir<33>
128; CHECK-NEXT:    EMIT vp<[[RESUME_3_P:%.*]]>.2 = resume-phi vp<[[RESUME_3]]>.2, ir<33>
129; CHECK-NEXT:    EMIT vp<[[RESUME_IV:%.*]]> = resume-phi vp<[[VTC]]>, ir<0>
130; CHECK-NEXT:  Successor(s): ir-bb<loop>
131; CHECK-EMPTY:
132; CHECK-NEXT:  ir-bb<loop>:
133; CHECK-NEXT:    IR   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ] (extra operand: vp<[[RESUME_1_P]]> from scalar.ph)
134; CHECK-NEXT:    IR   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ] (extra operand: vp<[[RESUME_2_P]]>.1 from scalar.ph)
135; CHECK-NEXT:    IR   %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ] (extra operand: vp<[[RESUME_3_P]]>.2 from scalar.ph)
136; CHECK-NEXT:    IR   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] (extra operand: vp<[[RESUME_IV]]> from scalar.ph)
137; CHECK:         IR   %exitcond.not = icmp eq i64 %iv.next, 1000
138; CHECK-NEXT: No successors
139; CHECK-EMPTY:
140; CHECK-NEXT:  ir-bb<exit>
141; CHECK-NEXT:  No successors
142; CHECK-NEXT: }
143;
144entry:
145  br label %loop
146
147loop:
148  %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
149  %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
150  %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
151  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
152  %iv.next = add nuw nsw i64 %iv, 1
153  %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
154  %for.1.next = load i16, ptr %gep.ptr, align 2
155  %add.1 = add i16 %for.1, %for.2
156  %add.2 = add i16 %add.1, %for.3
157  store i16 %add.2, ptr %gep.ptr
158  %exitcond.not = icmp eq i64 %iv.next, 1000
159  br i1 %exitcond.not, label %exit, label %loop
160
161exit:
162  ret void
163}
164
165; This test has two FORs (for.x and for.y) where incoming value from the previous
166; iteration (for.x.prev) of one FOR (for.y) depends on another FOR (for.x).
167; Sinking would require moving a recipe with side effects (store). Instead,
168; for.x.next can be hoisted.
169define i32 @test_chained_first_order_recurrences_4(ptr %base, i64 %x) {
170; CHECK-LABEL: 'test_chained_first_order_recurrences_4'
171; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
172; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
173; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
174; CHECK-NEXT: Live-in ir<4098> = original trip-count
175; CHECK-EMPTY:
176; CHECK-NEXT: ir-bb<entry>:
177; CHECK-NEXT: Successor(s): vector.ph
178; CHECK-EMPTY:
179; CHECK-NEXT: vector.ph:
180; CHECK-NEXT:   WIDEN ir<%for.x.next> = mul ir<%x>, ir<2>
181; CHECK-NEXT: Successor(s): vector loop
182; CHECK-EMPTY:
183; CHECK-NEXT: <x1> vector loop: {
184; CHECK-NEXT:   vector.body:
185; CHECK-NEXT:     EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[CAN_IV_NEXT:%.+]]>
186; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.x> = phi ir<0>, ir<%for.x.next>
187; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.y> = phi ir<0>, ir<%for.x.prev>
188; CHECK-NEXT:     vp<[[SCALAR_STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>
189; CHECK-NEXT:     CLONE ir<%gep> = getelementptr ir<%base>, vp<[[SCALAR_STEPS]]>
190; CHECK-NEXT:     EMIT vp<[[SPLICE_X:%.]]> = first-order splice ir<%for.x>, ir<%for.x.next>
191; CHECK-NEXT:     WIDEN-CAST ir<%for.x.prev> = trunc vp<[[SPLICE_X]]> to i32
192; CHECK-NEXT:     EMIT vp<[[SPLICE_Y:%.+]]> = first-order splice ir<%for.y>, ir<%for.x.prev>
193; CHECK-NEXT:     WIDEN-CAST ir<%for.y.i64> = sext vp<[[SPLICE_Y]]> to i64
194; CHECK-NEXT:     vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%gep>
195; CHECK-NEXT:     WIDEN store vp<[[VEC_PTR]]>, ir<%for.y.i64>
196; CHECK-NEXT:     EMIT vp<[[CAN_IV_NEXT]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
197; CHECK-NEXT:     EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VTC]]>
198; CHECK-NEXT:   No successors
199; CHECK-NEXT: }
200; CHECK-NEXT: Successor(s): middle.block
201; CHECK-EMPTY:
202; CHECK-NEXT: middle.block:
203; CHECK-NEXT:   EMIT vp<[[EXT_X:%.+]]> = extract-from-end ir<%for.x.next>, ir<1>
204; CHECK-NEXT:   EMIT vp<[[EXT_Y:%.+]]>.1 = extract-from-end ir<%for.x.prev>, ir<1>
205; CHECK-NEXT:   EMIT vp<[[MIDDLE_C:%.+]]> = icmp eq ir<4098>, vp<[[VTC]]>
206; CHECK-NEXT:   EMIT branch-on-cond vp<[[MIDDLE_C]]>
207; CHECK-NEXT: Successor(s): ir-bb<ret>, scalar.ph
208; CHECK-EMPTY:
209; CHECK-NEXT: scalar.ph:
210; CHECK-NEXT:   EMIT vp<[[RESUME_IV:%.*]]> = resume-phi vp<[[VTC]]>, ir<0>
211; CHECK-NEXT:   EMIT vp<[[RESUME_X:%.+]]> = resume-phi vp<[[EXT_X]]>, ir<0>
212; CHECK-NEXT:   EMIT vp<[[RESUME_Y:%.+]]>.1 = resume-phi vp<[[EXT_Y]]>.1, ir<0>
213; CHECK-NEXT: Successor(s): ir-bb<loop>
214; CHECK-EMPTY:
215; CHECK-NEXT: ir-bb<loop>:
216; CHECK-NEXT:   IR   %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] (extra operand: vp<[[RESUME_IV]]> from scalar.ph)
217; CHECK-NEXT:   IR   %for.x = phi i64 [ %for.x.next, %loop ], [ 0, %entry ] (extra operand: vp<[[RESUME_X]]> from scalar.ph)
218; CHECK-NEXT:   IR   %for.y = phi i32 [ %for.x.prev, %loop ], [ 0, %entry ] (extra operand: vp<[[RESUME_Y]]>.1 from scalar.ph)
219; CHECK:     No successors
220; CHECK-EMPTY:
221; CHECK-NEXT: ir-bb<ret>:
222; CHECK-NEXT: No successors
223; CHECK-NEXT: }
224;
225entry:
226  br label %loop
227
228loop:
229  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
230  %for.x = phi i64 [ %for.x.next, %loop ], [ 0, %entry ]
231  %for.y = phi i32 [ %for.x.prev, %loop ], [ 0, %entry ]
232  %iv.next = add i64 %iv, 1
233  %gep = getelementptr i64, ptr %base, i64 %iv
234  %for.x.prev = trunc i64 %for.x to i32
235  %for.y.i64 = sext i32 %for.y to i64
236  store i64 %for.y.i64, ptr %gep
237  %for.x.next = mul i64 %x, 2
238  %icmp = icmp ugt i64 %iv, 4096
239  br i1 %icmp, label %ret, label %loop
240
241ret:
242  ret i32 0
243}
244
245define i32 @test_chained_first_order_recurrences_5_hoist_to_load(ptr %base) {
246; CHECK-LABEL: 'test_chained_first_order_recurrences_5_hoist_to_load'
247; CHECK:      VPlan 'Initial VPlan for VF={4},UF>=1' {
248; CHECK-NEXT: Live-in vp<[[VFxUF:%.+]]> = VF * UF
249; CHECK-NEXT: Live-in vp<[[VTC:%.+]]> = vector-trip-count
250; CHECK-NEXT: Live-in ir<4098> = original trip-count
251; CHECK-EMPTY:
252; CHECK-NEXT: ir-bb<entry>:
253; CHECK-NEXT: Successor(s): vector.ph
254; CHECK-EMPTY:
255; CHECK-NEXT: vector.ph:
256; CHECK-NEXT: Successor(s): vector loop
257; CHECK-EMPTY:
258; CHECK-NEXT: <x1> vector loop: {
259; CHECK-NEXT:   vector.body:
260; CHECK-NEXT:     EMIT vp<[[CAN_IV:%.+]]> = CANONICAL-INDUCTION ir<0>, vp<[[CAN_IV_NEXT:%.+]]>
261; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.x> = phi ir<0>, ir<%for.x.next>
262; CHECK-NEXT:     FIRST-ORDER-RECURRENCE-PHI ir<%for.y> = phi ir<0>, ir<%for.x.prev>
263; CHECK-NEXT:     vp<[[SCALAR_STEPS:%.+]]> = SCALAR-STEPS vp<[[CAN_IV]]>, ir<1>
264; CHECK-NEXT:     CLONE ir<%gep> = getelementptr ir<%base>, vp<[[SCALAR_STEPS]]>
265; CHECK-NEXT:     vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%gep>
266; CHECK-NEXT:     WIDEN ir<%l> = load vp<[[VEC_PTR]]>
267; CHECK-NEXT:     WIDEN ir<%for.x.next> = mul ir<%l>, ir<2>
268; CHECK-NEXT:     EMIT vp<[[SPLICE_X:%.]]> = first-order splice ir<%for.x>, ir<%for.x.next>
269; CHECK-NEXT:     WIDEN-CAST ir<%for.x.prev> = trunc vp<[[SPLICE_X]]> to i32
270; CHECK-NEXT:     EMIT vp<[[SPLICE_Y:%.+]]> = first-order splice ir<%for.y>, ir<%for.x.prev>
271; CHECK-NEXT:     WIDEN-CAST ir<%for.y.i64> = sext vp<[[SPLICE_Y]]> to i64
272; CHECK-NEXT:     vp<[[VEC_PTR:%.+]]> = vector-pointer ir<%gep>
273; CHECK-NEXT:     WIDEN store vp<[[VEC_PTR]]>, ir<%for.y.i64>
274; CHECK-NEXT:     EMIT vp<[[CAN_IV_NEXT]]> = add nuw vp<[[CAN_IV]]>, vp<[[VFxUF]]>
275; CHECK-NEXT:     EMIT branch-on-count vp<[[CAN_IV_NEXT]]>, vp<[[VTC]]>
276; CHECK-NEXT:   No successors
277; CHECK-NEXT: }
278; CHECK-NEXT: Successor(s): middle.block
279; CHECK-EMPTY:
280; CHECK-NEXT: middle.block:
281; CHECK-NEXT:   EMIT vp<[[EXT_X:%.+]]> = extract-from-end ir<%for.x.next>, ir<1>
282; CHECK-NEXT:   EMIT vp<[[EXT_Y:%.+]]>.1 = extract-from-end ir<%for.x.prev>, ir<1>
283; CHECK-NEXT:   EMIT vp<[[MIDDLE_C:%.+]]> = icmp eq ir<4098>, vp<[[VTC]]>
284; CHECK-NEXT:   EMIT branch-on-cond vp<[[MIDDLE_C]]>
285; CHECK-NEXT: Successor(s): ir-bb<ret>, scalar.ph
286; CHECK-EMPTY:
287; CHECK-NEXT: scalar.ph:
288; CHECK-NEXT:   EMIT vp<[[RESUME_IV:%.*]]> = resume-phi vp<[[VTC]]>, ir<0>
289; CHECK-NEXT:   EMIT vp<[[RESUME_X:%.+]]> = resume-phi vp<[[EXT_X]]>, ir<0>
290; CHECK-NEXT:   EMIT vp<[[RESUME_Y:%.+]]>.1 = resume-phi vp<[[EXT_Y]]>.1, ir<0>
291; CHECK-NEXT: Successor(s): ir-bb<loop>
292; CHECK-EMPTY:
293; CHECK-NEXT: ir-bb<loop>:
294; CHECK-NEXT:   IR   %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] (extra operand: vp<[[RESUME_IV]]> from scalar.ph)
295; CHECK-NEXT:   IR   %for.x = phi i64 [ %for.x.next, %loop ], [ 0, %entry ] (extra operand: vp<[[RESUME_X]]> from scalar.ph)
296; CHECK-NEXT:   IR   %for.y = phi i32 [ %for.x.prev, %loop ], [ 0, %entry ] (extra operand: vp<[[RESUME_Y]]>.1 from scalar.ph)
297; CHECK:     No successors
298; CHECK-EMPTY:
299; CHECK-NEXT: ir-bb<ret>:
300; CHECK-NEXT: No successors
301; CHECK-NEXT: }
302;
303entry:
304  br label %loop
305
306loop:
307  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
308  %for.x = phi i64 [ %for.x.next, %loop ], [ 0, %entry ]
309  %for.y = phi i32 [ %for.x.prev, %loop ], [ 0, %entry ]
310  %iv.next = add i64 %iv, 1
311  %gep = getelementptr i64, ptr %base, i64 %iv
312  %l = load i64, ptr %gep
313  %for.x.prev = trunc i64 %for.x to i32
314  %for.y.i64 = sext i32 %for.y to i64
315  store i64 %for.y.i64, ptr %gep
316  %for.x.next = mul i64 %l, 2
317  %icmp = icmp ugt i64 %iv, 4096
318  br i1 %icmp, label %ret, label %loop
319
320ret:
321  ret i32 0
322}
323