Revert "Warn when unique objects might be duplicated in shared libraries (#117622)"
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / first-order-recurrence-chains-vplan.ll
blob32d32a64049ac0b58df6f876dc61b4bc5ee184c1
1 ; REQUIRES: asserts
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
5 define 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: }
62 entry:
63   br label %loop
65 loop:
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
77 exit:
78   ret void
81 define 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: }
144 entry:
145   br label %loop
147 loop:
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
161 exit:
162   ret void
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.
169 define 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: }
225 entry:
226   br label %loop
228 loop:
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
241 ret:
242   ret i32 0
245 define 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: }
303 entry:
304   br label %loop
306 loop:
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
320 ret:
321   ret i32 0