Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / first-order-recurrence-chains.ll
blobc663d2b15b5871e68d7072743270ea7c1ffc82c7
1 ; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -S %s | FileCheck %s
3 define i16 @test_chained_first_order_recurrences_1(ptr %ptr) {
4 ; CHECK-LABEL: @test_chained_first_order_recurrences_1
5 ; CHECK:       vector.body:
6 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
7 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
8 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
9 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
10 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
11 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
12 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
13 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
14 ; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
15 ; CHECK-NEXT:    [[TMP6:%.*]] = add <4 x i16> [[TMP4]], [[TMP5]]
16 ; CHECK-NEXT:    store <4 x i16> [[TMP6]], ptr [[TMP2]], align 2
17 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
18 ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
19 ; CHECK-NEXT:    br i1 [[TMP8]], label %middle.block, label %vector.body
20 ; CHECK:       middle.block:
21 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
22 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
23 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT2:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
24 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI3:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
26 entry:
27   br label %loop
29 loop:
30   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
31   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
32   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
33   %iv.next = add nuw nsw i64 %iv, 1
34   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
35   %for.1.next = load i16, ptr %gep.ptr, align 2
36   %add = add i16 %for.1, %for.2
37   store i16 %add, ptr %gep.ptr
38   %exitcond.not = icmp eq i64 %iv.next, 1000
39   br i1 %exitcond.not, label %exit, label %loop
41 exit:
42   %res = add i16 %for.1, %for.2
43   ret i16 %res
46 define i16 @test_chained_first_order_recurrences_2(ptr %ptr) {
47 ; CHECK-LABEL: @test_chained_first_order_recurrences_2
48 ; CHECK:       vector.body:
49 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
50 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
51 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
52 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
53 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
54 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
55 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
56 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
57 ; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
58 ; CHECK-NEXT:    [[TMP6:%.*]] = add <4 x i16> [[TMP4]], [[TMP5]]
59 ; CHECK-NEXT:    store <4 x i16> [[TMP6]], ptr [[TMP2]], align 2
60 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
61 ; CHECK-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
62 ; CHECK-NEXT:    br i1 [[TMP8]], label %middle.block, label %vector.body, !llvm.loop [[LOOP4:![0-9]+]]
63 ; CHECK:      middle.block:
64 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
65 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
66 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT2:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
67 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI3:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
69 entry:
70   br label %loop
72 loop:
73   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
74   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
75   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
76   %iv.next = add nuw nsw i64 %iv, 1
77   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
78   %for.1.next = load i16, ptr %gep.ptr, align 2
79   %add = add i16 %for.1, %for.2
80   store i16 %add, ptr %gep.ptr
81   %exitcond.not = icmp eq i64 %iv.next, 1000
82   br i1 %exitcond.not, label %exit, label %loop
84 exit:
85   %res = add i16 %for.1, %for.2
86   ret i16 %res
89 define i16 @test_chained_first_order_recurrences_3(ptr %ptr) {
90 ; CHECK-LABEL: @test_chained_first_order_recurrences_3
91 ; CHECK:       vector.body:
92 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
93 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
94 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
95 ; CHECK-NEXT:    [[VECTOR_RECUR2:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP5:%.*]], %vector.body ]
96 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
97 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
98 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
99 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
100 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
101 ; CHECK-NEXT:    [[TMP5]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
102 ; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR2]], <4 x i16> [[TMP5]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
103 ; CHECK-NEXT:    [[TMP7:%.*]] = add <4 x i16> [[TMP4]], [[TMP5]]
104 ; CHECK-NEXT:    [[TMP8:%.*]] = add <4 x i16> [[TMP7]], [[TMP6]]
105 ; CHECK-NEXT:    store <4 x i16> [[TMP8]], ptr [[TMP2]], align 2
106 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
107 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
108 ; CHECK-NEXT:    br i1 [[TMP10]], label %middle.block, label %vector.body, !llvm.loop [[LOOP6:![0-9]+]]
109 ; CHECK:      middle.block:
110 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
111 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
112 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT3:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
113 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI4:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
114 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT7:%.*]] = extractelement <4 x i16> [[TMP5]], i32 3
115 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI8:%.*]] = extractelement <4 x i16> [[TMP5]], i32 2
117 entry:
118   br label %loop
120 loop:
121   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
122   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
123   %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
124   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
125   %iv.next = add nuw nsw i64 %iv, 1
126   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
127   %for.1.next = load i16, ptr %gep.ptr, align 2
128   %add.1 = add i16 %for.1, %for.2
129   %add.2 = add i16 %add.1, %for.3
130   store i16 %add.2, ptr %gep.ptr
131   %exitcond.not = icmp eq i64 %iv.next, 1000
132   br i1 %exitcond.not, label %exit, label %loop
134 exit:
135   %res.1 = add i16 %for.1, %for.2
136   %res.2 = add i16 %res.1, %for.3
137   ret i16 %res.2
140 define void @test_cyclic_phis(ptr %ptr) {
141 ; CHECK-LABEL: @test_cyclic_phis
142 ; CHECK-NOT: vector.body:
144 entry:
145   br label %loop
147 loop:
148   %for.1 = phi i16 [ 22, %entry ], [ %for.2, %loop ]
149   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
150   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
151   %iv.next = add nuw nsw i64 %iv, 1
152   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
153   %for.1.next = load i16, ptr %gep.ptr, align 2
154   %add = add i16 %for.1, %for.2
155   store i16 %add, ptr %gep.ptr
156   %exitcond.not = icmp eq i64 %iv.next, 1000
157   br i1 %exitcond.not, label %exit, label %loop
159 exit:
160   ret void
163 define void @test_first_order_recurrences_incoming_cycle_preheader(ptr %ptr) {
164 ; CHECK-LABEL: @test_first_order_recurrences_incoming_cycle_preheader
165 ; CHECK:       vector.body:
166 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
167 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 0>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
168 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
169 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
170 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
171 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
172 ; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
173 ; CHECK-NEXT:    [[TMP5:%.*]] = add <4 x i16> [[TMP4]], <i16 10, i16 10, i16 10, i16 10>
174 ; CHECK-NEXT:    store <4 x i16> [[TMP5]], ptr [[TMP2]], align 2
175 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
176 ; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
177 ; CHECK-NEXT:    br i1 [[TMP7]], label %middle.block, label %vector.body
179 entry:
180   br label %loop.1
182 loop.1:
183   %p = phi i16 [ 0, %entry ], [ %p, %loop.1 ]
184   br i1 true, label %loop, label %loop.1
186 loop:
187   %for.1 = phi i16 [ %p, %loop.1 ], [ %for.1.next, %loop ]
188   %iv = phi i64 [ 0, %loop.1 ], [ %iv.next, %loop ]
189   %iv.next = add nuw nsw i64 %iv, 1
190   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
191   %for.1.next = load i16, ptr %gep.ptr, align 2
192   %add = add i16 %for.1, 10
193   store i16 %add, ptr %gep.ptr
194   %exitcond.not = icmp eq i64 %iv.next, 1000
195   br i1 %exitcond.not, label %exit, label %loop
197 exit:
198   ret void
201 define i16 @test_chained_first_order_recurrences_3_reordered_1(ptr %ptr) {
202 ; CHECK-LABEL: @test_chained_first_order_recurrences_3_reordered_1
203 ; CHECK:       vector.body:
204 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
205 ; CHECK-NEXT:    [[VECTOR_RECUR2:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP5:%.*]], %vector.body ]
206 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
207 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
208 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
209 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
210 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
211 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
212 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
213 ; CHECK-NEXT:    [[TMP5]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
214 ; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR2]], <4 x i16> [[TMP5]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
215 ; CHECK-NEXT:    [[TMP7:%.*]] = add <4 x i16> [[TMP4]], [[TMP5]]
216 ; CHECK-NEXT:    [[TMP8:%.*]] = add <4 x i16> [[TMP7]], [[TMP6]]
217 ; CHECK-NEXT:    store <4 x i16> [[TMP8]], ptr [[TMP2]], align 2
218 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
219 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
220 ; CHECK-NEXT:    br i1 [[TMP10]], label %middle.block, label %vector.body, !llvm.loop [[LOOP6:![0-9]+]]
221 ; CHECK:      middle.block:
222 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT7:%.*]] = extractelement <4 x i16> [[TMP5]], i32 3
223 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI8:%.*]] = extractelement <4 x i16> [[TMP5]], i32 2
224 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT3:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
225 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI4:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
226 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
227 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
229 entry:
230   br label %loop
232 loop:
233   %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
234   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
235   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
236   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
237   %iv.next = add nuw nsw i64 %iv, 1
238   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
239   %for.1.next = load i16, ptr %gep.ptr, align 2
240   %add.1 = add i16 %for.1, %for.2
241   %add.2 = add i16 %add.1, %for.3
242   store i16 %add.2, ptr %gep.ptr
243   %exitcond.not = icmp eq i64 %iv.next, 1000
244   br i1 %exitcond.not, label %exit, label %loop
246 exit:
247   %res.1 = add i16 %for.1, %for.2
248   %res.2 = add i16 %res.1, %for.3
249   ret i16 %res.2
252 define i16 @test_chained_first_order_recurrences_3_reordered_2(ptr %ptr) {
253 ; CHECK-LABEL: @test_chained_first_order_recurrences_3_reordered_2
254 ; CHECK:       vector.body:
255 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
256 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
257 ; CHECK-NEXT:    [[VECTOR_RECUR2:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP5:%.*]], %vector.body ]
258 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
259 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
260 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
261 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
262 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
263 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
264 ; CHECK-NEXT:    [[TMP5]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
265 ; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR2]], <4 x i16> [[TMP5]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
266 ; CHECK-NEXT:    [[TMP7:%.*]] = add <4 x i16> [[TMP4]], [[TMP5]]
267 ; CHECK-NEXT:    [[TMP8:%.*]] = add <4 x i16> [[TMP7]], [[TMP6]]
268 ; CHECK-NEXT:    store <4 x i16> [[TMP8]], ptr [[TMP2]], align 2
269 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
270 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
271 ; CHECK-NEXT:    br i1 [[TMP10]], label %middle.block, label %vector.body, !llvm.loop [[LOOP6:![0-9]+]]
272 ; CHECK:      middle.block:
273 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT3:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
274 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI4:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
275 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT7:%.*]] = extractelement <4 x i16> [[TMP5]], i32 3
276 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI8:%.*]] = extractelement <4 x i16> [[TMP5]], i32 2
277 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
278 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
280 entry:
281   br label %loop
283 loop:
284   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
285   %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
286   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
287   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
288   %iv.next = add nuw nsw i64 %iv, 1
289   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
290   %for.1.next = load i16, ptr %gep.ptr, align 2
291   %add.1 = add i16 %for.1, %for.2
292   %add.2 = add i16 %add.1, %for.3
293   store i16 %add.2, ptr %gep.ptr
294   %exitcond.not = icmp eq i64 %iv.next, 1000
295   br i1 %exitcond.not, label %exit, label %loop
297 exit:
298   %res.1 = add i16 %for.1, %for.2
299   %res.2 = add i16 %res.1, %for.3
300   ret i16 %res.2
303 define i16 @test_chained_first_order_recurrences_3_for2_no_other_uses(ptr %ptr) {
304 ; CHECK-LABEL: @test_chained_first_order_recurrences_3_for2_no_other_uses
305 ; CHECK:       vector.body:
306 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
307 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
308 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
309 ; CHECK-NEXT:    [[VECTOR_RECUR2:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP5:%.*]], %vector.body ]
310 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
311 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
312 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
313 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
314 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
315 ; CHECK-NEXT:    [[TMP5]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
316 ; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR2]], <4 x i16> [[TMP5]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
317 ; CHECK-NEXT:    [[TMP7:%.*]] = add <4 x i16> [[TMP4]], <i16 10, i16 10, i16 10, i16 10>
318 ; CHECK-NEXT:    [[TMP8:%.*]] = add <4 x i16> [[TMP7]], [[TMP6]]
319 ; CHECK-NEXT:    store <4 x i16> [[TMP8]], ptr [[TMP2]], align 2
320 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
321 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
322 ; CHECK-NEXT:    br i1 [[TMP10]], label %middle.block, label %vector.body, !llvm.loop [[LOOP6:![0-9]+]]
323 ; CHECK:      middle.block:
324 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
325 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
326 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT3:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
327 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI4:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
328 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT7:%.*]] = extractelement <4 x i16> [[TMP5]], i32 3
329 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI8:%.*]] = extractelement <4 x i16> [[TMP5]], i32 2
331 entry:
332   br label %loop
334 loop:
335   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
336   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
337   %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
338   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
339   %iv.next = add nuw nsw i64 %iv, 1
340   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
341   %for.1.next = load i16, ptr %gep.ptr, align 2
342   %add.1 = add i16 %for.1, 10
343   %add.2 = add i16 %add.1, %for.3
344   store i16 %add.2, ptr %gep.ptr
345   %exitcond.not = icmp eq i64 %iv.next, 1000
346   br i1 %exitcond.not, label %exit, label %loop
348 exit:
349   %res.1 = add i16 %for.1, %for.2
350   %res.2 = add i16 %res.1, %for.3
351   ret i16 %res.2
354 define i16 @test_chained_first_order_recurrences_3_for1_for2_no_other_uses(ptr %ptr) {
355 ; CHECK-LABEL: @test_chained_first_order_recurrences_3_for1_for2_no_other_uses
356 ; CHECK:       vector.body:
357 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
358 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 22>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
359 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
360 ; CHECK-NEXT:    [[VECTOR_RECUR2:%.*]] = phi <4 x i16> [ <i16 poison, i16 poison, i16 poison, i16 33>, %vector.ph ], [ [[TMP5:%.*]], %vector.body ]
361 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
362 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i16, ptr [[PTR:%.*]], i64 [[TMP0]]
363 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 0
364 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x i16>, ptr [[TMP2]], align 2
365 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x i16> [[VECTOR_RECUR]], <4 x i16> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
366 ; CHECK-NEXT:    [[TMP5]] = shufflevector <4 x i16> [[VECTOR_RECUR1]], <4 x i16> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
367 ; CHECK-NEXT:    [[TMP6:%.*]] = shufflevector <4 x i16> [[VECTOR_RECUR2]], <4 x i16> [[TMP5]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
368 ; CHECK-NEXT:    [[TMP8:%.*]] = add <4 x i16> [[TMP6]], <i16 10, i16 10, i16 10, i16 10>
369 ; CHECK-NEXT:    store <4 x i16> [[TMP8]], ptr [[TMP2]], align 2
370 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
371 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
372 ; CHECK-NEXT:    br i1 [[TMP10]], label %middle.block, label %vector.body, !llvm.loop [[LOOP6:![0-9]+]]
373 ; CHECK:      middle.block:
374 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 3
375 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i16> [[WIDE_LOAD]], i32 2
376 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT3:%.*]] = extractelement <4 x i16> [[TMP4]], i32 3
377 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI4:%.*]] = extractelement <4 x i16> [[TMP4]], i32 2
378 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT7:%.*]] = extractelement <4 x i16> [[TMP5]], i32 3
379 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI8:%.*]] = extractelement <4 x i16> [[TMP5]], i32 2
381 entry:
382   br label %loop
384 loop:
385   %for.1 = phi i16 [ 22, %entry ], [ %for.1.next, %loop ]
386   %for.2 = phi i16 [ 33, %entry ], [ %for.1, %loop ]
387   %for.3 = phi i16 [ 33, %entry ], [ %for.2, %loop ]
388   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
389   %iv.next = add nuw nsw i64 %iv, 1
390   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
391   %for.1.next = load i16, ptr %gep.ptr, align 2
392   %add.1 = add i16 %for.3, 10
393   store i16 %add.1, ptr %gep.ptr
394   %exitcond.not = icmp eq i64 %iv.next, 1000
395   br i1 %exitcond.not, label %exit, label %loop
397 exit:
398   %res.1 = add i16 %for.1, %for.2
399   %res.2 = add i16 %res.1, %for.3
400   ret i16 %res.2
403 define double @test_chained_first_order_recurrence_sink_users_1(ptr %ptr) {
404 ; CHECK-LABEL: @test_chained_first_order_recurrence_sink_users_1
405 ; CHECK:       vector.body:
406 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
407 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x double> [ <double poison, double poison, double poison, double 1.000000e+01>, %vector.ph ], [ [[WIDE_LOAD:%.*]], %vector.body ]
408 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x double> [ <double poison, double poison, double poison, double 2.000000e+01>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
409 ; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = add i64 1, [[INDEX]]
410 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[OFFSET_IDX]], 0
411 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds double, ptr [[PTR:%.*]], i64 [[TMP0]]
412 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds double, ptr [[TMP1]], i32 0
413 ; CHECK-NEXT:    [[WIDE_LOAD]] = load <4 x double>, ptr [[TMP2]], align 8
414 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x double> [[VECTOR_RECUR]], <4 x double> [[WIDE_LOAD]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
415 ; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR1]], <4 x double> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
416 ; CHECK-NEXT:    [[TMP6:%.*]] = fadd <4 x double> <double 1.000000e+01, double 1.000000e+01, double 1.000000e+01, double 1.000000e+01>, [[TMP5]]
417 ; CHECK-NEXT:    [[TMP7:%.*]] = fadd <4 x double> [[TMP6]], [[TMP4]]
418 ; CHECK-NEXT:    store <4 x double> [[TMP7]], ptr [[TMP2]], align 8
419 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
420 ; CHECK-NEXT:    [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], 996
421 ; CHECK-NEXT:    br i1 [[TMP9]], label %middle.block, label %vector.body, !llvm.loop [[LOOP10:![0-9]+]]
422 ; CHECK:       middle.block:
423 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x double> [[WIDE_LOAD]], i32 3
424 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x double> [[WIDE_LOAD]], i32 2
425 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT2:%.*]] = extractelement <4 x double> [[TMP4]], i32 3
426 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI3:%.*]] = extractelement <4 x double> [[TMP4]], i32 2
428 entry:
429   br label %loop
431 loop:
432   %for.1 = phi double [ 10.0, %entry ], [ %for.1.next, %loop ]
433   %for.2 = phi double [ 20.0, %entry ], [ %for.1, %loop ]
434   %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
435   %add.1 = fadd double 10.0, %for.2
436   %add.2 = fadd double %add.1, %for.1
437   %iv.next = add nuw nsw i64 %iv, 1
438   %gep.ptr = getelementptr inbounds double, ptr %ptr, i64 %iv
439   %for.1.next  = load double, ptr %gep.ptr, align 8
440   store double %add.2, ptr %gep.ptr
441   %exitcond.not = icmp eq i64 %iv.next, 1000
442   br i1 %exitcond.not, label %exit, label %loop
444 exit:
445   %res = fadd double %for.1, %for.2
446   ret double %res
449 define void @test_first_order_recurrences_and_reduction(ptr %ptr) {
450 ; CHECK-LABEL: @test_first_order_recurrences_and_reduction(
451 ; CHECK-NOT:   vector.body:
453 entry:
454   br label %loop
456 loop:
457   %for.1 = phi i16 [ 22, %entry ], [ %red, %loop ]
458   %red = phi i16 [ 33, %entry ], [ %red.next, %loop ]
459   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
460   %iv.next = add nuw nsw i64 %iv, 1
461   %gep.ptr = getelementptr inbounds i16, ptr %ptr, i64 %iv
462   %lv = load i16, ptr %gep.ptr
463   %for.1.next = load i16, ptr %gep.ptr, align 2
464   %add.1 = add i16 %for.1, 10
465   %red.next = add i16 %red, %lv
466   store i16 %add.1, ptr %gep.ptr
467   %exitcond.not = icmp eq i64 %iv.next, 1000
468   br i1 %exitcond.not, label %exit, label %loop
470 exit:
471   ret void
474 define i64 @test_first_order_recurrences_and_induction(ptr %ptr) {
475 ; CHECK-LABEL: @test_first_order_recurrences_and_induction(
476 ; CHECK:       vector.body:
477 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
478 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i64> [ <i64 poison, i64 poison, i64 poison, i64 22>, %vector.ph ], [ [[VEC_IND:%.*]], %vector.body ]
479 ; CHECK-NEXT:    [[VEC_IND]] = phi <4 x i64> [ <i64 0, i64 1, i64 2, i64 3>, %vector.ph ], [ [[VEC_IND_NEXT:%.*]], %vector.body ]
480 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
481 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i64> [[VECTOR_RECUR]], <4 x i64> [[VEC_IND]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
482 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[PTR:%.*]], i64 [[TMP0]]
483 ; CHECK-NEXT:    [[TMP4:%.*]] = add <4 x i64> [[TMP1]], <i64 10, i64 10, i64 10, i64 10>
484 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i32 0
485 ; CHECK-NEXT:    store <4 x i64> [[TMP4]], ptr [[TMP3]], align 4
486 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
487 ; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], <i64 4, i64 4, i64 4, i64 4>
488 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
489 ; CHECK-NEXT:    br i1 [[TMP5]], label %middle.block, label %vector.body
490 ; CHECK:       middle.block:
491 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i64> [[VEC_IND]], i32 3
492 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i64> [[VEC_IND]], i32 2
493 ; CHECK-NEXT:    br i1 true
495 entry:
496   br label %loop
498 loop:
499   %for.1 = phi i64 [ 22, %entry ], [ %iv, %loop ]
500   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
501   %iv.next = add nuw nsw i64 %iv, 1
502   %gep.ptr = getelementptr inbounds i64, ptr %ptr, i64 %iv
503   %add.1 = add i64 %for.1, 10
504   store i64 %add.1, ptr %gep.ptr
505   %exitcond.not = icmp eq i64 %iv.next, 1000
506   br i1 %exitcond.not, label %exit, label %loop
508 exit:
509   ret i64 %for.1
512 ; Same as @test_first_order_recurrences_and_induction but with order of phis
513 ; flipped.
514 define i64 @test_first_order_recurrences_and_induction2(ptr %ptr) {
515 ; CHECK-LABEL: @test_first_order_recurrences_and_induction2(
516 ; CHECK:       vector.body:
517 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
518 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 0, i64 1, i64 2, i64 3>, %vector.ph ], [ [[VEC_IND_NEXT:%.*]], %vector.body ]
519 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x i64> [ <i64 poison, i64 poison, i64 poison, i64 22>, %vector.ph ], [ [[VEC_IND]], %vector.body ]
520 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[INDEX]], 0
521 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x i64> [[VECTOR_RECUR]], <4 x i64> [[VEC_IND]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
522 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds i64, ptr [[PTR:%.*]], i64 [[TMP0]]
523 ; CHECK-NEXT:    [[TMP4:%.*]] = add <4 x i64> [[TMP1]], <i64 10, i64 10, i64 10, i64 10>
524 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i64, ptr [[TMP2]], i32 0
525 ; CHECK-NEXT:    store <4 x i64> [[TMP4]], ptr [[TMP3]], align 4
526 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
527 ; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], <i64 4, i64 4, i64 4, i64 4>
528 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
529 ; CHECK-NEXT:    br i1 [[TMP5]], label %middle.block, label %vector.body
530 ; CHECK:       middle.block:
531 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x i64> [[VEC_IND]], i32 3
532 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x i64> [[VEC_IND]], i32 2
533 ; CHECK-NEXT:    br i1 true
535 entry:
536   br label %loop
538 loop:
539   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
540   %for.1 = phi i64 [ 22, %entry ], [ %iv, %loop ]
541   %iv.next = add nuw nsw i64 %iv, 1
542   %gep.ptr = getelementptr inbounds i64, ptr %ptr, i64 %iv
543   %add.1 = add i64 %for.1, 10
544   store i64 %add.1, ptr %gep.ptr
545   %exitcond.not = icmp eq i64 %iv.next, 1000
546   br i1 %exitcond.not, label %exit, label %loop
548 exit:
549   ret i64 %for.1
552 define ptr @test_first_order_recurrences_and_pointer_induction1(ptr %ptr) {
553 ; CHECK-LABEL: @test_first_order_recurrences_and_pointer_induction1(
554 ; CHECK:       vector.ph:
555 ; CHECK-NEXT:    [[IND_END:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 4000
556 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
557 ; CHECK:       vector.body:
558 ; CHECK-NEXT:    [[POINTER_PHI:%.*]] = phi ptr [ [[PTR]], %vector.ph ], [ [[PTR_IND:%.*]], %vector.body ]
559 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
560 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x ptr> [ <ptr poison, ptr poison, ptr poison, ptr null>, %vector.ph ], [ [[TMP0:%.*]], %vector.body ]
561 ; CHECK-NEXT:    [[TMP0]] = getelementptr i8, ptr [[POINTER_PHI]], <4 x i64> <i64 0, i64 4, i64 8, i64 12>
562 ; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 0
563 ; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x ptr> [[VECTOR_RECUR]], <4 x ptr> [[TMP0]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
564 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds ptr, ptr [[PTR]], i64 [[TMP1]]
565 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[TMP3]], i32 0
566 ; CHECK-NEXT:    store <4 x ptr> [[TMP0]], ptr [[TMP4]], align 8
567 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
568 ; CHECK-NEXT:    [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 16
569 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
570 ; CHECK-NEXT:    br i1 [[TMP5]], label %middle.block, label %vector.body
571 ; CHECK:       middle.block:
572 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x ptr> [[TMP0]], i32 3
573 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x ptr> [[TMP0]], i32 2
574 ; CHECK-NEXT:    br i1 true
576 entry:
577   br label %loop
579 loop:
580   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
581   %for.1 = phi ptr [ null, %entry ], [ %ptr.iv, %loop ]
582   %ptr.iv = phi ptr [ %ptr, %entry ], [ %ptr.iv.next, %loop ]
583   %iv.next = add nuw nsw i64 %iv, 1
584   %gep.ptr = getelementptr inbounds ptr, ptr %ptr, i64 %iv
585   store ptr %ptr.iv, ptr %gep.ptr
586   %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i64 1
587   %exitcond.not = icmp eq i64 %iv.next, 1000
588   br i1 %exitcond.not, label %exit, label %loop
590 exit:
591   ret ptr %for.1
594 ; same as @test_first_order_recurrences_and_pointer_induction1 but with order
595 ; of phis flipped.
596 define ptr @test_first_order_recurrences_and_pointer_induction2(ptr %ptr) {
597 ; CHECK-LABEL: @test_first_order_recurrences_and_pointer_induction2(
598 ; CHECK:       vector.ph:
599 ; CHECK-NEXT:    [[IND_END:%.*]] = getelementptr i8, ptr [[PTR:%.*]], i64 4000
600 ; CHECK-NEXT:    br label %vector.body
601 ; CHECK:       vector.body:
602 ; CHECK-NEXT:    [[POINTER_PHI:%.*]] = phi ptr [ [[PTR]], %vector.ph ], [ [[PTR_IND:%.*]], %vector.body ]
603 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
604 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x ptr> [ <ptr poison, ptr poison, ptr poison, ptr null>, %vector.ph ], [ [[TMP0:%.*]], %vector.body ]
605 ; CHECK-NEXT:    [[TMP0]] = getelementptr i8, ptr [[POINTER_PHI]], <4 x i64> <i64 0, i64 4, i64 8, i64 12>
606 ; CHECK-NEXT:    [[TMP1:%.*]] = add i64 [[INDEX]], 0
607 ; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x ptr> [[VECTOR_RECUR]], <4 x ptr> [[TMP0]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
608 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds ptr, ptr [[PTR]], i64 [[TMP1]]
609 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds ptr, ptr [[TMP3]], i32 0
610 ; CHECK-NEXT:    store <4 x ptr> [[TMP0]], ptr [[TMP4]], align 8
611 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
612 ; CHECK-NEXT:    [[PTR_IND]] = getelementptr i8, ptr [[POINTER_PHI]], i64 16
613 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1000
614 ; CHECK-NEXT:    br i1 [[TMP5]], label %middle.block, label %vector.body
615 ; CHECK:       middle.block:
616 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x ptr> [[TMP0]], i32 3
617 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x ptr> [[TMP0]], i32 2
618 ; CHECK-NEXT:    br i1 true
620 entry:
621   br label %loop
623 loop:
624   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
625   %ptr.iv = phi ptr [ %ptr, %entry ], [ %ptr.iv.next, %loop ]
626   %for.1 = phi ptr [ null, %entry ], [ %ptr.iv, %loop ]
627   %iv.next = add nuw nsw i64 %iv, 1
628   %gep.ptr = getelementptr inbounds ptr, ptr %ptr, i64 %iv
629   store ptr %ptr.iv, ptr %gep.ptr
630   %ptr.iv.next = getelementptr i32, ptr %ptr.iv, i64 1
631   %exitcond.not = icmp eq i64 %iv.next, 1000
632   br i1 %exitcond.not, label %exit, label %loop
634 exit:
635   ret ptr %for.1
638 ; In this test case, %USE_2_FORS uses 2 different fixed-order recurrences and
639 ; it needs to be sunk past the previous value for both recurrences.
640 define double @test_resinking_required(ptr %p, ptr noalias %a, ptr noalias %b) {
641 ; CHECK-LABEL: @test_resinking_required(
642 ; CHECK:       vector.body:
643 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %vector.ph ], [ [[INDEX_NEXT:%.*]], %vector.body ]
644 ; CHECK-NEXT:    [[VECTOR_RECUR:%.*]] = phi <4 x double> [ <double poison, double poison, double poison, double 0.000000e+00>, %vector.ph ], [ [[BROADCAST_SPLAT:%.*]], %vector.body ]
645 ; CHECK-NEXT:    [[VECTOR_RECUR1:%.*]] = phi <4 x double> [ <double poison, double poison, double poison, double 0.000000e+00>, %vector.ph ], [ [[BROADCAST_SPLAT4:%.*]], %vector.body ]
646 ; CHECK-NEXT:    [[VECTOR_RECUR2:%.*]] = phi <4 x double> [ <double poison, double poison, double poison, double 0.000000e+00>, %vector.ph ], [ [[TMP4:%.*]], %vector.body ]
647 ; CHECK-NEXT:    [[TMP0:%.*]] = load double, ptr %a, align 8
648 ; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x double> poison, double [[TMP0]], i64 0
649 ; CHECK-NEXT:    [[BROADCAST_SPLAT]] = shufflevector <4 x double> [[BROADCAST_SPLATINSERT]], <4 x double> poison, <4 x i32> zeroinitializer
650 ; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR]], <4 x double> [[BROADCAST_SPLAT]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
651 ; CHECK-NEXT:    [[TMP2:%.*]] = fdiv <4 x double> zeroinitializer, [[TMP1]]
652 ; CHECK-NEXT:    [[TMP3:%.*]] = load double, ptr %b, align 8
653 ; CHECK-NEXT:    [[BROADCAST_SPLATINSERT3:%.*]] = insertelement <4 x double> poison, double [[TMP3]], i64 0
654 ; CHECK-NEXT:    [[BROADCAST_SPLAT4]] = shufflevector <4 x double> [[BROADCAST_SPLATINSERT3]], <4 x double> poison, <4 x i32> zeroinitializer
655 ; CHECK-NEXT:    [[TMP4]] = shufflevector <4 x double> [[VECTOR_RECUR1]], <4 x double> [[BROADCAST_SPLAT4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
656 ; CHECK-NEXT:    [[TMP5:%.*]] = shufflevector <4 x double> [[VECTOR_RECUR2]], <4 x double> [[TMP4]], <4 x i32> <i32 3, i32 4, i32 5, i32 6>
657 ; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <4 x double> [[TMP2]], i32 3
658 ; CHECK-NEXT:    store double [[TMP6]], ptr [[P:%.*]], align 8
659 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
660 ; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 0
661 ; CHECK-NEXT:    br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP28:![0-9]+]]
662 ; CHECK:       middle.block:
663 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT:%.*]] = extractelement <4 x double> [[BROADCAST_SPLAT]], i32 3
664 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI:%.*]] = extractelement <4 x double> [[BROADCAST_SPLAT]], i32 2
665 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT5:%.*]] = extractelement <4 x double> [[BROADCAST_SPLAT4]], i32 3
666 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI6:%.*]] = extractelement <4 x double> [[BROADCAST_SPLAT4]], i32 2
667 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT9:%.*]] = extractelement <4 x double> [[TMP4]], i32 3
668 ; CHECK-NEXT:    [[VECTOR_RECUR_EXTRACT_FOR_PHI10:%.*]] = extractelement <4 x double> [[TMP4]], i32 2
669 ; CHECK-NEXT:    br i1 true, label %End, label %scalar.ph
671 Entry:
672   br label %Loop
674 Loop:
675   %for.1 = phi double [ %l1, %Loop ], [ 0.000000e+00, %Entry ]
676   %for.2 = phi double [ %l2, %Loop ], [ 0.000000e+00, %Entry ]
677   %for.3 = phi double [ %for.2, %Loop ], [ 0.000000e+00, %Entry ]
678   %iv = phi i64 [ %iv.next, %Loop ], [ 0, %Entry ]
679   %USE_2_FORS = fdiv double %for.3, %for.1
680   %div = fdiv double 0.000000e+00, %for.1
681   %l1 = load double, ptr %a, align 8
682   %iv.next= add nuw nsw i64 %iv, 1
683   %l2 = load double, ptr %b, align 8
684   store double %div, ptr %p, align 8
685   %cond = icmp eq i64 %iv.next, 0
686   br i1 %cond, label %End, label %Loop
688 End:
689   %res.1 = fadd double %for.1, %for.2
690   %res.2 = fadd double %res.1, %for.3
691   ret double %res.2