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(
10 ; CHECK-NEXT: ret <4 x i8> zeroinitializer
13 %mul = mul <4 x i8> %InVec, <i8 0, i8 0, i8 0, i8 0>
17 define <4 x i8> @Identity_i8(<4 x i8> %InVec) {
18 ; CHECK-LABEL: @Identity_i8(
20 ; CHECK-NEXT: ret <4 x i8> [[INVEC:%.*]]
23 %mul = mul <4 x i8> %InVec, <i8 1, i8 1, i8 1, i8 1>
27 define <4 x i8> @AddToSelf_i8(<4 x i8> %InVec) {
28 ; CHECK-LABEL: @AddToSelf_i8(
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]]
34 %mul = mul <4 x i8> %InVec, <i8 2, i8 2, i8 2, i8 2>
38 define <4 x i8> @SplatPow2Test1_i8(<4 x i8> %InVec) {
39 ; CHECK-LABEL: @SplatPow2Test1_i8(
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]]
45 %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 4, i8 4>
49 define <4 x i8> @SplatPow2Test2_i8(<4 x i8> %InVec) {
50 ; CHECK-LABEL: @SplatPow2Test2_i8(
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]]
56 %mul = mul <4 x i8> %InVec, <i8 8, i8 8, i8 8, i8 8>
60 define <4 x i8> @MulTest1_i8(<4 x i8> %InVec) {
61 ; CHECK-LABEL: @MulTest1_i8(
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]]
67 %mul = mul <4 x i8> %InVec, <i8 1, i8 2, i8 4, i8 8>
71 define <4 x i8> @MulTest2_i8(<4 x i8> %InVec) {
72 ; CHECK-LABEL: @MulTest2_i8(
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]]
78 %mul = mul <4 x i8> %InVec, <i8 3, i8 3, i8 3, i8 3>
82 define <4 x i8> @MulTest3_i8(<4 x i8> %InVec) {
83 ; CHECK-LABEL: @MulTest3_i8(
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]]
89 %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 2, i8 2>
93 define <4 x i8> @MulTest4_i8(<4 x i8> %InVec) {
94 ; CHECK-LABEL: @MulTest4_i8(
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]]
100 %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 0, i8 1>
104 define <4 x i16> @Zero_i16(<4 x i16> %InVec) {
105 ; CHECK-LABEL: @Zero_i16(
107 ; CHECK-NEXT: ret <4 x i16> zeroinitializer
110 %mul = mul <4 x i16> %InVec, <i16 0, i16 0, i16 0, i16 0>
114 define <4 x i16> @Identity_i16(<4 x i16> %InVec) {
115 ; CHECK-LABEL: @Identity_i16(
117 ; CHECK-NEXT: ret <4 x i16> [[INVEC:%.*]]
120 %mul = mul <4 x i16> %InVec, <i16 1, i16 1, i16 1, i16 1>
124 define <4 x i16> @AddToSelf_i16(<4 x i16> %InVec) {
125 ; CHECK-LABEL: @AddToSelf_i16(
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]]
131 %mul = mul <4 x i16> %InVec, <i16 2, i16 2, i16 2, i16 2>
135 define <4 x i16> @SplatPow2Test1_i16(<4 x i16> %InVec) {
136 ; CHECK-LABEL: @SplatPow2Test1_i16(
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]]
142 %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 4, i16 4>
146 define <4 x i16> @SplatPow2Test2_i16(<4 x i16> %InVec) {
147 ; CHECK-LABEL: @SplatPow2Test2_i16(
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]]
153 %mul = mul <4 x i16> %InVec, <i16 8, i16 8, i16 8, i16 8>
157 define <4 x i16> @MulTest1_i16(<4 x i16> %InVec) {
158 ; CHECK-LABEL: @MulTest1_i16(
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]]
164 %mul = mul <4 x i16> %InVec, <i16 1, i16 2, i16 4, i16 8>
168 define <4 x i16> @MulTest2_i16(<4 x i16> %InVec) {
169 ; CHECK-LABEL: @MulTest2_i16(
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]]
175 %mul = mul <4 x i16> %InVec, <i16 3, i16 3, i16 3, i16 3>
179 define <4 x i16> @MulTest3_i16(<4 x i16> %InVec) {
180 ; CHECK-LABEL: @MulTest3_i16(
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]]
186 %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 2, i16 2>
190 define <4 x i16> @MulTest4_i16(<4 x i16> %InVec) {
191 ; CHECK-LABEL: @MulTest4_i16(
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]]
197 %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 0, i16 2>
201 define <4 x i32> @Zero_i32(<4 x i32> %InVec) {
202 ; CHECK-LABEL: @Zero_i32(
204 ; CHECK-NEXT: ret <4 x i32> zeroinitializer
207 %mul = mul <4 x i32> %InVec, <i32 0, i32 0, i32 0, i32 0>
211 define <4 x i32> @Identity_i32(<4 x i32> %InVec) {
212 ; CHECK-LABEL: @Identity_i32(
214 ; CHECK-NEXT: ret <4 x i32> [[INVEC:%.*]]
217 %mul = mul <4 x i32> %InVec, <i32 1, i32 1, i32 1, i32 1>
221 define <4 x i32> @AddToSelf_i32(<4 x i32> %InVec) {
222 ; CHECK-LABEL: @AddToSelf_i32(
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]]
228 %mul = mul <4 x i32> %InVec, <i32 2, i32 2, i32 2, i32 2>
232 define <4 x i32> @SplatPow2Test1_i32(<4 x i32> %InVec) {
233 ; CHECK-LABEL: @SplatPow2Test1_i32(
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]]
239 %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 4, i32 4>
243 define <4 x i32> @SplatPow2Test2_i32(<4 x i32> %InVec) {
244 ; CHECK-LABEL: @SplatPow2Test2_i32(
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]]
250 %mul = mul <4 x i32> %InVec, <i32 8, i32 8, i32 8, i32 8>
254 define <4 x i32> @MulTest1_i32(<4 x i32> %InVec) {
255 ; CHECK-LABEL: @MulTest1_i32(
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]]
261 %mul = mul <4 x i32> %InVec, <i32 1, i32 2, i32 4, i32 8>
265 define <4 x i32> @MulTest2_i32(<4 x i32> %InVec) {
266 ; CHECK-LABEL: @MulTest2_i32(
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]]
272 %mul = mul <4 x i32> %InVec, <i32 3, i32 3, i32 3, i32 3>
276 define <4 x i32> @MulTest3_i32(<4 x i32> %InVec) {
277 ; CHECK-LABEL: @MulTest3_i32(
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]]
283 %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 2, i32 2>
287 define <4 x i32> @MulTest4_i32(<4 x i32> %InVec) {
288 ; CHECK-LABEL: @MulTest4_i32(
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]]
294 %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 0, i32 1>
298 define <4 x i64> @Zero_i64(<4 x i64> %InVec) {
299 ; CHECK-LABEL: @Zero_i64(
301 ; CHECK-NEXT: ret <4 x i64> zeroinitializer
304 %mul = mul <4 x i64> %InVec, <i64 0, i64 0, i64 0, i64 0>
308 define <4 x i64> @Identity_i64(<4 x i64> %InVec) {
309 ; CHECK-LABEL: @Identity_i64(
311 ; CHECK-NEXT: ret <4 x i64> [[INVEC:%.*]]
314 %mul = mul <4 x i64> %InVec, <i64 1, i64 1, i64 1, i64 1>
318 define <4 x i64> @AddToSelf_i64(<4 x i64> %InVec) {
319 ; CHECK-LABEL: @AddToSelf_i64(
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]]
325 %mul = mul <4 x i64> %InVec, <i64 2, i64 2, i64 2, i64 2>
329 define <4 x i64> @SplatPow2Test1_i64(<4 x i64> %InVec) {
330 ; CHECK-LABEL: @SplatPow2Test1_i64(
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]]
336 %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 4, i64 4>
340 define <4 x i64> @SplatPow2Test2_i64(<4 x i64> %InVec) {
341 ; CHECK-LABEL: @SplatPow2Test2_i64(
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]]
347 %mul = mul <4 x i64> %InVec, <i64 8, i64 8, i64 8, i64 8>
351 define <4 x i64> @MulTest1_i64(<4 x i64> %InVec) {
352 ; CHECK-LABEL: @MulTest1_i64(
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]]
358 %mul = mul <4 x i64> %InVec, <i64 1, i64 2, i64 4, i64 8>
362 define <4 x i64> @MulTest2_i64(<4 x i64> %InVec) {
363 ; CHECK-LABEL: @MulTest2_i64(
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]]
369 %mul = mul <4 x i64> %InVec, <i64 3, i64 3, i64 3, i64 3>
373 define <4 x i64> @MulTest3_i64(<4 x i64> %InVec) {
374 ; CHECK-LABEL: @MulTest3_i64(
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]]
380 %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 2, i64 2>
384 define <4 x i64> @MulTest4_i64(<4 x i64> %InVec) {
385 ; CHECK-LABEL: @MulTest4_i64(
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]]
391 %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 0, i64 1>
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(
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]]
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>
411 define <4 x i16> @ShiftMulTest2(<4 x i16> %InVec) {
412 ; CHECK-LABEL: @ShiftMulTest2(
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]]
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>
423 define <4 x i32> @ShiftMulTest3(<4 x i32> %InVec) {
424 ; CHECK-LABEL: @ShiftMulTest3(
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]]
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>
435 define <4 x i64> @ShiftMulTest4(<4 x i64> %InVec) {
436 ; CHECK-LABEL: @ShiftMulTest4(
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]]
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>