1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=slp-vectorizer %s --mtriple=aarch64-- | FileCheck %s
4 ; This test checks whether load-zext-add and load-add reduction patterns
5 ; get vectorized by SLP.
7 define i64 @red_zext_ld_2xi64(ptr %ptr) {
8 ; CHECK-LABEL: @red_zext_ld_2xi64(
10 ; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[PTR:%.*]], align 1
11 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[LD0]] to i64
12 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
13 ; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[GEP]], align 1
14 ; CHECK-NEXT: [[ZEXT_1:%.*]] = zext i8 [[LD1]] to i64
15 ; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[ZEXT]], [[ZEXT_1]]
16 ; CHECK-NEXT: ret i64 [[ADD_1]]
19 %ld0 = load i8, ptr %ptr
20 %zext = zext i8 %ld0 to i64
21 %gep = getelementptr inbounds i8, ptr %ptr, i64 1
22 %ld1 = load i8, ptr %gep
23 %zext.1 = zext i8 %ld1 to i64
24 %add.1 = add nuw nsw i64 %zext, %zext.1
28 define i64 @red_zext_ld_4xi64(ptr %ptr) {
29 ; CHECK-LABEL: @red_zext_ld_4xi64(
31 ; CHECK-NEXT: [[LD0:%.*]] = load i8, ptr [[PTR:%.*]], align 1
32 ; CHECK-NEXT: [[ZEXT:%.*]] = zext i8 [[LD0]] to i64
33 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 1
34 ; CHECK-NEXT: [[LD1:%.*]] = load i8, ptr [[GEP]], align 1
35 ; CHECK-NEXT: [[ZEXT_1:%.*]] = zext i8 [[LD1]] to i64
36 ; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[ZEXT]], [[ZEXT_1]]
37 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 2
38 ; CHECK-NEXT: [[LD2:%.*]] = load i8, ptr [[GEP_1]], align 1
39 ; CHECK-NEXT: [[ZEXT_2:%.*]] = zext i8 [[LD2]] to i64
40 ; CHECK-NEXT: [[ADD_2:%.*]] = add nuw nsw i64 [[ADD_1]], [[ZEXT_2]]
41 ; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64 3
42 ; CHECK-NEXT: [[LD3:%.*]] = load i8, ptr [[GEP_2]], align 1
43 ; CHECK-NEXT: [[ZEXT_3:%.*]] = zext i8 [[LD3]] to i64
44 ; CHECK-NEXT: [[ADD_3:%.*]] = add nuw nsw i64 [[ADD_2]], [[ZEXT_3]]
45 ; CHECK-NEXT: ret i64 [[ADD_3]]
48 %ld0 = load i8, ptr %ptr
49 %zext = zext i8 %ld0 to i64
50 %gep = getelementptr inbounds i8, ptr %ptr, i64 1
51 %ld1 = load i8, ptr %gep
52 %zext.1 = zext i8 %ld1 to i64
53 %add.1 = add nuw nsw i64 %zext, %zext.1
54 %gep.1 = getelementptr inbounds i8, ptr %ptr, i64 2
55 %ld2 = load i8, ptr %gep.1
56 %zext.2 = zext i8 %ld2 to i64
57 %add.2 = add nuw nsw i64 %add.1, %zext.2
58 %gep.2 = getelementptr inbounds i8, ptr %ptr, i64 3
59 %ld3 = load i8, ptr %gep.2
60 %zext.3 = zext i8 %ld3 to i64
61 %add.3 = add nuw nsw i64 %add.2, %zext.3
65 define i64 @red_zext_ld_8xi64(ptr %ptr) {
66 ; CHECK-LABEL: @red_zext_ld_8xi64(
68 ; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr [[PTR:%.*]], align 1
69 ; CHECK-NEXT: [[TMP1:%.*]] = zext <8 x i8> [[TMP0]] to <8 x i64>
70 ; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> [[TMP1]])
71 ; CHECK-NEXT: ret i64 [[TMP2]]
74 %ld0 = load i8, ptr %ptr
75 %zext = zext i8 %ld0 to i64
76 %gep = getelementptr inbounds i8, ptr %ptr, i64 1
77 %ld1 = load i8, ptr %gep
78 %zext.1 = zext i8 %ld1 to i64
79 %add.1 = add nuw nsw i64 %zext, %zext.1
80 %gep.1 = getelementptr inbounds i8, ptr %ptr, i64 2
81 %ld2 = load i8, ptr %gep.1
82 %zext.2 = zext i8 %ld2 to i64
83 %add.2 = add nuw nsw i64 %add.1, %zext.2
84 %gep.2 = getelementptr inbounds i8, ptr %ptr, i64 3
85 %ld3 = load i8, ptr %gep.2
86 %zext.3 = zext i8 %ld3 to i64
87 %add.3 = add nuw nsw i64 %add.2, %zext.3
88 %gep.3 = getelementptr inbounds i8, ptr %ptr, i64 4
89 %ld4 = load i8, ptr %gep.3
90 %zext.4 = zext i8 %ld4 to i64
91 %add.4 = add nuw nsw i64 %add.3, %zext.4
92 %gep.4 = getelementptr inbounds i8, ptr %ptr, i64 5
93 %ld5 = load i8, ptr %gep.4
94 %zext.5 = zext i8 %ld5 to i64
95 %add.5 = add nuw nsw i64 %add.4, %zext.5
96 %gep.5 = getelementptr inbounds i8, ptr %ptr, i64 6
97 %ld6 = load i8, ptr %gep.5
98 %zext.6 = zext i8 %ld6 to i64
99 %add.6 = add nuw nsw i64 %add.5, %zext.6
100 %gep.6 = getelementptr inbounds i8, ptr %ptr, i64 7
101 %ld7 = load i8, ptr %gep.6
102 %zext.7 = zext i8 %ld7 to i64
103 %add.7 = add nuw nsw i64 %add.6, %zext.7
107 define i64 @red_zext_ld_16xi64(ptr %ptr) {
108 ; CHECK-LABEL: @red_zext_ld_16xi64(
110 ; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr [[PTR:%.*]], align 1
111 ; CHECK-NEXT: [[TMP1:%.*]] = zext <16 x i8> [[TMP0]] to <16 x i64>
112 ; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> [[TMP1]])
113 ; CHECK-NEXT: ret i64 [[TMP2]]
116 %ld0 = load i8, ptr %ptr
117 %zext = zext i8 %ld0 to i64
118 %gep = getelementptr inbounds i8, ptr %ptr, i64 1
119 %ld1 = load i8, ptr %gep
120 %zext.1 = zext i8 %ld1 to i64
121 %add.1 = add nuw nsw i64 %zext, %zext.1
122 %gep.1 = getelementptr inbounds i8, ptr %ptr, i64 2
123 %ld2 = load i8, ptr %gep.1
124 %zext.2 = zext i8 %ld2 to i64
125 %add.2 = add nuw nsw i64 %add.1, %zext.2
126 %gep.2 = getelementptr inbounds i8, ptr %ptr, i64 3
127 %ld3 = load i8, ptr %gep.2
128 %zext.3 = zext i8 %ld3 to i64
129 %add.3 = add nuw nsw i64 %add.2, %zext.3
130 %gep.3 = getelementptr inbounds i8, ptr %ptr, i64 4
131 %ld4 = load i8, ptr %gep.3
132 %zext.4 = zext i8 %ld4 to i64
133 %add.4 = add nuw nsw i64 %add.3, %zext.4
134 %gep.4 = getelementptr inbounds i8, ptr %ptr, i64 5
135 %ld5 = load i8, ptr %gep.4
136 %zext.5 = zext i8 %ld5 to i64
137 %add.5 = add nuw nsw i64 %add.4, %zext.5
138 %gep.5 = getelementptr inbounds i8, ptr %ptr, i64 6
139 %ld6 = load i8, ptr %gep.5
140 %zext.6 = zext i8 %ld6 to i64
141 %add.6 = add nuw nsw i64 %add.5, %zext.6
142 %gep.6 = getelementptr inbounds i8, ptr %ptr, i64 7
143 %ld7 = load i8, ptr %gep.6
144 %zext.7 = zext i8 %ld7 to i64
145 %add.7 = add nuw nsw i64 %add.6, %zext.7
146 %gep.7 = getelementptr inbounds i8, ptr %ptr, i64 8
147 %ld8 = load i8, ptr %gep.7
148 %zext.8 = zext i8 %ld8 to i64
149 %add.8 = add nuw nsw i64 %add.7, %zext.8
150 %gep.8 = getelementptr inbounds i8, ptr %ptr, i64 9
151 %ld9 = load i8, ptr %gep.8
152 %zext.9 = zext i8 %ld9 to i64
153 %add.9 = add nuw nsw i64 %add.8, %zext.9
154 %gep.9 = getelementptr inbounds i8, ptr %ptr, i64 10
155 %ld10 = load i8, ptr %gep.9
156 %zext.10 = zext i8 %ld10 to i64
157 %add.10 = add nuw nsw i64 %add.9, %zext.10
158 %gep.10 = getelementptr inbounds i8, ptr %ptr, i64 11
159 %ld11 = load i8, ptr %gep.10
160 %zext.11 = zext i8 %ld11 to i64
161 %add.11 = add nuw nsw i64 %add.10, %zext.11
162 %gep.11 = getelementptr inbounds i8, ptr %ptr, i64 12
163 %ld12 = load i8, ptr %gep.11
164 %zext.12 = zext i8 %ld12 to i64
165 %add.12 = add nuw nsw i64 %add.11, %zext.12
166 %gep.12 = getelementptr inbounds i8, ptr %ptr, i64 13
167 %ld13 = load i8, ptr %gep.12
168 %zext.13 = zext i8 %ld13 to i64
169 %add.13 = add nuw nsw i64 %add.12, %zext.13
170 %gep.13 = getelementptr inbounds i8, ptr %ptr, i64 14
171 %ld14 = load i8, ptr %gep.13
172 %zext.14 = zext i8 %ld14 to i64
173 %add.14 = add nuw nsw i64 %add.13, %zext.14
174 %gep.14 = getelementptr inbounds i8, ptr %ptr, i64 15
175 %ld15 = load i8, ptr %gep.14
176 %zext.15 = zext i8 %ld15 to i64
177 %add.15 = add nuw nsw i64 %add.14, %zext.15
183 define i64 @red_ld_2xi64(ptr %ptr) {
184 ; CHECK-LABEL: @red_ld_2xi64(
186 ; CHECK-NEXT: [[LD0:%.*]] = load i64, ptr [[PTR:%.*]], align 8
187 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[PTR]], i64 1
188 ; CHECK-NEXT: [[LD1:%.*]] = load i64, ptr [[GEP]], align 8
189 ; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i64 [[LD0]], [[LD1]]
190 ; CHECK-NEXT: ret i64 [[ADD_1]]
193 %ld0 = load i64, ptr %ptr
194 %gep = getelementptr inbounds i64, ptr %ptr, i64 1
195 %ld1 = load i64, ptr %gep
196 %add.1 = add nuw nsw i64 %ld0, %ld1
200 define i64 @red_ld_4xi64(ptr %ptr) {
201 ; CHECK-LABEL: @red_ld_4xi64(
203 ; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i64>, ptr [[PTR:%.*]], align 8
204 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.add.v4i64(<4 x i64> [[TMP0]])
205 ; CHECK-NEXT: ret i64 [[TMP1]]
208 %ld0 = load i64, ptr %ptr
209 %gep = getelementptr inbounds i64, ptr %ptr, i64 1
210 %ld1 = load i64, ptr %gep
211 %add.1 = add nuw nsw i64 %ld0, %ld1
212 %gep.1 = getelementptr inbounds i64, ptr %ptr, i64 2
213 %ld2 = load i64, ptr %gep.1
214 %add.2 = add nuw nsw i64 %add.1, %ld2
215 %gep.2 = getelementptr inbounds i64, ptr %ptr, i64 3
216 %ld3 = load i64, ptr %gep.2
217 %add.3 = add nuw nsw i64 %add.2, %ld3
221 define i64 @red_ld_8xi64(ptr %ptr) {
222 ; CHECK-LABEL: @red_ld_8xi64(
224 ; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, ptr [[PTR:%.*]], align 8
225 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> [[TMP0]])
226 ; CHECK-NEXT: ret i64 [[TMP1]]
229 %ld0 = load i64, ptr %ptr
230 %gep = getelementptr inbounds i64, ptr %ptr, i64 1
231 %ld1 = load i64, ptr %gep
232 %add.1 = add nuw nsw i64 %ld0, %ld1
233 %gep.1 = getelementptr inbounds i64, ptr %ptr, i64 2
234 %ld2 = load i64, ptr %gep.1
235 %add.2 = add nuw nsw i64 %add.1, %ld2
236 %gep.2 = getelementptr inbounds i64, ptr %ptr, i64 3
237 %ld3 = load i64, ptr %gep.2
238 %add.3 = add nuw nsw i64 %add.2, %ld3
239 %gep.3 = getelementptr inbounds i64, ptr %ptr, i64 4
240 %ld4 = load i64, ptr %gep.3
241 %add.4 = add nuw nsw i64 %add.3, %ld4
242 %gep.4 = getelementptr inbounds i64, ptr %ptr, i64 5
243 %ld5 = load i64, ptr %gep.4
244 %add.5 = add nuw nsw i64 %add.4, %ld5
245 %gep.5 = getelementptr inbounds i64, ptr %ptr, i64 6
246 %ld6 = load i64, ptr %gep.5
247 %add.6 = add nuw nsw i64 %add.5, %ld6
248 %gep.6 = getelementptr inbounds i64, ptr %ptr, i64 7
249 %ld7 = load i64, ptr %gep.6
250 %add.7 = add nuw nsw i64 %add.6, %ld7
254 define i64 @red_ld_16xi64(ptr %ptr) {
255 ; CHECK-LABEL: @red_ld_16xi64(
257 ; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i64>, ptr [[PTR:%.*]], align 8
258 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vector.reduce.add.v16i64(<16 x i64> [[TMP0]])
259 ; CHECK-NEXT: ret i64 [[TMP1]]
262 %ld0 = load i64, ptr %ptr
263 %gep = getelementptr inbounds i64, ptr %ptr, i64 1
264 %ld1 = load i64, ptr %gep
265 %add.1 = add nuw nsw i64 %ld0, %ld1
266 %gep.1 = getelementptr inbounds i64, ptr %ptr, i64 2
267 %ld2 = load i64, ptr %gep.1
268 %add.2 = add nuw nsw i64 %add.1, %ld2
269 %gep.2 = getelementptr inbounds i64, ptr %ptr, i64 3
270 %ld3 = load i64, ptr %gep.2
271 %add.3 = add nuw nsw i64 %add.2, %ld3
272 %gep.3 = getelementptr inbounds i64, ptr %ptr, i64 4
273 %ld4 = load i64, ptr %gep.3
274 %add.4 = add nuw nsw i64 %add.3, %ld4
275 %gep.4 = getelementptr inbounds i64, ptr %ptr, i64 5
276 %ld5 = load i64, ptr %gep.4
277 %add.5 = add nuw nsw i64 %add.4, %ld5
278 %gep.5 = getelementptr inbounds i64, ptr %ptr, i64 6
279 %ld6 = load i64, ptr %gep.5
280 %add.6 = add nuw nsw i64 %add.5, %ld6
281 %gep.6 = getelementptr inbounds i64, ptr %ptr, i64 7
282 %ld7 = load i64, ptr %gep.6
283 %add.7 = add nuw nsw i64 %add.6, %ld7
284 %gep.7 = getelementptr inbounds i64, ptr %ptr, i64 8
285 %ld8 = load i64, ptr %gep.7
286 %add.8 = add nuw nsw i64 %add.7, %ld8
287 %gep.8 = getelementptr inbounds i64, ptr %ptr, i64 9
288 %ld9 = load i64, ptr %gep.8
289 %add.9 = add nuw nsw i64 %add.8, %ld9
290 %gep.9 = getelementptr inbounds i64, ptr %ptr, i64 10
291 %ld10 = load i64, ptr %gep.9
292 %add.10 = add nuw nsw i64 %add.9, %ld10
293 %gep.10 = getelementptr inbounds i64, ptr %ptr, i64 11
294 %ld11 = load i64, ptr %gep.10
295 %add.11 = add nuw nsw i64 %add.10, %ld11
296 %gep.11 = getelementptr inbounds i64, ptr %ptr, i64 12
297 %ld12 = load i64, ptr %gep.11
298 %add.12 = add nuw nsw i64 %add.11, %ld12
299 %gep.12 = getelementptr inbounds i64, ptr %ptr, i64 13
300 %ld13 = load i64, ptr %gep.12
301 %add.13 = add nuw nsw i64 %add.12, %ld13
302 %gep.13 = getelementptr inbounds i64, ptr %ptr, i64 14
303 %ld14 = load i64, ptr %gep.13
304 %add.14 = add nuw nsw i64 %add.13, %ld14
305 %gep.14 = getelementptr inbounds i64, ptr %ptr, i64 15
306 %ld15 = load i64, ptr %gep.14
307 %add.15 = add nuw nsw i64 %add.14, %ld15