[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / vector-mul.ll
blobd9809281edbd968d0a18bfa56140eb4eb8715ea5
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
4 ; Check that instcombine rewrites multiply by a vector
5 ; of known constant power-of-2 elements with vector shift.
7 define <4 x i8> @Zero_i8(<4 x i8> %InVec)  {
8 ; CHECK-LABEL: @Zero_i8(
9 ; CHECK-NEXT:  entry:
10 ; CHECK-NEXT:    ret <4 x i8> zeroinitializer
12 entry:
13   %mul = mul <4 x i8> %InVec, <i8 0, i8 0, i8 0, i8 0>
14   ret <4 x i8> %mul
17 define <4 x i8> @Identity_i8(<4 x i8> %InVec)  {
18 ; CHECK-LABEL: @Identity_i8(
19 ; CHECK-NEXT:  entry:
20 ; CHECK-NEXT:    ret <4 x i8> [[INVEC:%.*]]
22 entry:
23   %mul = mul <4 x i8> %InVec, <i8 1, i8 1, i8 1, i8 1>
24   ret <4 x i8> %mul
27 define <4 x i8> @AddToSelf_i8(<4 x i8> %InVec)  {
28 ; CHECK-LABEL: @AddToSelf_i8(
29 ; CHECK-NEXT:  entry:
30 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 1, i8 1, i8 1, i8 1>
31 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
33 entry:
34   %mul = mul <4 x i8> %InVec, <i8 2, i8 2, i8 2, i8 2>
35   ret <4 x i8> %mul
38 define <4 x i8> @SplatPow2Test1_i8(<4 x i8> %InVec)  {
39 ; CHECK-LABEL: @SplatPow2Test1_i8(
40 ; CHECK-NEXT:  entry:
41 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 2, i8 2, i8 2, i8 2>
42 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
44 entry:
45   %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 4, i8 4>
46   ret <4 x i8> %mul
49 define <4 x i8> @SplatPow2Test2_i8(<4 x i8> %InVec)  {
50 ; CHECK-LABEL: @SplatPow2Test2_i8(
51 ; CHECK-NEXT:  entry:
52 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 3, i8 3, i8 3, i8 3>
53 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
55 entry:
56   %mul = mul <4 x i8> %InVec, <i8 8, i8 8, i8 8, i8 8>
57   ret <4 x i8> %mul
60 define <4 x i8> @MulTest1_i8(<4 x i8> %InVec)  {
61 ; CHECK-LABEL: @MulTest1_i8(
62 ; CHECK-NEXT:  entry:
63 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 0, i8 1, i8 2, i8 3>
64 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
66 entry:
67   %mul = mul <4 x i8> %InVec, <i8 1, i8 2, i8 4, i8 8>
68   ret <4 x i8> %mul
71 define <4 x i8> @MulTest2_i8(<4 x i8> %InVec)  {
72 ; CHECK-LABEL: @MulTest2_i8(
73 ; CHECK-NEXT:  entry:
74 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i8> [[INVEC:%.*]], <i8 3, i8 3, i8 3, i8 3>
75 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
77 entry:
78   %mul = mul <4 x i8> %InVec, <i8 3, i8 3, i8 3, i8 3>
79   ret <4 x i8> %mul
82 define <4 x i8> @MulTest3_i8(<4 x i8> %InVec)  {
83 ; CHECK-LABEL: @MulTest3_i8(
84 ; CHECK-NEXT:  entry:
85 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i8> [[INVEC:%.*]], <i8 2, i8 2, i8 1, i8 1>
86 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
88 entry:
89   %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 2, i8 2>
90   ret <4 x i8> %mul
93 define <4 x i8> @MulTest4_i8(<4 x i8> %InVec)  {
94 ; CHECK-LABEL: @MulTest4_i8(
95 ; CHECK-NEXT:  entry:
96 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i8> [[INVEC:%.*]], <i8 4, i8 4, i8 0, i8 1>
97 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
99 entry:
100   %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 0, i8 1>
101   ret <4 x i8> %mul
104 define <4 x i16> @Zero_i16(<4 x i16> %InVec)  {
105 ; CHECK-LABEL: @Zero_i16(
106 ; CHECK-NEXT:  entry:
107 ; CHECK-NEXT:    ret <4 x i16> zeroinitializer
109 entry:
110   %mul = mul <4 x i16> %InVec, <i16 0, i16 0, i16 0, i16 0>
111   ret <4 x i16> %mul
114 define <4 x i16> @Identity_i16(<4 x i16> %InVec)  {
115 ; CHECK-LABEL: @Identity_i16(
116 ; CHECK-NEXT:  entry:
117 ; CHECK-NEXT:    ret <4 x i16> [[INVEC:%.*]]
119 entry:
120   %mul = mul <4 x i16> %InVec, <i16 1, i16 1, i16 1, i16 1>
121   ret <4 x i16> %mul
124 define <4 x i16> @AddToSelf_i16(<4 x i16> %InVec)  {
125 ; CHECK-LABEL: @AddToSelf_i16(
126 ; CHECK-NEXT:  entry:
127 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 1, i16 1, i16 1, i16 1>
128 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
130 entry:
131   %mul = mul <4 x i16> %InVec, <i16 2, i16 2, i16 2, i16 2>
132   ret <4 x i16> %mul
135 define <4 x i16> @SplatPow2Test1_i16(<4 x i16> %InVec)  {
136 ; CHECK-LABEL: @SplatPow2Test1_i16(
137 ; CHECK-NEXT:  entry:
138 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 2, i16 2, i16 2, i16 2>
139 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
141 entry:
142   %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 4, i16 4>
143   ret <4 x i16> %mul
146 define <4 x i16> @SplatPow2Test2_i16(<4 x i16> %InVec)  {
147 ; CHECK-LABEL: @SplatPow2Test2_i16(
148 ; CHECK-NEXT:  entry:
149 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 3, i16 3, i16 3, i16 3>
150 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
152 entry:
153   %mul = mul <4 x i16> %InVec, <i16 8, i16 8, i16 8, i16 8>
154   ret <4 x i16> %mul
157 define <4 x i16> @MulTest1_i16(<4 x i16> %InVec)  {
158 ; CHECK-LABEL: @MulTest1_i16(
159 ; CHECK-NEXT:  entry:
160 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 0, i16 1, i16 2, i16 3>
161 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
163 entry:
164   %mul = mul <4 x i16> %InVec, <i16 1, i16 2, i16 4, i16 8>
165   ret <4 x i16> %mul
168 define <4 x i16> @MulTest2_i16(<4 x i16> %InVec)  {
169 ; CHECK-LABEL: @MulTest2_i16(
170 ; CHECK-NEXT:  entry:
171 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i16> [[INVEC:%.*]], <i16 3, i16 3, i16 3, i16 3>
172 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
174 entry:
175   %mul = mul <4 x i16> %InVec, <i16 3, i16 3, i16 3, i16 3>
176   ret <4 x i16> %mul
179 define <4 x i16> @MulTest3_i16(<4 x i16> %InVec)  {
180 ; CHECK-LABEL: @MulTest3_i16(
181 ; CHECK-NEXT:  entry:
182 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i16> [[INVEC:%.*]], <i16 2, i16 2, i16 1, i16 1>
183 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
185 entry:
186   %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 2, i16 2>
187   ret <4 x i16> %mul
190 define <4 x i16> @MulTest4_i16(<4 x i16> %InVec)  {
191 ; CHECK-LABEL: @MulTest4_i16(
192 ; CHECK-NEXT:  entry:
193 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i16> [[INVEC:%.*]], <i16 4, i16 4, i16 0, i16 2>
194 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
196 entry:
197   %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 0, i16 2>
198   ret <4 x i16> %mul
201 define <4 x i32> @Zero_i32(<4 x i32> %InVec)  {
202 ; CHECK-LABEL: @Zero_i32(
203 ; CHECK-NEXT:  entry:
204 ; CHECK-NEXT:    ret <4 x i32> zeroinitializer
206 entry:
207   %mul = mul <4 x i32> %InVec, <i32 0, i32 0, i32 0, i32 0>
208   ret <4 x i32> %mul
211 define <4 x i32> @Identity_i32(<4 x i32> %InVec)  {
212 ; CHECK-LABEL: @Identity_i32(
213 ; CHECK-NEXT:  entry:
214 ; CHECK-NEXT:    ret <4 x i32> [[INVEC:%.*]]
216 entry:
217   %mul = mul <4 x i32> %InVec, <i32 1, i32 1, i32 1, i32 1>
218   ret <4 x i32> %mul
221 define <4 x i32> @AddToSelf_i32(<4 x i32> %InVec)  {
222 ; CHECK-LABEL: @AddToSelf_i32(
223 ; CHECK-NEXT:  entry:
224 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 1, i32 1, i32 1, i32 1>
225 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
227 entry:
228   %mul = mul <4 x i32> %InVec, <i32 2, i32 2, i32 2, i32 2>
229   ret <4 x i32> %mul
232 define <4 x i32> @SplatPow2Test1_i32(<4 x i32> %InVec)  {
233 ; CHECK-LABEL: @SplatPow2Test1_i32(
234 ; CHECK-NEXT:  entry:
235 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 2, i32 2, i32 2, i32 2>
236 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
238 entry:
239   %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 4, i32 4>
240   ret <4 x i32> %mul
243 define <4 x i32> @SplatPow2Test2_i32(<4 x i32> %InVec)  {
244 ; CHECK-LABEL: @SplatPow2Test2_i32(
245 ; CHECK-NEXT:  entry:
246 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 3, i32 3, i32 3, i32 3>
247 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
249 entry:
250   %mul = mul <4 x i32> %InVec, <i32 8, i32 8, i32 8, i32 8>
251   ret <4 x i32> %mul
254 define <4 x i32> @MulTest1_i32(<4 x i32> %InVec)  {
255 ; CHECK-LABEL: @MulTest1_i32(
256 ; CHECK-NEXT:  entry:
257 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 0, i32 1, i32 2, i32 3>
258 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
260 entry:
261   %mul = mul <4 x i32> %InVec, <i32 1, i32 2, i32 4, i32 8>
262   ret <4 x i32> %mul
265 define <4 x i32> @MulTest2_i32(<4 x i32> %InVec)  {
266 ; CHECK-LABEL: @MulTest2_i32(
267 ; CHECK-NEXT:  entry:
268 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i32> [[INVEC:%.*]], <i32 3, i32 3, i32 3, i32 3>
269 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
271 entry:
272   %mul = mul <4 x i32> %InVec, <i32 3, i32 3, i32 3, i32 3>
273   ret <4 x i32> %mul
276 define <4 x i32> @MulTest3_i32(<4 x i32> %InVec)  {
277 ; CHECK-LABEL: @MulTest3_i32(
278 ; CHECK-NEXT:  entry:
279 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i32> [[INVEC:%.*]], <i32 2, i32 2, i32 1, i32 1>
280 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
282 entry:
283   %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 2, i32 2>
284   ret <4 x i32> %mul
287 define <4 x i32> @MulTest4_i32(<4 x i32> %InVec)  {
288 ; CHECK-LABEL: @MulTest4_i32(
289 ; CHECK-NEXT:  entry:
290 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i32> [[INVEC:%.*]], <i32 4, i32 4, i32 0, i32 1>
291 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
293 entry:
294   %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 0, i32 1>
295   ret <4 x i32> %mul
298 define <4 x i64> @Zero_i64(<4 x i64> %InVec)  {
299 ; CHECK-LABEL: @Zero_i64(
300 ; CHECK-NEXT:  entry:
301 ; CHECK-NEXT:    ret <4 x i64> zeroinitializer
303 entry:
304   %mul = mul <4 x i64> %InVec, <i64 0, i64 0, i64 0, i64 0>
305   ret <4 x i64> %mul
308 define <4 x i64> @Identity_i64(<4 x i64> %InVec)  {
309 ; CHECK-LABEL: @Identity_i64(
310 ; CHECK-NEXT:  entry:
311 ; CHECK-NEXT:    ret <4 x i64> [[INVEC:%.*]]
313 entry:
314   %mul = mul <4 x i64> %InVec, <i64 1, i64 1, i64 1, i64 1>
315   ret <4 x i64> %mul
318 define <4 x i64> @AddToSelf_i64(<4 x i64> %InVec)  {
319 ; CHECK-LABEL: @AddToSelf_i64(
320 ; CHECK-NEXT:  entry:
321 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 1, i64 1, i64 1, i64 1>
322 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
324 entry:
325   %mul = mul <4 x i64> %InVec, <i64 2, i64 2, i64 2, i64 2>
326   ret <4 x i64> %mul
329 define <4 x i64> @SplatPow2Test1_i64(<4 x i64> %InVec)  {
330 ; CHECK-LABEL: @SplatPow2Test1_i64(
331 ; CHECK-NEXT:  entry:
332 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 2, i64 2, i64 2, i64 2>
333 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
335 entry:
336   %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 4, i64 4>
337   ret <4 x i64> %mul
340 define <4 x i64> @SplatPow2Test2_i64(<4 x i64> %InVec)  {
341 ; CHECK-LABEL: @SplatPow2Test2_i64(
342 ; CHECK-NEXT:  entry:
343 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 3, i64 3, i64 3, i64 3>
344 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
346 entry:
347   %mul = mul <4 x i64> %InVec, <i64 8, i64 8, i64 8, i64 8>
348   ret <4 x i64> %mul
351 define <4 x i64> @MulTest1_i64(<4 x i64> %InVec)  {
352 ; CHECK-LABEL: @MulTest1_i64(
353 ; CHECK-NEXT:  entry:
354 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 0, i64 1, i64 2, i64 3>
355 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
357 entry:
358   %mul = mul <4 x i64> %InVec, <i64 1, i64 2, i64 4, i64 8>
359   ret <4 x i64> %mul
362 define <4 x i64> @MulTest2_i64(<4 x i64> %InVec)  {
363 ; CHECK-LABEL: @MulTest2_i64(
364 ; CHECK-NEXT:  entry:
365 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i64> [[INVEC:%.*]], <i64 3, i64 3, i64 3, i64 3>
366 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
368 entry:
369   %mul = mul <4 x i64> %InVec, <i64 3, i64 3, i64 3, i64 3>
370   ret <4 x i64> %mul
373 define <4 x i64> @MulTest3_i64(<4 x i64> %InVec)  {
374 ; CHECK-LABEL: @MulTest3_i64(
375 ; CHECK-NEXT:  entry:
376 ; CHECK-NEXT:    [[MUL:%.*]] = shl <4 x i64> [[INVEC:%.*]], <i64 2, i64 2, i64 1, i64 1>
377 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
379 entry:
380   %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 2, i64 2>
381   ret <4 x i64> %mul
384 define <4 x i64> @MulTest4_i64(<4 x i64> %InVec)  {
385 ; CHECK-LABEL: @MulTest4_i64(
386 ; CHECK-NEXT:  entry:
387 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i64> [[INVEC:%.*]], <i64 4, i64 4, i64 0, i64 1>
388 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
390 entry:
391   %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 0, i64 1>
392   ret <4 x i64> %mul
395 ; Test also that the following rewriting rule works with vectors
396 ; of integers as well:
397 ;   ((X << C1)*C2) == (X * (C2 << C1))
399 define <4 x i8> @ShiftMulTest1(<4 x i8> %InVec) {
400 ; CHECK-LABEL: @ShiftMulTest1(
401 ; CHECK-NEXT:  entry:
402 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i8> [[INVEC:%.*]], <i8 12, i8 12, i8 12, i8 12>
403 ; CHECK-NEXT:    ret <4 x i8> [[MUL]]
405 entry:
406   %shl = shl <4 x i8> %InVec, <i8 2, i8 2, i8 2, i8 2>
407   %mul = mul <4 x i8> %shl, <i8 3, i8 3, i8 3, i8 3>
408   ret <4 x i8> %mul
411 define <4 x i16> @ShiftMulTest2(<4 x i16> %InVec) {
412 ; CHECK-LABEL: @ShiftMulTest2(
413 ; CHECK-NEXT:  entry:
414 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i16> [[INVEC:%.*]], <i16 12, i16 12, i16 12, i16 12>
415 ; CHECK-NEXT:    ret <4 x i16> [[MUL]]
417 entry:
418   %shl = shl <4 x i16> %InVec, <i16 2, i16 2, i16 2, i16 2>
419   %mul = mul <4 x i16> %shl, <i16 3, i16 3, i16 3, i16 3>
420   ret <4 x i16> %mul
423 define <4 x i32> @ShiftMulTest3(<4 x i32> %InVec) {
424 ; CHECK-LABEL: @ShiftMulTest3(
425 ; CHECK-NEXT:  entry:
426 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i32> [[INVEC:%.*]], <i32 12, i32 12, i32 12, i32 12>
427 ; CHECK-NEXT:    ret <4 x i32> [[MUL]]
429 entry:
430   %shl = shl <4 x i32> %InVec, <i32 2, i32 2, i32 2, i32 2>
431   %mul = mul <4 x i32> %shl, <i32 3, i32 3, i32 3, i32 3>
432   ret <4 x i32> %mul
435 define <4 x i64> @ShiftMulTest4(<4 x i64> %InVec) {
436 ; CHECK-LABEL: @ShiftMulTest4(
437 ; CHECK-NEXT:  entry:
438 ; CHECK-NEXT:    [[MUL:%.*]] = mul <4 x i64> [[INVEC:%.*]], <i64 12, i64 12, i64 12, i64 12>
439 ; CHECK-NEXT:    ret <4 x i64> [[MUL]]
441 entry:
442   %shl = shl <4 x i64> %InVec, <i64 2, i64 2, i64 2, i64 2>
443   %mul = mul <4 x i64> %shl, <i64 3, i64 3, i64 3, i64 3>
444   ret <4 x i64> %mul