1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; NOTE: Assertions have been autogenerated by update_llc_test_checks.py
3; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s
4
5@c = external global i32*, align 8
6
7; %val1 = load <2 x i8>
8; %op1 = zext<2 x i32> %val1
9; %val2 = load <2 x i8>
10; %op2 = zext<2 x i32> %val2
11; %rst = mul <2 x i32> %op1, %op2
12;
13define void @mul_2xi8(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
14; CHECK-LABEL: mul_2xi8:
15; CHECK:       # BB#0: # %entry
16; CHECK-NEXT:    movq {{.*}}(%rip), %rax
17; CHECK-NEXT:    movzwl (%rdi,%rdx), %ecx
18; CHECK-NEXT:    movd %ecx, %xmm0
19; CHECK-NEXT:    movzwl (%rsi,%rdx), %ecx
20; CHECK-NEXT:    movd %ecx, %xmm1
21; CHECK-NEXT:    pxor %xmm2, %xmm2
22; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7]
23; CHECK-NEXT:    punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
24; CHECK-NEXT:    pmullw %xmm0, %xmm1
25; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
26; CHECK-NEXT:    movq %xmm1, (%rax,%rdx,4)
27; CHECK-NEXT:    retq
28entry:
29  %pre = load i32*, i32** @c
30  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
31  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
32  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
33  %tmp8 = zext <2 x i8> %wide.load to <2 x i32>
34  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
35  %tmp11 = bitcast i8* %tmp10 to <2 x i8>*
36  %wide.load17 = load <2 x i8>, <2 x i8>* %tmp11, align 1
37  %tmp12 = zext <2 x i8> %wide.load17 to <2 x i32>
38  %tmp13 = mul nuw nsw <2 x i32> %tmp12, %tmp8
39  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
40  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
41  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
42  ret void
43}
44
45; %val1 = load <4 x i8>
46; %op1 = zext<4 x i32> %val1
47; %val2 = load <4 x i8>
48; %op2 = zext<4 x i32> %val2
49; %rst = mul <4 x i32> %op1, %op2
50;
51define void @mul_4xi8(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
52; CHECK-LABEL: mul_4xi8:
53; CHECK:       # BB#0: # %entry
54; CHECK-NEXT:    movq {{.*}}(%rip), %rax
55; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
56; CHECK-NEXT:    movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
57; CHECK-NEXT:    pxor %xmm2, %xmm2
58; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7]
59; CHECK-NEXT:    punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
60; CHECK-NEXT:    pmullw %xmm0, %xmm1
61; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
62; CHECK-NEXT:    movdqu %xmm1, (%rax,%rdx,4)
63; CHECK-NEXT:    retq
64entry:
65  %pre = load i32*, i32** @c
66  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
67  %tmp7 = bitcast i8* %tmp6 to <4 x i8>*
68  %wide.load = load <4 x i8>, <4 x i8>* %tmp7, align 1
69  %tmp8 = zext <4 x i8> %wide.load to <4 x i32>
70  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
71  %tmp11 = bitcast i8* %tmp10 to <4 x i8>*
72  %wide.load17 = load <4 x i8>, <4 x i8>* %tmp11, align 1
73  %tmp12 = zext <4 x i8> %wide.load17 to <4 x i32>
74  %tmp13 = mul nuw nsw <4 x i32> %tmp12, %tmp8
75  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
76  %tmp15 = bitcast i32* %tmp14 to <4 x i32>*
77  store <4 x i32> %tmp13, <4 x i32>* %tmp15, align 4
78  ret void
79}
80
81; %val1 = load <8 x i8>
82; %op1 = zext<8 x i32> %val1
83; %val2 = load <8 x i8>
84; %op2 = zext<8 x i32> %val2
85; %rst = mul <8 x i32> %op1, %op2
86;
87define void @mul_8xi8(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
88; CHECK-LABEL: mul_8xi8:
89; CHECK:       # BB#0: # %entry
90; CHECK-NEXT:    movq {{.*}}(%rip), %rax
91; CHECK-NEXT:    movq {{.*#+}} xmm0 = mem[0],zero
92; CHECK-NEXT:    movq {{.*#+}} xmm1 = mem[0],zero
93; CHECK-NEXT:    pxor %xmm2, %xmm2
94; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3],xmm0[4],xmm2[4],xmm0[5],xmm2[5],xmm0[6],xmm2[6],xmm0[7],xmm2[7]
95; CHECK-NEXT:    punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
96; CHECK-NEXT:    pmullw %xmm0, %xmm1
97; CHECK-NEXT:    movdqa %xmm1, %xmm0
98; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
99; CHECK-NEXT:    punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
100; CHECK-NEXT:    movdqu %xmm1, 16(%rax,%rdx,4)
101; CHECK-NEXT:    movdqu %xmm0, (%rax,%rdx,4)
102; CHECK-NEXT:    retq
103entry:
104  %pre = load i32*, i32** @c
105  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
106  %tmp7 = bitcast i8* %tmp6 to <8 x i8>*
107  %wide.load = load <8 x i8>, <8 x i8>* %tmp7, align 1
108  %tmp8 = zext <8 x i8> %wide.load to <8 x i32>
109  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
110  %tmp11 = bitcast i8* %tmp10 to <8 x i8>*
111  %wide.load17 = load <8 x i8>, <8 x i8>* %tmp11, align 1
112  %tmp12 = zext <8 x i8> %wide.load17 to <8 x i32>
113  %tmp13 = mul nuw nsw <8 x i32> %tmp12, %tmp8
114  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
115  %tmp15 = bitcast i32* %tmp14 to <8 x i32>*
116  store <8 x i32> %tmp13, <8 x i32>* %tmp15, align 4
117  ret void
118}
119
120; %val1 = load <16 x i8>
121; %op1 = zext<16 x i32> %val1
122; %val2 = load <16 x i8>
123; %op2 = zext<16 x i32> %val2
124; %rst = mul <16 x i32> %op1, %op2
125;
126define void @mul_16xi8(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
127; CHECK-LABEL: mul_16xi8:
128; CHECK:       # BB#0: # %entry
129; CHECK-NEXT:    movq {{.*}}(%rip), %rax
130; CHECK-NEXT:    movdqu (%rdi,%rdx), %xmm0
131; CHECK-NEXT:    movdqu (%rsi,%rdx), %xmm1
132; CHECK-NEXT:    pxor %xmm2, %xmm2
133; CHECK-NEXT:    movdqa %xmm0, %xmm3
134; CHECK-NEXT:    punpcklbw {{.*#+}} xmm3 = xmm3[0],xmm2[0],xmm3[1],xmm2[1],xmm3[2],xmm2[2],xmm3[3],xmm2[3],xmm3[4],xmm2[4],xmm3[5],xmm2[5],xmm3[6],xmm2[6],xmm3[7],xmm2[7]
135; CHECK-NEXT:    movdqa %xmm1, %xmm4
136; CHECK-NEXT:    punpcklbw {{.*#+}} xmm4 = xmm4[0],xmm2[0],xmm4[1],xmm2[1],xmm4[2],xmm2[2],xmm4[3],xmm2[3],xmm4[4],xmm2[4],xmm4[5],xmm2[5],xmm4[6],xmm2[6],xmm4[7],xmm2[7]
137; CHECK-NEXT:    pmullw %xmm3, %xmm4
138; CHECK-NEXT:    movdqa %xmm4, %xmm3
139; CHECK-NEXT:    punpcklwd {{.*#+}} xmm3 = xmm3[0],xmm2[0],xmm3[1],xmm2[1],xmm3[2],xmm2[2],xmm3[3],xmm2[3]
140; CHECK-NEXT:    punpckhwd {{.*#+}} xmm4 = xmm4[4],xmm2[4],xmm4[5],xmm2[5],xmm4[6],xmm2[6],xmm4[7],xmm2[7]
141; CHECK-NEXT:    punpckhbw {{.*#+}} xmm0 = xmm0[8],xmm2[8],xmm0[9],xmm2[9],xmm0[10],xmm2[10],xmm0[11],xmm2[11],xmm0[12],xmm2[12],xmm0[13],xmm2[13],xmm0[14],xmm2[14],xmm0[15],xmm2[15]
142; CHECK-NEXT:    punpckhbw {{.*#+}} xmm1 = xmm1[8],xmm2[8],xmm1[9],xmm2[9],xmm1[10],xmm2[10],xmm1[11],xmm2[11],xmm1[12],xmm2[12],xmm1[13],xmm2[13],xmm1[14],xmm2[14],xmm1[15],xmm2[15]
143; CHECK-NEXT:    pmullw %xmm0, %xmm1
144; CHECK-NEXT:    movdqa %xmm1, %xmm0
145; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
146; CHECK-NEXT:    punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
147; CHECK-NEXT:    movdqu %xmm1, 48(%rax,%rdx,4)
148; CHECK-NEXT:    movdqu %xmm0, 32(%rax,%rdx,4)
149; CHECK-NEXT:    movdqu %xmm4, 16(%rax,%rdx,4)
150; CHECK-NEXT:    movdqu %xmm3, (%rax,%rdx,4)
151; CHECK-NEXT:    retq
152entry:
153  %pre = load i32*, i32** @c
154  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
155  %tmp7 = bitcast i8* %tmp6 to <16 x i8>*
156  %wide.load = load <16 x i8>, <16 x i8>* %tmp7, align 1
157  %tmp8 = zext <16 x i8> %wide.load to <16 x i32>
158  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
159  %tmp11 = bitcast i8* %tmp10 to <16 x i8>*
160  %wide.load17 = load <16 x i8>, <16 x i8>* %tmp11, align 1
161  %tmp12 = zext <16 x i8> %wide.load17 to <16 x i32>
162  %tmp13 = mul nuw nsw <16 x i32> %tmp12, %tmp8
163  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
164  %tmp15 = bitcast i32* %tmp14 to <16 x i32>*
165  store <16 x i32> %tmp13, <16 x i32>* %tmp15, align 4
166  ret void
167}
168
169; %val1 = load <2 x i16>
170; %op1 = zext<2 x i32> %val1
171; %val2 = load <2 x i16>
172; %op2 = zext<2 x i32> %val2
173; %rst = mul <2 x i32> %op1, %op2
174;
175define void @mul_2xi16(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
176; CHECK-LABEL: mul_2xi16:
177; CHECK:       # BB#0: # %entry
178; CHECK-NEXT:    movq {{.*}}(%rip), %rax
179; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
180; CHECK-NEXT:    movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
181; CHECK-NEXT:    movdqa %xmm1, %xmm2
182; CHECK-NEXT:    pmulhuw %xmm0, %xmm2
183; CHECK-NEXT:    pmullw %xmm0, %xmm1
184; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
185; CHECK-NEXT:    movq %xmm1, (%rax,%rdx,4)
186; CHECK-NEXT:    retq
187entry:
188  %pre = load i32*, i32** @c
189  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
190  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
191  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
192  %tmp8 = zext <2 x i16> %wide.load to <2 x i32>
193  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
194  %tmp11 = bitcast i8* %tmp10 to <2 x i16>*
195  %wide.load17 = load <2 x i16>, <2 x i16>* %tmp11, align 1
196  %tmp12 = zext <2 x i16> %wide.load17 to <2 x i32>
197  %tmp13 = mul nuw nsw <2 x i32> %tmp12, %tmp8
198  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
199  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
200  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
201  ret void
202}
203
204; %val1 = load <4 x i16>
205; %op1 = zext<4 x i32> %val1
206; %val2 = load <4 x i16>
207; %op2 = zext<4 x i32> %val2
208; %rst = mul <4 x i32> %op1, %op2
209;
210define void @mul_4xi16(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
211; CHECK-LABEL: mul_4xi16:
212; CHECK:       # BB#0: # %entry
213; CHECK-NEXT:    movq {{.*}}(%rip), %rax
214; CHECK-NEXT:    movq {{.*#+}} xmm0 = mem[0],zero
215; CHECK-NEXT:    movq {{.*#+}} xmm1 = mem[0],zero
216; CHECK-NEXT:    movdqa %xmm1, %xmm2
217; CHECK-NEXT:    pmulhuw %xmm0, %xmm2
218; CHECK-NEXT:    pmullw %xmm0, %xmm1
219; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
220; CHECK-NEXT:    movdqu %xmm1, (%rax,%rdx,4)
221; CHECK-NEXT:    retq
222entry:
223  %pre = load i32*, i32** @c
224  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
225  %tmp7 = bitcast i8* %tmp6 to <4 x i16>*
226  %wide.load = load <4 x i16>, <4 x i16>* %tmp7, align 1
227  %tmp8 = zext <4 x i16> %wide.load to <4 x i32>
228  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
229  %tmp11 = bitcast i8* %tmp10 to <4 x i16>*
230  %wide.load17 = load <4 x i16>, <4 x i16>* %tmp11, align 1
231  %tmp12 = zext <4 x i16> %wide.load17 to <4 x i32>
232  %tmp13 = mul nuw nsw <4 x i32> %tmp12, %tmp8
233  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
234  %tmp15 = bitcast i32* %tmp14 to <4 x i32>*
235  store <4 x i32> %tmp13, <4 x i32>* %tmp15, align 4
236  ret void
237}
238
239; %val1 = load <8 x i16>
240; %op1 = zext<8 x i32> %val1
241; %val2 = load <8 x i16>
242; %op2 = zext<8 x i32> %val2
243; %rst = mul <8 x i32> %op1, %op2
244;
245define void @mul_8xi16(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
246; CHECK-LABEL: mul_8xi16:
247; CHECK:       # BB#0: # %entry
248; CHECK-NEXT:    movq {{.*}}(%rip), %rax
249; CHECK-NEXT:    movdqu (%rdi,%rdx), %xmm0
250; CHECK-NEXT:    movdqu (%rsi,%rdx), %xmm1
251; CHECK-NEXT:    movdqa %xmm1, %xmm2
252; CHECK-NEXT:    pmulhuw %xmm0, %xmm2
253; CHECK-NEXT:    pmullw %xmm0, %xmm1
254; CHECK-NEXT:    movdqa %xmm1, %xmm0
255; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
256; CHECK-NEXT:    punpckhwd {{.*#+}} xmm1 = xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
257; CHECK-NEXT:    movdqu %xmm1, 16(%rax,%rdx,4)
258; CHECK-NEXT:    movdqu %xmm0, (%rax,%rdx,4)
259; CHECK-NEXT:    retq
260entry:
261  %pre = load i32*, i32** @c
262  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
263  %tmp7 = bitcast i8* %tmp6 to <8 x i16>*
264  %wide.load = load <8 x i16>, <8 x i16>* %tmp7, align 1
265  %tmp8 = zext <8 x i16> %wide.load to <8 x i32>
266  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
267  %tmp11 = bitcast i8* %tmp10 to <8 x i16>*
268  %wide.load17 = load <8 x i16>, <8 x i16>* %tmp11, align 1
269  %tmp12 = zext <8 x i16> %wide.load17 to <8 x i32>
270  %tmp13 = mul nuw nsw <8 x i32> %tmp12, %tmp8
271  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
272  %tmp15 = bitcast i32* %tmp14 to <8 x i32>*
273  store <8 x i32> %tmp13, <8 x i32>* %tmp15, align 4
274  ret void
275}
276
277; %val1 = load <16 x i16>
278; %op1 = zext<16 x i32> %val1
279; %val2 = load <16 x i16>
280; %op2 = zext<16 x i32> %val2
281; %rst = mul <16 x i32> %op1, %op2
282;
283define void @mul_16xi16(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
284; CHECK-LABEL: mul_16xi16:
285; CHECK:       # BB#0: # %entry
286; CHECK-NEXT:    movq {{.*}}(%rip), %rax
287; CHECK-NEXT:    movdqu (%rdi,%rdx), %xmm0
288; CHECK-NEXT:    movdqu 16(%rdi,%rdx), %xmm1
289; CHECK-NEXT:    movdqu (%rsi,%rdx), %xmm2
290; CHECK-NEXT:    movdqu 16(%rsi,%rdx), %xmm3
291; CHECK-NEXT:    movdqa %xmm2, %xmm4
292; CHECK-NEXT:    pmulhuw %xmm0, %xmm4
293; CHECK-NEXT:    pmullw %xmm0, %xmm2
294; CHECK-NEXT:    movdqa %xmm2, %xmm0
295; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3]
296; CHECK-NEXT:    punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7]
297; CHECK-NEXT:    movdqa %xmm3, %xmm4
298; CHECK-NEXT:    pmulhuw %xmm1, %xmm4
299; CHECK-NEXT:    pmullw %xmm1, %xmm3
300; CHECK-NEXT:    movdqa %xmm3, %xmm1
301; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3]
302; CHECK-NEXT:    punpckhwd {{.*#+}} xmm3 = xmm3[4],xmm4[4],xmm3[5],xmm4[5],xmm3[6],xmm4[6],xmm3[7],xmm4[7]
303; CHECK-NEXT:    movdqu %xmm3, 48(%rax,%rdx,4)
304; CHECK-NEXT:    movdqu %xmm1, 32(%rax,%rdx,4)
305; CHECK-NEXT:    movdqu %xmm2, 16(%rax,%rdx,4)
306; CHECK-NEXT:    movdqu %xmm0, (%rax,%rdx,4)
307; CHECK-NEXT:    retq
308entry:
309  %pre = load i32*, i32** @c
310  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
311  %tmp7 = bitcast i8* %tmp6 to <16 x i16>*
312  %wide.load = load <16 x i16>, <16 x i16>* %tmp7, align 1
313  %tmp8 = zext <16 x i16> %wide.load to <16 x i32>
314  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
315  %tmp11 = bitcast i8* %tmp10 to <16 x i16>*
316  %wide.load17 = load <16 x i16>, <16 x i16>* %tmp11, align 1
317  %tmp12 = zext <16 x i16> %wide.load17 to <16 x i32>
318  %tmp13 = mul nuw nsw <16 x i32> %tmp12, %tmp8
319  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
320  %tmp15 = bitcast i32* %tmp14 to <16 x i32>*
321  store <16 x i32> %tmp13, <16 x i32>* %tmp15, align 4
322  ret void
323}
324
325; %val1 = load <2 x i8>
326; %op1 = sext<2 x i32> %val1
327; %val2 = load <2 x i8>
328; %op2 = sext<2 x i32> %val2
329; %rst = mul <2 x i32> %op1, %op2
330;
331define void @mul_2xi8_sext(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
332; CHECK-LABEL: mul_2xi8_sext:
333; CHECK:       # BB#0: # %entry
334; CHECK-NEXT:    movq {{.*}}(%rip), %rax
335; CHECK-NEXT:    movzwl (%rdi,%rdx), %ecx
336; CHECK-NEXT:    movd %ecx, %xmm0
337; CHECK-NEXT:    movzwl (%rsi,%rdx), %ecx
338; CHECK-NEXT:    movd %ecx, %xmm1
339; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
340; CHECK-NEXT:    psraw $8, %xmm0
341; CHECK-NEXT:    punpcklbw {{.*#+}} xmm1 = xmm1[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
342; CHECK-NEXT:    psraw $8, %xmm1
343; CHECK-NEXT:    pmullw %xmm0, %xmm1
344; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
345; CHECK-NEXT:    psrad $16, %xmm0
346; CHECK-NEXT:    movq %xmm0, (%rax,%rdx,4)
347; CHECK-NEXT:    retq
348entry:
349  %pre = load i32*, i32** @c
350  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
351  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
352  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
353  %tmp8 = sext <2 x i8> %wide.load to <2 x i32>
354  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
355  %tmp11 = bitcast i8* %tmp10 to <2 x i8>*
356  %wide.load17 = load <2 x i8>, <2 x i8>* %tmp11, align 1
357  %tmp12 = sext <2 x i8> %wide.load17 to <2 x i32>
358  %tmp13 = mul nuw nsw <2 x i32> %tmp12, %tmp8
359  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
360  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
361  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
362  ret void
363}
364
365; %val1 = load <2 x i8>
366; %op1 = sext<2 x i32> %val1
367; %val2 = load <2 x i8>
368; %op2 = zext<2 x i32> %val2
369; %rst = mul <2 x i32> %op1, %op2
370;
371define void @mul_2xi8_sext_zext(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
372; CHECK-LABEL: mul_2xi8_sext_zext:
373; CHECK:       # BB#0: # %entry
374; CHECK-NEXT:    movq {{.*}}(%rip), %rax
375; CHECK-NEXT:    movzwl (%rdi,%rdx), %ecx
376; CHECK-NEXT:    movd %ecx, %xmm0
377; CHECK-NEXT:    movzwl (%rsi,%rdx), %ecx
378; CHECK-NEXT:    movd %ecx, %xmm1
379; CHECK-NEXT:    pxor %xmm2, %xmm2
380; CHECK-NEXT:    punpcklbw {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
381; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
382; CHECK-NEXT:    psraw $8, %xmm0
383; CHECK-NEXT:    movdqa %xmm1, %xmm2
384; CHECK-NEXT:    pmulhw %xmm0, %xmm2
385; CHECK-NEXT:    pmullw %xmm1, %xmm0
386; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
387; CHECK-NEXT:    movq %xmm0, (%rax,%rdx,4)
388; CHECK-NEXT:    retq
389entry:
390  %pre = load i32*, i32** @c
391  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
392  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
393  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
394  %tmp8 = sext <2 x i8> %wide.load to <2 x i32>
395  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
396  %tmp11 = bitcast i8* %tmp10 to <2 x i8>*
397  %wide.load17 = load <2 x i8>, <2 x i8>* %tmp11, align 1
398  %tmp12 = zext <2 x i8> %wide.load17 to <2 x i32>
399  %tmp13 = mul nuw nsw <2 x i32> %tmp12, %tmp8
400  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
401  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
402  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
403  ret void
404}
405
406; %val1 = load <2 x i16>
407; %op1 = sext<2 x i32> %val1
408; %val2 = load <2 x i16>
409; %op2 = sext<2 x i32> %val2
410; %rst = mul <2 x i32> %op1, %op2
411;
412define void @mul_2xi16_sext(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
413; CHECK-LABEL: mul_2xi16_sext:
414; CHECK:       # BB#0: # %entry
415; CHECK-NEXT:    movq {{.*}}(%rip), %rax
416; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
417; CHECK-NEXT:    movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
418; CHECK-NEXT:    movdqa %xmm1, %xmm2
419; CHECK-NEXT:    pmulhw %xmm0, %xmm2
420; CHECK-NEXT:    pmullw %xmm0, %xmm1
421; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
422; CHECK-NEXT:    movq %xmm1, (%rax,%rdx,4)
423; CHECK-NEXT:    retq
424entry:
425  %pre = load i32*, i32** @c
426  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
427  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
428  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
429  %tmp8 = sext <2 x i16> %wide.load to <2 x i32>
430  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
431  %tmp11 = bitcast i8* %tmp10 to <2 x i16>*
432  %wide.load17 = load <2 x i16>, <2 x i16>* %tmp11, align 1
433  %tmp12 = sext <2 x i16> %wide.load17 to <2 x i32>
434  %tmp13 = mul nuw nsw <2 x i32> %tmp12, %tmp8
435  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
436  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
437  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
438  ret void
439}
440
441; %val1 = load <2 x i16>
442; %op1 = sext<2 x i32> %val1
443; %val2 = load <2 x i16>
444; %op2 = zext<2 x i32> %val2
445; %rst = mul <2 x i32> %op1, %op2
446;
447define void @mul_2xi16_sext_zext(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
448; CHECK-LABEL: mul_2xi16_sext_zext:
449; CHECK:       # BB#0: # %entry
450; CHECK-NEXT:    movq {{.*}}(%rip), %rax
451; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
452; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3]
453; CHECK-NEXT:    psrad $16, %xmm0
454; CHECK-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,1,1,3]
455; CHECK-NEXT:    movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
456; CHECK-NEXT:    pxor %xmm2, %xmm2
457; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
458; CHECK-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,1,3]
459; CHECK-NEXT:    movdqa %xmm1, %xmm2
460; CHECK-NEXT:    psrlq $32, %xmm2
461; CHECK-NEXT:    pmuludq %xmm0, %xmm2
462; CHECK-NEXT:    movdqa %xmm0, %xmm3
463; CHECK-NEXT:    psrlq $32, %xmm3
464; CHECK-NEXT:    pmuludq %xmm1, %xmm3
465; CHECK-NEXT:    paddq %xmm2, %xmm3
466; CHECK-NEXT:    psllq $32, %xmm3
467; CHECK-NEXT:    pmuludq %xmm0, %xmm1
468; CHECK-NEXT:    paddq %xmm3, %xmm1
469; CHECK-NEXT:    pshufd {{.*#+}} xmm0 = xmm1[0,2,2,3]
470; CHECK-NEXT:    movq %xmm0, (%rax,%rdx,4)
471; CHECK-NEXT:    retq
472entry:
473  %pre = load i32*, i32** @c
474  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
475  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
476  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
477  %tmp8 = sext <2 x i16> %wide.load to <2 x i32>
478  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
479  %tmp11 = bitcast i8* %tmp10 to <2 x i16>*
480  %wide.load17 = load <2 x i16>, <2 x i16>* %tmp11, align 1
481  %tmp12 = zext <2 x i16> %wide.load17 to <2 x i32>
482  %tmp13 = mul nuw nsw <2 x i32> %tmp12, %tmp8
483  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
484  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
485  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
486  ret void
487}
488
489; %val1 = load <16 x i16>
490; %op1 = sext<16 x i32> %val1
491; %val2 = load <16 x i16>
492; %op2 = sext<16 x i32> %val2
493; %rst = mul <16 x i32> %op1, %op2
494;
495define void @mul_16xi16_sext(i8* nocapture readonly %a, i8* nocapture readonly %b, i64 %index) {
496; CHECK-LABEL: mul_16xi16_sext:
497; CHECK:       # BB#0: # %entry
498; CHECK-NEXT:    movq {{.*}}(%rip), %rax
499; CHECK-NEXT:    movdqu (%rdi,%rdx), %xmm0
500; CHECK-NEXT:    movdqu 16(%rdi,%rdx), %xmm1
501; CHECK-NEXT:    movdqu (%rsi,%rdx), %xmm2
502; CHECK-NEXT:    movdqu 16(%rsi,%rdx), %xmm3
503; CHECK-NEXT:    movdqa %xmm2, %xmm4
504; CHECK-NEXT:    pmulhw %xmm0, %xmm4
505; CHECK-NEXT:    pmullw %xmm0, %xmm2
506; CHECK-NEXT:    movdqa %xmm2, %xmm0
507; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1],xmm0[2],xmm4[2],xmm0[3],xmm4[3]
508; CHECK-NEXT:    punpckhwd {{.*#+}} xmm2 = xmm2[4],xmm4[4],xmm2[5],xmm4[5],xmm2[6],xmm4[6],xmm2[7],xmm4[7]
509; CHECK-NEXT:    movdqa %xmm3, %xmm4
510; CHECK-NEXT:    pmulhw %xmm1, %xmm4
511; CHECK-NEXT:    pmullw %xmm1, %xmm3
512; CHECK-NEXT:    movdqa %xmm3, %xmm1
513; CHECK-NEXT:    punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3]
514; CHECK-NEXT:    punpckhwd {{.*#+}} xmm3 = xmm3[4],xmm4[4],xmm3[5],xmm4[5],xmm3[6],xmm4[6],xmm3[7],xmm4[7]
515; CHECK-NEXT:    movdqu %xmm3, 48(%rax,%rdx,4)
516; CHECK-NEXT:    movdqu %xmm1, 32(%rax,%rdx,4)
517; CHECK-NEXT:    movdqu %xmm2, 16(%rax,%rdx,4)
518; CHECK-NEXT:    movdqu %xmm0, (%rax,%rdx,4)
519; CHECK-NEXT:    retq
520entry:
521  %pre = load i32*, i32** @c
522  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
523  %tmp7 = bitcast i8* %tmp6 to <16 x i16>*
524  %wide.load = load <16 x i16>, <16 x i16>* %tmp7, align 1
525  %tmp8 = sext <16 x i16> %wide.load to <16 x i32>
526  %tmp10 = getelementptr inbounds i8, i8* %b, i64 %index
527  %tmp11 = bitcast i8* %tmp10 to <16 x i16>*
528  %wide.load17 = load <16 x i16>, <16 x i16>* %tmp11, align 1
529  %tmp12 = sext <16 x i16> %wide.load17 to <16 x i32>
530  %tmp13 = mul nuw nsw <16 x i32> %tmp12, %tmp8
531  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
532  %tmp15 = bitcast i32* %tmp14 to <16 x i32>*
533  store <16 x i32> %tmp13, <16 x i32>* %tmp15, align 4
534  ret void
535}
536
537; %val = load <2 x i8>
538; %op1 = zext<2 x i32> %val
539; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (0 ~ 255)
540; %rst = mul <2 x i32> %op1, %op2
541;
542define void @mul_2xi8_varconst1(i8* nocapture readonly %a, i64 %index) {
543; CHECK-LABEL: mul_2xi8_varconst1:
544; CHECK:       # BB#0: # %entry
545; CHECK-NEXT:    movq {{.*}}(%rip), %rax
546; CHECK-NEXT:    movzwl (%rdi,%rsi), %ecx
547; CHECK-NEXT:    movd %ecx, %xmm0
548; CHECK-NEXT:    pxor %xmm1, %xmm1
549; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
550; CHECK-NEXT:    pmullw {{.*}}(%rip), %xmm0
551; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
552; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
553; CHECK-NEXT:    retq
554entry:
555  %pre = load i32*, i32** @c
556  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
557  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
558  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
559  %tmp8 = zext <2 x i8> %wide.load to <2 x i32>
560  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 0, i32 255>
561  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
562  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
563  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
564  ret void
565}
566
567; %val = load <2 x i8>
568; %op1 = sext<2 x i32> %val
569; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (-128 ~ 127)
570; %rst = mul <2 x i32> %op1, %op2
571;
572define void @mul_2xi8_varconst2(i8* nocapture readonly %a, i64 %index) {
573; CHECK-LABEL: mul_2xi8_varconst2:
574; CHECK:       # BB#0: # %entry
575; CHECK-NEXT:    movq {{.*}}(%rip), %rax
576; CHECK-NEXT:    movzwl (%rdi,%rsi), %ecx
577; CHECK-NEXT:    movd %ecx, %xmm0
578; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
579; CHECK-NEXT:    psraw $8, %xmm0
580; CHECK-NEXT:    pmullw {{.*}}(%rip), %xmm0
581; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3]
582; CHECK-NEXT:    psrad $16, %xmm0
583; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
584; CHECK-NEXT:    retq
585entry:
586  %pre = load i32*, i32** @c
587  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
588  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
589  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
590  %tmp8 = sext <2 x i8> %wide.load to <2 x i32>
591  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 -128, i32 127>
592  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
593  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
594  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
595  ret void
596}
597
598; %val = load <2 x i8>
599; %op1 = zext<2 x i32> %val
600; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (0 ~ 256)
601; %rst = mul <2 x i32> %op1, %op2
602;
603define void @mul_2xi8_varconst3(i8* nocapture readonly %a, i64 %index) {
604; CHECK-LABEL: mul_2xi8_varconst3:
605; CHECK:       # BB#0: # %entry
606; CHECK-NEXT:    movq {{.*}}(%rip), %rax
607; CHECK-NEXT:    movzwl (%rdi,%rsi), %ecx
608; CHECK-NEXT:    movd %ecx, %xmm0
609; CHECK-NEXT:    pxor %xmm1, %xmm1
610; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
611; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = <0,256,u,u,u,u,u,u>
612; CHECK-NEXT:    movdqa %xmm0, %xmm2
613; CHECK-NEXT:    pmulhw %xmm1, %xmm2
614; CHECK-NEXT:    pmullw %xmm1, %xmm0
615; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
616; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
617; CHECK-NEXT:    retq
618entry:
619  %pre = load i32*, i32** @c
620  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
621  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
622  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
623  %tmp8 = zext <2 x i8> %wide.load to <2 x i32>
624  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 0, i32 256>
625  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
626  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
627  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
628  ret void
629}
630
631; %val = load <2 x i8>
632; %op1 = zext<2 x i32> %val
633; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (-1 ~ 255)
634; %rst = mul <2 x i32> %op1, %op2
635;
636define void @mul_2xi8_varconst4(i8* nocapture readonly %a, i64 %index) {
637; CHECK-LABEL: mul_2xi8_varconst4:
638; CHECK:       # BB#0: # %entry
639; CHECK-NEXT:    movq {{.*}}(%rip), %rax
640; CHECK-NEXT:    movzwl (%rdi,%rsi), %ecx
641; CHECK-NEXT:    movd %ecx, %xmm0
642; CHECK-NEXT:    pxor %xmm1, %xmm1
643; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
644; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = <65535,255,u,u,u,u,u,u>
645; CHECK-NEXT:    movdqa %xmm0, %xmm2
646; CHECK-NEXT:    pmulhw %xmm1, %xmm2
647; CHECK-NEXT:    pmullw %xmm1, %xmm0
648; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
649; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
650; CHECK-NEXT:    retq
651entry:
652  %pre = load i32*, i32** @c
653  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
654  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
655  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
656  %tmp8 = zext <2 x i8> %wide.load to <2 x i32>
657  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 -1, i32 255>
658  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
659  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
660  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
661  ret void
662}
663
664; %val = load <2 x i8>
665; %op1 = sext<2 x i32> %val
666; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (-129 ~ 127)
667; %rst = mul <2 x i32> %op1, %op2
668;
669define void @mul_2xi8_varconst5(i8* nocapture readonly %a, i64 %index) {
670; CHECK-LABEL: mul_2xi8_varconst5:
671; CHECK:       # BB#0: # %entry
672; CHECK-NEXT:    movq {{.*}}(%rip), %rax
673; CHECK-NEXT:    movzwl (%rdi,%rsi), %ecx
674; CHECK-NEXT:    movd %ecx, %xmm0
675; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
676; CHECK-NEXT:    psraw $8, %xmm0
677; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = <65407,127,u,u,u,u,u,u>
678; CHECK-NEXT:    movdqa %xmm0, %xmm2
679; CHECK-NEXT:    pmulhw %xmm1, %xmm2
680; CHECK-NEXT:    pmullw %xmm1, %xmm0
681; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
682; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
683; CHECK-NEXT:    retq
684entry:
685  %pre = load i32*, i32** @c
686  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
687  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
688  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
689  %tmp8 = sext <2 x i8> %wide.load to <2 x i32>
690  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 -129, i32 127>
691  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
692  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
693  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
694  ret void
695}
696
697; %val = load <2 x i8>
698; %op1 = sext<2 x i32> %val
699; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (-128 ~ 128)
700; %rst = mul <2 x i32> %op1, %op2
701;
702define void @mul_2xi8_varconst6(i8* nocapture readonly %a, i64 %index) {
703; CHECK-LABEL: mul_2xi8_varconst6:
704; CHECK:       # BB#0: # %entry
705; CHECK-NEXT:    movq {{.*}}(%rip), %rax
706; CHECK-NEXT:    movzwl (%rdi,%rsi), %ecx
707; CHECK-NEXT:    movd %ecx, %xmm0
708; CHECK-NEXT:    punpcklbw {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
709; CHECK-NEXT:    psraw $8, %xmm0
710; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = <65408,128,u,u,u,u,u,u>
711; CHECK-NEXT:    movdqa %xmm0, %xmm2
712; CHECK-NEXT:    pmulhw %xmm1, %xmm2
713; CHECK-NEXT:    pmullw %xmm1, %xmm0
714; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
715; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
716; CHECK-NEXT:    retq
717entry:
718  %pre = load i32*, i32** @c
719  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
720  %tmp7 = bitcast i8* %tmp6 to <2 x i8>*
721  %wide.load = load <2 x i8>, <2 x i8>* %tmp7, align 1
722  %tmp8 = sext <2 x i8> %wide.load to <2 x i32>
723  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 -128, i32 128>
724  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
725  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
726  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
727  ret void
728}
729
730; %val = load <2 x i16>
731; %op1 = zext<2 x i32> %val
732; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (0 ~ 65535)
733; %rst = mul <2 x i32> %op1, %op2
734;
735define void @mul_2xi16_varconst1(i8* nocapture readonly %a, i64 %index) {
736; CHECK-LABEL: mul_2xi16_varconst1:
737; CHECK:       # BB#0: # %entry
738; CHECK-NEXT:    movq {{.*}}(%rip), %rax
739; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
740; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = <0,65535,u,u,u,u,u,u>
741; CHECK-NEXT:    movdqa %xmm0, %xmm2
742; CHECK-NEXT:    pmulhuw %xmm1, %xmm2
743; CHECK-NEXT:    pmullw %xmm1, %xmm0
744; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
745; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
746; CHECK-NEXT:    retq
747entry:
748  %pre = load i32*, i32** @c
749  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
750  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
751  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
752  %tmp8 = zext <2 x i16> %wide.load to <2 x i32>
753  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 0, i32 65535>
754  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
755  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
756  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
757  ret void
758}
759
760; %val = load <2 x i16>
761; %op1 = sext<2 x i32> %val
762; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (-32768 ~ 32767)
763; %rst = mul <2 x i32> %op1, %op2
764;
765define void @mul_2xi16_varconst2(i8* nocapture readonly %a, i64 %index) {
766; CHECK-LABEL: mul_2xi16_varconst2:
767; CHECK:       # BB#0: # %entry
768; CHECK-NEXT:    movq {{.*}}(%rip), %rax
769; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
770; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = <32768,32767,u,u,u,u,u,u>
771; CHECK-NEXT:    movdqa %xmm0, %xmm2
772; CHECK-NEXT:    pmulhw %xmm1, %xmm2
773; CHECK-NEXT:    pmullw %xmm1, %xmm0
774; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1],xmm0[2],xmm2[2],xmm0[3],xmm2[3]
775; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
776; CHECK-NEXT:    retq
777entry:
778  %pre = load i32*, i32** @c
779  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
780  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
781  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
782  %tmp8 = sext <2 x i16> %wide.load to <2 x i32>
783  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 -32768, i32 32767>
784  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
785  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
786  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
787  ret void
788}
789
790; %val = load <2 x i16>
791; %op1 = zext<2 x i32> %val
792; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (0 ~ 65536)
793; %rst = mul <2 x i32> %op1, %op2
794;
795define void @mul_2xi16_varconst3(i8* nocapture readonly %a, i64 %index) {
796; CHECK-LABEL: mul_2xi16_varconst3:
797; CHECK:       # BB#0: # %entry
798; CHECK-NEXT:    movq {{.*}}(%rip), %rax
799; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
800; CHECK-NEXT:    pxor %xmm1, %xmm1
801; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3]
802; CHECK-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,1,1,3]
803; CHECK-NEXT:    movl $65536, %ecx # imm = 0x10000
804; CHECK-NEXT:    movd %rcx, %xmm1
805; CHECK-NEXT:    pslldq {{.*#+}} xmm1 = zero,zero,zero,zero,zero,zero,zero,zero,xmm1[0,1,2,3,4,5,6,7]
806; CHECK-NEXT:    movdqa %xmm0, %xmm2
807; CHECK-NEXT:    pmuludq %xmm1, %xmm2
808; CHECK-NEXT:    psrlq $32, %xmm0
809; CHECK-NEXT:    pmuludq %xmm1, %xmm0
810; CHECK-NEXT:    psllq $32, %xmm0
811; CHECK-NEXT:    paddq %xmm2, %xmm0
812; CHECK-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
813; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
814; CHECK-NEXT:    retq
815entry:
816  %pre = load i32*, i32** @c
817  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
818  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
819  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
820  %tmp8 = zext <2 x i16> %wide.load to <2 x i32>
821  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 0, i32 65536>
822  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
823  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
824  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
825  ret void
826}
827
828; %val = load <2 x i16>
829; %op1 = sext<2 x i32> %val
830; %op2 = const <2 x i32> {c1, c2} // c1 and c2 are within (0 ~ 32768)
831; %rst = mul <2 x i32> %op1, %op2
832;
833define void @mul_2xi16_varconst4(i8* nocapture readonly %a, i64 %index) {
834; CHECK-LABEL: mul_2xi16_varconst4:
835; CHECK:       # BB#0: # %entry
836; CHECK-NEXT:    movq {{.*}}(%rip), %rax
837; CHECK-NEXT:    movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
838; CHECK-NEXT:    punpcklwd {{.*#+}} xmm0 = xmm0[0,0,1,1,2,2,3,3]
839; CHECK-NEXT:    psrad $16, %xmm0
840; CHECK-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,1,1,3]
841; CHECK-NEXT:    movl $32768, %ecx # imm = 0x8000
842; CHECK-NEXT:    movd %rcx, %xmm1
843; CHECK-NEXT:    pslldq {{.*#+}} xmm1 = zero,zero,zero,zero,zero,zero,zero,zero,xmm1[0,1,2,3,4,5,6,7]
844; CHECK-NEXT:    movdqa %xmm0, %xmm2
845; CHECK-NEXT:    pmuludq %xmm1, %xmm2
846; CHECK-NEXT:    psrlq $32, %xmm0
847; CHECK-NEXT:    pmuludq %xmm1, %xmm0
848; CHECK-NEXT:    psllq $32, %xmm0
849; CHECK-NEXT:    paddq %xmm2, %xmm0
850; CHECK-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
851; CHECK-NEXT:    movq %xmm0, (%rax,%rsi,4)
852; CHECK-NEXT:    retq
853entry:
854  %pre = load i32*, i32** @c
855  %tmp6 = getelementptr inbounds i8, i8* %a, i64 %index
856  %tmp7 = bitcast i8* %tmp6 to <2 x i16>*
857  %wide.load = load <2 x i16>, <2 x i16>* %tmp7, align 1
858  %tmp8 = sext <2 x i16> %wide.load to <2 x i32>
859  %tmp13 = mul nuw nsw <2 x i32> %tmp8, <i32 0, i32 32768>
860  %tmp14 = getelementptr inbounds i32, i32* %pre, i64 %index
861  %tmp15 = bitcast i32* %tmp14 to <2 x i32>*
862  store <2 x i32> %tmp13, <2 x i32>* %tmp15, align 4
863  ret void
864}
865