1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; Check that instcombine rewrites multiply by a vector
5; of known constant power-of-2 elements with vector shift.
6
7define <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
11;
12entry:
13  %mul = mul <4 x i8> %InVec, <i8 0, i8 0, i8 0, i8 0>
14  ret <4 x i8> %mul
15}
16
17define <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:%.*]]
21;
22entry:
23  %mul = mul <4 x i8> %InVec, <i8 1, i8 1, i8 1, i8 1>
24  ret <4 x i8> %mul
25}
26
27define <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]]
32;
33entry:
34  %mul = mul <4 x i8> %InVec, <i8 2, i8 2, i8 2, i8 2>
35  ret <4 x i8> %mul
36}
37
38define <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]]
43;
44entry:
45  %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 4, i8 4>
46  ret <4 x i8> %mul
47}
48
49define <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]]
54;
55entry:
56  %mul = mul <4 x i8> %InVec, <i8 8, i8 8, i8 8, i8 8>
57  ret <4 x i8> %mul
58}
59
60define <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]]
65;
66entry:
67  %mul = mul <4 x i8> %InVec, <i8 1, i8 2, i8 4, i8 8>
68  ret <4 x i8> %mul
69}
70
71define <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]]
76;
77entry:
78  %mul = mul <4 x i8> %InVec, <i8 3, i8 3, i8 3, i8 3>
79  ret <4 x i8> %mul
80}
81
82define <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]]
87;
88entry:
89  %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 2, i8 2>
90  ret <4 x i8> %mul
91}
92
93define <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]]
98;
99entry:
100  %mul = mul <4 x i8> %InVec, <i8 4, i8 4, i8 0, i8 1>
101  ret <4 x i8> %mul
102}
103
104define <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
108;
109entry:
110  %mul = mul <4 x i16> %InVec, <i16 0, i16 0, i16 0, i16 0>
111  ret <4 x i16> %mul
112}
113
114define <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:%.*]]
118;
119entry:
120  %mul = mul <4 x i16> %InVec, <i16 1, i16 1, i16 1, i16 1>
121  ret <4 x i16> %mul
122}
123
124define <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]]
129;
130entry:
131  %mul = mul <4 x i16> %InVec, <i16 2, i16 2, i16 2, i16 2>
132  ret <4 x i16> %mul
133}
134
135define <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]]
140;
141entry:
142  %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 4, i16 4>
143  ret <4 x i16> %mul
144}
145
146define <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]]
151;
152entry:
153  %mul = mul <4 x i16> %InVec, <i16 8, i16 8, i16 8, i16 8>
154  ret <4 x i16> %mul
155}
156
157define <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]]
162;
163entry:
164  %mul = mul <4 x i16> %InVec, <i16 1, i16 2, i16 4, i16 8>
165  ret <4 x i16> %mul
166}
167
168define <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]]
173;
174entry:
175  %mul = mul <4 x i16> %InVec, <i16 3, i16 3, i16 3, i16 3>
176  ret <4 x i16> %mul
177}
178
179define <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]]
184;
185entry:
186  %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 2, i16 2>
187  ret <4 x i16> %mul
188}
189
190define <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]]
195;
196entry:
197  %mul = mul <4 x i16> %InVec, <i16 4, i16 4, i16 0, i16 2>
198  ret <4 x i16> %mul
199}
200
201define <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
205;
206entry:
207  %mul = mul <4 x i32> %InVec, <i32 0, i32 0, i32 0, i32 0>
208  ret <4 x i32> %mul
209}
210
211define <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:%.*]]
215;
216entry:
217  %mul = mul <4 x i32> %InVec, <i32 1, i32 1, i32 1, i32 1>
218  ret <4 x i32> %mul
219}
220
221define <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]]
226;
227entry:
228  %mul = mul <4 x i32> %InVec, <i32 2, i32 2, i32 2, i32 2>
229  ret <4 x i32> %mul
230}
231
232define <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]]
237;
238entry:
239  %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 4, i32 4>
240  ret <4 x i32> %mul
241}
242
243define <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]]
248;
249entry:
250  %mul = mul <4 x i32> %InVec, <i32 8, i32 8, i32 8, i32 8>
251  ret <4 x i32> %mul
252}
253
254define <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]]
259;
260entry:
261  %mul = mul <4 x i32> %InVec, <i32 1, i32 2, i32 4, i32 8>
262  ret <4 x i32> %mul
263}
264
265define <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]]
270;
271entry:
272  %mul = mul <4 x i32> %InVec, <i32 3, i32 3, i32 3, i32 3>
273  ret <4 x i32> %mul
274}
275
276define <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]]
281;
282entry:
283  %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 2, i32 2>
284  ret <4 x i32> %mul
285}
286
287define <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]]
292;
293entry:
294  %mul = mul <4 x i32> %InVec, <i32 4, i32 4, i32 0, i32 1>
295  ret <4 x i32> %mul
296}
297
298define <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
302;
303entry:
304  %mul = mul <4 x i64> %InVec, <i64 0, i64 0, i64 0, i64 0>
305  ret <4 x i64> %mul
306}
307
308define <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:%.*]]
312;
313entry:
314  %mul = mul <4 x i64> %InVec, <i64 1, i64 1, i64 1, i64 1>
315  ret <4 x i64> %mul
316}
317
318define <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]]
323;
324entry:
325  %mul = mul <4 x i64> %InVec, <i64 2, i64 2, i64 2, i64 2>
326  ret <4 x i64> %mul
327}
328
329define <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]]
334;
335entry:
336  %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 4, i64 4>
337  ret <4 x i64> %mul
338}
339
340define <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]]
345;
346entry:
347  %mul = mul <4 x i64> %InVec, <i64 8, i64 8, i64 8, i64 8>
348  ret <4 x i64> %mul
349}
350
351define <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]]
356;
357entry:
358  %mul = mul <4 x i64> %InVec, <i64 1, i64 2, i64 4, i64 8>
359  ret <4 x i64> %mul
360}
361
362define <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]]
367;
368entry:
369  %mul = mul <4 x i64> %InVec, <i64 3, i64 3, i64 3, i64 3>
370  ret <4 x i64> %mul
371}
372
373define <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]]
378;
379entry:
380  %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 2, i64 2>
381  ret <4 x i64> %mul
382}
383
384define <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]]
389;
390entry:
391  %mul = mul <4 x i64> %InVec, <i64 4, i64 4, i64 0, i64 1>
392  ret <4 x i64> %mul
393}
394
395; Test also that the following rewriting rule works with vectors
396; of integers as well:
397;   ((X << C1)*C2) == (X * (C2 << C1))
398
399define <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]]
404;
405entry:
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
409}
410
411define <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]]
416;
417entry:
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
421}
422
423define <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]]
428;
429entry:
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
433}
434
435define <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]]
440;
441entry:
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
445}
446