1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=sse4.1 | FileCheck %s --check-prefix=SSE
3; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=avx2 | FileCheck %s --check-prefix=AVX2
4; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mattr=avx512f | FileCheck %s --check-prefix=AVX512
5
6; Verify that we don't scalarize a packed vector shift left of 16-bit
7; signed integers if the amount is a constant build_vector.
8; Check that we produce a SSE2 packed integer multiply (pmullw) instead.
9
10define <8 x i16> @test1(<8 x i16> %a) {
11; SSE-LABEL: test1:
12; SSE:       # BB#0:
13; SSE-NEXT:    pmullw {{.*}}(%rip), %xmm0
14; SSE-NEXT:    retq
15;
16; AVX2-LABEL: test1:
17; AVX2:       # BB#0:
18; AVX2-NEXT:    vpmullw {{.*}}(%rip), %xmm0, %xmm0
19; AVX2-NEXT:    retq
20;
21; AVX512-LABEL: test1:
22; AVX512:       # BB#0:
23; AVX512-NEXT:    vpmullw {{.*}}(%rip), %xmm0, %xmm0
24; AVX512-NEXT:    retq
25  %shl = shl <8 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11>
26  ret <8 x i16> %shl
27}
28
29define <8 x i16> @test2(<8 x i16> %a) {
30; SSE-LABEL: test2:
31; SSE:       # BB#0:
32; SSE-NEXT:    pmullw {{.*}}(%rip), %xmm0
33; SSE-NEXT:    retq
34;
35; AVX2-LABEL: test2:
36; AVX2:       # BB#0:
37; AVX2-NEXT:    vpmullw {{.*}}(%rip), %xmm0, %xmm0
38; AVX2-NEXT:    retq
39;
40; AVX512-LABEL: test2:
41; AVX512:       # BB#0:
42; AVX512-NEXT:    vpmullw {{.*}}(%rip), %xmm0, %xmm0
43; AVX512-NEXT:    retq
44  %shl = shl <8 x i16> %a, <i16 0, i16 undef, i16 0, i16 0, i16 1, i16 undef, i16 -1, i16 1>
45  ret <8 x i16> %shl
46}
47
48; Verify that a vector shift left of 32-bit signed integers is simply expanded
49; into a SSE4.1 pmulld (instead of cvttps2dq + pmulld) if the vector of shift
50; counts is a constant build_vector.
51
52define <4 x i32> @test3(<4 x i32> %a) {
53; SSE-LABEL: test3:
54; SSE:       # BB#0:
55; SSE-NEXT:    pmulld {{.*}}(%rip), %xmm0
56; SSE-NEXT:    retq
57;
58; AVX2-LABEL: test3:
59; AVX2:       # BB#0:
60; AVX2-NEXT:    vpsllvd {{.*}}(%rip), %xmm0, %xmm0
61; AVX2-NEXT:    retq
62;
63; AVX512-LABEL: test3:
64; AVX512:       # BB#0:
65; AVX512-NEXT:    vpsllvd {{.*}}(%rip), %xmm0, %xmm0
66; AVX512-NEXT:    retq
67  %shl = shl <4 x i32> %a, <i32 1, i32 -1, i32 2, i32 -3>
68  ret <4 x i32> %shl
69}
70
71define <4 x i32> @test4(<4 x i32> %a) {
72; SSE-LABEL: test4:
73; SSE:       # BB#0:
74; SSE-NEXT:    pmulld {{.*}}(%rip), %xmm0
75; SSE-NEXT:    retq
76;
77; AVX2-LABEL: test4:
78; AVX2:       # BB#0:
79; AVX2-NEXT:    vpsllvd {{.*}}(%rip), %xmm0, %xmm0
80; AVX2-NEXT:    retq
81;
82; AVX512-LABEL: test4:
83; AVX512:       # BB#0:
84; AVX512-NEXT:    vpsllvd {{.*}}(%rip), %xmm0, %xmm0
85; AVX512-NEXT:    retq
86  %shl = shl <4 x i32> %a, <i32 0, i32 0, i32 1, i32 1>
87  ret <4 x i32> %shl
88}
89
90; If we have AVX/SSE2 but not AVX2, verify that the following shift is split
91; into two pmullw instructions. With AVX2, the test case below would produce
92; a single vpmullw.
93
94define <16 x i16> @test5(<16 x i16> %a) {
95; SSE-LABEL: test5:
96; SSE:       # BB#0:
97; SSE-NEXT:    movdqa {{.*#+}} xmm2 = [2,2,4,8,128,1,512,2048]
98; SSE-NEXT:    pmullw %xmm2, %xmm0
99; SSE-NEXT:    pmullw %xmm2, %xmm1
100; SSE-NEXT:    retq
101;
102; AVX2-LABEL: test5:
103; AVX2:       # BB#0:
104; AVX2-NEXT:    vpmullw {{.*}}(%rip), %ymm0, %ymm0
105; AVX2-NEXT:    retq
106;
107; AVX512-LABEL: test5:
108; AVX512:       # BB#0:
109; AVX512-NEXT:    vpmullw {{.*}}(%rip), %ymm0, %ymm0
110; AVX512-NEXT:    retq
111  %shl = shl <16 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11>
112  ret <16 x i16> %shl
113}
114
115; If we have AVX/SSE4.1 but not AVX2, verify that the following shift is split
116; into two pmulld instructions. With AVX2, the test case below would produce
117; a single vpsllvd instead.
118
119define <8 x i32> @test6(<8 x i32> %a) {
120; SSE-LABEL: test6:
121; SSE:       # BB#0:
122; SSE-NEXT:    movdqa {{.*#+}} xmm2 = [2,2,4,8]
123; SSE-NEXT:    pmulld %xmm2, %xmm0
124; SSE-NEXT:    pmulld %xmm2, %xmm1
125; SSE-NEXT:    retq
126;
127; AVX2-LABEL: test6:
128; AVX2:       # BB#0:
129; AVX2-NEXT:    vpsllvd {{.*}}(%rip), %ymm0, %ymm0
130; AVX2-NEXT:    retq
131;
132; AVX512-LABEL: test6:
133; AVX512:       # BB#0:
134; AVX512-NEXT:    vpsllvd {{.*}}(%rip), %ymm0, %ymm0
135; AVX512-NEXT:    retq
136  %shl = shl <8 x i32> %a, <i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3>
137  ret <8 x i32> %shl
138}
139
140; With AVX2 and AVX512, the test case below should produce a sequence of
141; two vpmullw instructions. On SSE2 instead, we split the shift in four
142; parts and then we convert each part into a pmullw.
143
144define <32 x i16> @test7(<32 x i16> %a) {
145; SSE-LABEL: test7:
146; SSE:       # BB#0:
147; SSE-NEXT:    movdqa {{.*#+}} xmm4 = [2,2,4,8,128,1,512,2048]
148; SSE-NEXT:    pmullw %xmm4, %xmm0
149; SSE-NEXT:    pmullw %xmm4, %xmm1
150; SSE-NEXT:    pmullw %xmm4, %xmm2
151; SSE-NEXT:    pmullw %xmm4, %xmm3
152; SSE-NEXT:    retq
153;
154; AVX2-LABEL: test7:
155; AVX2:       # BB#0:
156; AVX2-NEXT:    vbroadcasti128 {{.*#+}} ymm2 = [2,2,4,8,128,1,512,2048,2,2,4,8,128,1,512,2048]
157; AVX2-NEXT:    # ymm2 = mem[0,1,0,1]
158; AVX2-NEXT:    vpmullw %ymm2, %ymm0, %ymm0
159; AVX2-NEXT:    vpmullw %ymm2, %ymm1, %ymm1
160; AVX2-NEXT:    retq
161;
162; AVX512-LABEL: test7:
163; AVX512:       # BB#0:
164; AVX512-NEXT:    vbroadcasti128 {{.*#+}} ymm2 = [2,2,4,8,128,1,512,2048,2,2,4,8,128,1,512,2048]
165; AVX512-NEXT:    # ymm2 = mem[0,1,0,1]
166; AVX512-NEXT:    vpmullw %ymm2, %ymm0, %ymm0
167; AVX512-NEXT:    vpmullw %ymm2, %ymm1, %ymm1
168; AVX512-NEXT:    retq
169  %shl = shl <32 x i16> %a, <i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11, i16 1, i16 1, i16 2, i16 3, i16 7, i16 0, i16 9, i16 11>
170  ret <32 x i16> %shl
171}
172
173; Similar to test7; the difference is that with AVX512 support
174; we only produce a single vpsllvd/vpsllvq instead of a pair of vpsllvd/vpsllvq.
175
176define <16 x i32> @test8(<16 x i32> %a) {
177; SSE-LABEL: test8:
178; SSE:       # BB#0:
179; SSE-NEXT:    movdqa {{.*#+}} xmm4 = [2,2,4,8]
180; SSE-NEXT:    pmulld %xmm4, %xmm0
181; SSE-NEXT:    pmulld %xmm4, %xmm1
182; SSE-NEXT:    pmulld %xmm4, %xmm2
183; SSE-NEXT:    pmulld %xmm4, %xmm3
184; SSE-NEXT:    retq
185;
186; AVX2-LABEL: test8:
187; AVX2:       # BB#0:
188; AVX2-NEXT:    vbroadcasti128 {{.*#+}} ymm2 = [1,1,2,3,1,1,2,3]
189; AVX2-NEXT:    # ymm2 = mem[0,1,0,1]
190; AVX2-NEXT:    vpsllvd %ymm2, %ymm0, %ymm0
191; AVX2-NEXT:    vpsllvd %ymm2, %ymm1, %ymm1
192; AVX2-NEXT:    retq
193;
194; AVX512-LABEL: test8:
195; AVX512:       # BB#0:
196; AVX512-NEXT:    vpsllvd {{.*}}(%rip), %zmm0, %zmm0
197; AVX512-NEXT:    retq
198  %shl = shl <16 x i32> %a, <i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3, i32 1, i32 1, i32 2, i32 3>
199  ret <16 x i32> %shl
200}
201
202; The shift from 'test9' gets shifted separately and blended if we don't have AVX2/AVX512f support.
203
204define <8 x i64> @test9(<8 x i64> %a) {
205; SSE-LABEL: test9:
206; SSE:       # BB#0:
207; SSE-NEXT:    movdqa %xmm1, %xmm4
208; SSE-NEXT:    psllq $3, %xmm4
209; SSE-NEXT:    psllq $2, %xmm1
210; SSE-NEXT:    pblendw {{.*#+}} xmm1 = xmm1[0,1,2,3],xmm4[4,5,6,7]
211; SSE-NEXT:    movdqa %xmm3, %xmm4
212; SSE-NEXT:    psllq $3, %xmm4
213; SSE-NEXT:    psllq $2, %xmm3
214; SSE-NEXT:    pblendw {{.*#+}} xmm3 = xmm3[0,1,2,3],xmm4[4,5,6,7]
215; SSE-NEXT:    paddq %xmm0, %xmm0
216; SSE-NEXT:    paddq %xmm2, %xmm2
217; SSE-NEXT:    retq
218;
219; AVX2-LABEL: test9:
220; AVX2:       # BB#0:
221; AVX2-NEXT:    vmovdqa {{.*#+}} ymm2 = [1,1,2,3]
222; AVX2-NEXT:    vpsllvq %ymm2, %ymm0, %ymm0
223; AVX2-NEXT:    vpsllvq %ymm2, %ymm1, %ymm1
224; AVX2-NEXT:    retq
225;
226; AVX512-LABEL: test9:
227; AVX512:       # BB#0:
228; AVX512-NEXT:    vpsllvq {{.*}}(%rip), %zmm0, %zmm0
229; AVX512-NEXT:    retq
230  %shl = shl <8 x i64> %a, <i64 1, i64 1, i64 2, i64 3, i64 1, i64 1, i64 2, i64 3>
231  ret <8 x i64> %shl
232}
233