1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ssse3              | FileCheck %s --check-prefixes=SSE3,SSE3-SLOW
3; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ssse3,fast-hops    | FileCheck %s --check-prefixes=SSE3,SSE3-FAST
4; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx                | FileCheck %s --check-prefixes=AVX,AVX-SLOW,AVX1-SLOW
5; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx,fast-hops      | FileCheck %s --check-prefixes=AVX,AVX-FAST,AVX1-FAST
6; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2               | FileCheck %s --check-prefixes=AVX,AVX-SLOW,AVX2-SLOW
7; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2,fast-hops     | FileCheck %s --check-prefixes=AVX,AVX-FAST,AVX2-FAST
8; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx512vl           | FileCheck %s --check-prefixes=AVX,AVX-SLOW,AVX512-SLOW
9; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx512vl,fast-hops | FileCheck %s --check-prefixes=AVX,AVX-FAST,AVX512-FAST
10
11; 128-bit vectors, 16/32-bit, add/sub
12
13define i32 @extract_extract_v4i32_add_i32(<4 x i32> %x) {
14; SSE3-LABEL: extract_extract_v4i32_add_i32:
15; SSE3:       # %bb.0:
16; SSE3-NEXT:    movd %xmm0, %ecx
17; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
18; SSE3-NEXT:    movd %xmm0, %eax
19; SSE3-NEXT:    addl %ecx, %eax
20; SSE3-NEXT:    retq
21;
22; AVX-LABEL: extract_extract_v4i32_add_i32:
23; AVX:       # %bb.0:
24; AVX-NEXT:    vmovd %xmm0, %ecx
25; AVX-NEXT:    vpextrd $1, %xmm0, %eax
26; AVX-NEXT:    addl %ecx, %eax
27; AVX-NEXT:    retq
28  %x0 = extractelement <4 x i32> %x, i32 0
29  %x1 = extractelement <4 x i32> %x, i32 1
30  %x01 = add i32 %x0, %x1
31  ret i32 %x01
32}
33
34define i32 @extract_extract_v4i32_add_i32_commute(<4 x i32> %x) {
35; SSE3-LABEL: extract_extract_v4i32_add_i32_commute:
36; SSE3:       # %bb.0:
37; SSE3-NEXT:    movd %xmm0, %ecx
38; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
39; SSE3-NEXT:    movd %xmm0, %eax
40; SSE3-NEXT:    addl %ecx, %eax
41; SSE3-NEXT:    retq
42;
43; AVX-LABEL: extract_extract_v4i32_add_i32_commute:
44; AVX:       # %bb.0:
45; AVX-NEXT:    vmovd %xmm0, %ecx
46; AVX-NEXT:    vpextrd $1, %xmm0, %eax
47; AVX-NEXT:    addl %ecx, %eax
48; AVX-NEXT:    retq
49  %x0 = extractelement <4 x i32> %x, i32 0
50  %x1 = extractelement <4 x i32> %x, i32 1
51  %x01 = add i32 %x1, %x0
52  ret i32 %x01
53}
54
55define i16 @extract_extract_v8i16_add_i16(<8 x i16> %x) {
56; SSE3-LABEL: extract_extract_v8i16_add_i16:
57; SSE3:       # %bb.0:
58; SSE3-NEXT:    movd %xmm0, %ecx
59; SSE3-NEXT:    pextrw $1, %xmm0, %eax
60; SSE3-NEXT:    addl %ecx, %eax
61; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
62; SSE3-NEXT:    retq
63;
64; AVX-LABEL: extract_extract_v8i16_add_i16:
65; AVX:       # %bb.0:
66; AVX-NEXT:    vmovd %xmm0, %ecx
67; AVX-NEXT:    vpextrw $1, %xmm0, %eax
68; AVX-NEXT:    addl %ecx, %eax
69; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
70; AVX-NEXT:    retq
71  %x0 = extractelement <8 x i16> %x, i32 0
72  %x1 = extractelement <8 x i16> %x, i32 1
73  %x01 = add i16 %x0, %x1
74  ret i16 %x01
75}
76
77define i16 @extract_extract_v8i16_add_i16_commute(<8 x i16> %x) {
78; SSE3-LABEL: extract_extract_v8i16_add_i16_commute:
79; SSE3:       # %bb.0:
80; SSE3-NEXT:    movd %xmm0, %ecx
81; SSE3-NEXT:    pextrw $1, %xmm0, %eax
82; SSE3-NEXT:    addl %ecx, %eax
83; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
84; SSE3-NEXT:    retq
85;
86; AVX-LABEL: extract_extract_v8i16_add_i16_commute:
87; AVX:       # %bb.0:
88; AVX-NEXT:    vmovd %xmm0, %ecx
89; AVX-NEXT:    vpextrw $1, %xmm0, %eax
90; AVX-NEXT:    addl %ecx, %eax
91; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
92; AVX-NEXT:    retq
93  %x0 = extractelement <8 x i16> %x, i32 0
94  %x1 = extractelement <8 x i16> %x, i32 1
95  %x01 = add i16 %x1, %x0
96  ret i16 %x01
97}
98
99define i32 @extract_extract_v4i32_sub_i32(<4 x i32> %x) {
100; SSE3-LABEL: extract_extract_v4i32_sub_i32:
101; SSE3:       # %bb.0:
102; SSE3-NEXT:    movd %xmm0, %eax
103; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
104; SSE3-NEXT:    movd %xmm0, %ecx
105; SSE3-NEXT:    subl %ecx, %eax
106; SSE3-NEXT:    retq
107;
108; AVX-LABEL: extract_extract_v4i32_sub_i32:
109; AVX:       # %bb.0:
110; AVX-NEXT:    vmovd %xmm0, %eax
111; AVX-NEXT:    vpextrd $1, %xmm0, %ecx
112; AVX-NEXT:    subl %ecx, %eax
113; AVX-NEXT:    retq
114  %x0 = extractelement <4 x i32> %x, i32 0
115  %x1 = extractelement <4 x i32> %x, i32 1
116  %x01 = sub i32 %x0, %x1
117  ret i32 %x01
118}
119
120define i32 @extract_extract_v4i32_sub_i32_commute(<4 x i32> %x) {
121; SSE3-LABEL: extract_extract_v4i32_sub_i32_commute:
122; SSE3:       # %bb.0:
123; SSE3-NEXT:    movd %xmm0, %ecx
124; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
125; SSE3-NEXT:    movd %xmm0, %eax
126; SSE3-NEXT:    subl %ecx, %eax
127; SSE3-NEXT:    retq
128;
129; AVX-LABEL: extract_extract_v4i32_sub_i32_commute:
130; AVX:       # %bb.0:
131; AVX-NEXT:    vmovd %xmm0, %ecx
132; AVX-NEXT:    vpextrd $1, %xmm0, %eax
133; AVX-NEXT:    subl %ecx, %eax
134; AVX-NEXT:    retq
135  %x0 = extractelement <4 x i32> %x, i32 0
136  %x1 = extractelement <4 x i32> %x, i32 1
137  %x01 = sub i32 %x1, %x0
138  ret i32 %x01
139}
140
141define i16 @extract_extract_v8i16_sub_i16(<8 x i16> %x) {
142; SSE3-LABEL: extract_extract_v8i16_sub_i16:
143; SSE3:       # %bb.0:
144; SSE3-NEXT:    movd %xmm0, %eax
145; SSE3-NEXT:    pextrw $1, %xmm0, %ecx
146; SSE3-NEXT:    subl %ecx, %eax
147; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
148; SSE3-NEXT:    retq
149;
150; AVX-LABEL: extract_extract_v8i16_sub_i16:
151; AVX:       # %bb.0:
152; AVX-NEXT:    vmovd %xmm0, %eax
153; AVX-NEXT:    vpextrw $1, %xmm0, %ecx
154; AVX-NEXT:    subl %ecx, %eax
155; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
156; AVX-NEXT:    retq
157  %x0 = extractelement <8 x i16> %x, i32 0
158  %x1 = extractelement <8 x i16> %x, i32 1
159  %x01 = sub i16 %x0, %x1
160  ret i16 %x01
161}
162
163define i16 @extract_extract_v8i16_sub_i16_commute(<8 x i16> %x) {
164; SSE3-LABEL: extract_extract_v8i16_sub_i16_commute:
165; SSE3:       # %bb.0:
166; SSE3-NEXT:    movd %xmm0, %ecx
167; SSE3-NEXT:    pextrw $1, %xmm0, %eax
168; SSE3-NEXT:    subl %ecx, %eax
169; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
170; SSE3-NEXT:    retq
171;
172; AVX-LABEL: extract_extract_v8i16_sub_i16_commute:
173; AVX:       # %bb.0:
174; AVX-NEXT:    vmovd %xmm0, %ecx
175; AVX-NEXT:    vpextrw $1, %xmm0, %eax
176; AVX-NEXT:    subl %ecx, %eax
177; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
178; AVX-NEXT:    retq
179  %x0 = extractelement <8 x i16> %x, i32 0
180  %x1 = extractelement <8 x i16> %x, i32 1
181  %x01 = sub i16 %x1, %x0
182  ret i16 %x01
183}
184
185; 256-bit vectors, i32/i16, add/sub
186
187define i32 @extract_extract_v8i32_add_i32(<8 x i32> %x) {
188; SSE3-LABEL: extract_extract_v8i32_add_i32:
189; SSE3:       # %bb.0:
190; SSE3-NEXT:    movd %xmm0, %ecx
191; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
192; SSE3-NEXT:    movd %xmm0, %eax
193; SSE3-NEXT:    addl %ecx, %eax
194; SSE3-NEXT:    retq
195;
196; AVX-LABEL: extract_extract_v8i32_add_i32:
197; AVX:       # %bb.0:
198; AVX-NEXT:    vmovd %xmm0, %ecx
199; AVX-NEXT:    vpextrd $1, %xmm0, %eax
200; AVX-NEXT:    addl %ecx, %eax
201; AVX-NEXT:    vzeroupper
202; AVX-NEXT:    retq
203  %x0 = extractelement <8 x i32> %x, i32 0
204  %x1 = extractelement <8 x i32> %x, i32 1
205  %x01 = add i32 %x0, %x1
206  ret i32 %x01
207}
208
209define i32 @extract_extract_v8i32_add_i32_commute(<8 x i32> %x) {
210; SSE3-LABEL: extract_extract_v8i32_add_i32_commute:
211; SSE3:       # %bb.0:
212; SSE3-NEXT:    movd %xmm0, %ecx
213; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
214; SSE3-NEXT:    movd %xmm0, %eax
215; SSE3-NEXT:    addl %ecx, %eax
216; SSE3-NEXT:    retq
217;
218; AVX-LABEL: extract_extract_v8i32_add_i32_commute:
219; AVX:       # %bb.0:
220; AVX-NEXT:    vmovd %xmm0, %ecx
221; AVX-NEXT:    vpextrd $1, %xmm0, %eax
222; AVX-NEXT:    addl %ecx, %eax
223; AVX-NEXT:    vzeroupper
224; AVX-NEXT:    retq
225  %x0 = extractelement <8 x i32> %x, i32 0
226  %x1 = extractelement <8 x i32> %x, i32 1
227  %x01 = add i32 %x1, %x0
228  ret i32 %x01
229}
230
231define i16 @extract_extract_v16i16_add_i16(<16 x i16> %x) {
232; SSE3-LABEL: extract_extract_v16i16_add_i16:
233; SSE3:       # %bb.0:
234; SSE3-NEXT:    movd %xmm0, %ecx
235; SSE3-NEXT:    pextrw $1, %xmm0, %eax
236; SSE3-NEXT:    addl %ecx, %eax
237; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
238; SSE3-NEXT:    retq
239;
240; AVX-LABEL: extract_extract_v16i16_add_i16:
241; AVX:       # %bb.0:
242; AVX-NEXT:    vmovd %xmm0, %ecx
243; AVX-NEXT:    vpextrw $1, %xmm0, %eax
244; AVX-NEXT:    addl %ecx, %eax
245; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
246; AVX-NEXT:    vzeroupper
247; AVX-NEXT:    retq
248  %x0 = extractelement <16 x i16> %x, i32 0
249  %x1 = extractelement <16 x i16> %x, i32 1
250  %x01 = add i16 %x0, %x1
251  ret i16 %x01
252}
253
254define i16 @extract_extract_v16i16_add_i16_commute(<16 x i16> %x) {
255; SSE3-LABEL: extract_extract_v16i16_add_i16_commute:
256; SSE3:       # %bb.0:
257; SSE3-NEXT:    movd %xmm0, %ecx
258; SSE3-NEXT:    pextrw $1, %xmm0, %eax
259; SSE3-NEXT:    addl %ecx, %eax
260; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
261; SSE3-NEXT:    retq
262;
263; AVX-LABEL: extract_extract_v16i16_add_i16_commute:
264; AVX:       # %bb.0:
265; AVX-NEXT:    vmovd %xmm0, %ecx
266; AVX-NEXT:    vpextrw $1, %xmm0, %eax
267; AVX-NEXT:    addl %ecx, %eax
268; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
269; AVX-NEXT:    vzeroupper
270; AVX-NEXT:    retq
271  %x0 = extractelement <16 x i16> %x, i32 0
272  %x1 = extractelement <16 x i16> %x, i32 1
273  %x01 = add i16 %x1, %x0
274  ret i16 %x01
275}
276
277define i32 @extract_extract_v8i32_sub_i32(<8 x i32> %x) {
278; SSE3-LABEL: extract_extract_v8i32_sub_i32:
279; SSE3:       # %bb.0:
280; SSE3-NEXT:    movd %xmm0, %eax
281; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
282; SSE3-NEXT:    movd %xmm0, %ecx
283; SSE3-NEXT:    subl %ecx, %eax
284; SSE3-NEXT:    retq
285;
286; AVX-LABEL: extract_extract_v8i32_sub_i32:
287; AVX:       # %bb.0:
288; AVX-NEXT:    vmovd %xmm0, %eax
289; AVX-NEXT:    vpextrd $1, %xmm0, %ecx
290; AVX-NEXT:    subl %ecx, %eax
291; AVX-NEXT:    vzeroupper
292; AVX-NEXT:    retq
293  %x0 = extractelement <8 x i32> %x, i32 0
294  %x1 = extractelement <8 x i32> %x, i32 1
295  %x01 = sub i32 %x0, %x1
296  ret i32 %x01
297}
298
299; Negative test...or get hoppy and negate?
300
301define i32 @extract_extract_v8i32_sub_i32_commute(<8 x i32> %x) {
302; SSE3-LABEL: extract_extract_v8i32_sub_i32_commute:
303; SSE3:       # %bb.0:
304; SSE3-NEXT:    movd %xmm0, %ecx
305; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
306; SSE3-NEXT:    movd %xmm0, %eax
307; SSE3-NEXT:    subl %ecx, %eax
308; SSE3-NEXT:    retq
309;
310; AVX-LABEL: extract_extract_v8i32_sub_i32_commute:
311; AVX:       # %bb.0:
312; AVX-NEXT:    vmovd %xmm0, %ecx
313; AVX-NEXT:    vpextrd $1, %xmm0, %eax
314; AVX-NEXT:    subl %ecx, %eax
315; AVX-NEXT:    vzeroupper
316; AVX-NEXT:    retq
317  %x0 = extractelement <8 x i32> %x, i32 0
318  %x1 = extractelement <8 x i32> %x, i32 1
319  %x01 = sub i32 %x1, %x0
320  ret i32 %x01
321}
322
323define i16 @extract_extract_v16i16_sub_i16(<16 x i16> %x) {
324; SSE3-LABEL: extract_extract_v16i16_sub_i16:
325; SSE3:       # %bb.0:
326; SSE3-NEXT:    movd %xmm0, %eax
327; SSE3-NEXT:    pextrw $1, %xmm0, %ecx
328; SSE3-NEXT:    subl %ecx, %eax
329; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
330; SSE3-NEXT:    retq
331;
332; AVX-LABEL: extract_extract_v16i16_sub_i16:
333; AVX:       # %bb.0:
334; AVX-NEXT:    vmovd %xmm0, %eax
335; AVX-NEXT:    vpextrw $1, %xmm0, %ecx
336; AVX-NEXT:    subl %ecx, %eax
337; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
338; AVX-NEXT:    vzeroupper
339; AVX-NEXT:    retq
340  %x0 = extractelement <16 x i16> %x, i32 0
341  %x1 = extractelement <16 x i16> %x, i32 1
342  %x01 = sub i16 %x0, %x1
343  ret i16 %x01
344}
345
346; Negative test...or get hoppy and negate?
347
348define i16 @extract_extract_v16i16_sub_i16_commute(<16 x i16> %x) {
349; SSE3-LABEL: extract_extract_v16i16_sub_i16_commute:
350; SSE3:       # %bb.0:
351; SSE3-NEXT:    movd %xmm0, %ecx
352; SSE3-NEXT:    pextrw $1, %xmm0, %eax
353; SSE3-NEXT:    subl %ecx, %eax
354; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
355; SSE3-NEXT:    retq
356;
357; AVX-LABEL: extract_extract_v16i16_sub_i16_commute:
358; AVX:       # %bb.0:
359; AVX-NEXT:    vmovd %xmm0, %ecx
360; AVX-NEXT:    vpextrw $1, %xmm0, %eax
361; AVX-NEXT:    subl %ecx, %eax
362; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
363; AVX-NEXT:    vzeroupper
364; AVX-NEXT:    retq
365  %x0 = extractelement <16 x i16> %x, i32 0
366  %x1 = extractelement <16 x i16> %x, i32 1
367  %x01 = sub i16 %x1, %x0
368  ret i16 %x01
369}
370
371; 512-bit vectors, i32/i16, add/sub
372
373define i32 @extract_extract_v16i32_add_i32(<16 x i32> %x) {
374; SSE3-LABEL: extract_extract_v16i32_add_i32:
375; SSE3:       # %bb.0:
376; SSE3-NEXT:    movd %xmm0, %ecx
377; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
378; SSE3-NEXT:    movd %xmm0, %eax
379; SSE3-NEXT:    addl %ecx, %eax
380; SSE3-NEXT:    retq
381;
382; AVX-LABEL: extract_extract_v16i32_add_i32:
383; AVX:       # %bb.0:
384; AVX-NEXT:    vmovd %xmm0, %ecx
385; AVX-NEXT:    vpextrd $1, %xmm0, %eax
386; AVX-NEXT:    addl %ecx, %eax
387; AVX-NEXT:    vzeroupper
388; AVX-NEXT:    retq
389  %x0 = extractelement <16 x i32> %x, i32 0
390  %x1 = extractelement <16 x i32> %x, i32 1
391  %x01 = add i32 %x0, %x1
392  ret i32 %x01
393}
394
395define i32 @extract_extract_v16i32_add_i32_commute(<16 x i32> %x) {
396; SSE3-LABEL: extract_extract_v16i32_add_i32_commute:
397; SSE3:       # %bb.0:
398; SSE3-NEXT:    movd %xmm0, %ecx
399; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
400; SSE3-NEXT:    movd %xmm0, %eax
401; SSE3-NEXT:    addl %ecx, %eax
402; SSE3-NEXT:    retq
403;
404; AVX-LABEL: extract_extract_v16i32_add_i32_commute:
405; AVX:       # %bb.0:
406; AVX-NEXT:    vmovd %xmm0, %ecx
407; AVX-NEXT:    vpextrd $1, %xmm0, %eax
408; AVX-NEXT:    addl %ecx, %eax
409; AVX-NEXT:    vzeroupper
410; AVX-NEXT:    retq
411  %x0 = extractelement <16 x i32> %x, i32 0
412  %x1 = extractelement <16 x i32> %x, i32 1
413  %x01 = add i32 %x1, %x0
414  ret i32 %x01
415}
416
417define i16 @extract_extract_v32i16_add_i16(<32 x i16> %x) {
418; SSE3-LABEL: extract_extract_v32i16_add_i16:
419; SSE3:       # %bb.0:
420; SSE3-NEXT:    movd %xmm0, %ecx
421; SSE3-NEXT:    pextrw $1, %xmm0, %eax
422; SSE3-NEXT:    addl %ecx, %eax
423; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
424; SSE3-NEXT:    retq
425;
426; AVX-LABEL: extract_extract_v32i16_add_i16:
427; AVX:       # %bb.0:
428; AVX-NEXT:    vmovd %xmm0, %ecx
429; AVX-NEXT:    vpextrw $1, %xmm0, %eax
430; AVX-NEXT:    addl %ecx, %eax
431; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
432; AVX-NEXT:    vzeroupper
433; AVX-NEXT:    retq
434  %x0 = extractelement <32 x i16> %x, i32 0
435  %x1 = extractelement <32 x i16> %x, i32 1
436  %x01 = add i16 %x0, %x1
437  ret i16 %x01
438}
439
440define i16 @extract_extract_v32i16_add_i16_commute(<32 x i16> %x) {
441; SSE3-LABEL: extract_extract_v32i16_add_i16_commute:
442; SSE3:       # %bb.0:
443; SSE3-NEXT:    movd %xmm0, %ecx
444; SSE3-NEXT:    pextrw $1, %xmm0, %eax
445; SSE3-NEXT:    addl %ecx, %eax
446; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
447; SSE3-NEXT:    retq
448;
449; AVX-LABEL: extract_extract_v32i16_add_i16_commute:
450; AVX:       # %bb.0:
451; AVX-NEXT:    vmovd %xmm0, %ecx
452; AVX-NEXT:    vpextrw $1, %xmm0, %eax
453; AVX-NEXT:    addl %ecx, %eax
454; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
455; AVX-NEXT:    vzeroupper
456; AVX-NEXT:    retq
457  %x0 = extractelement <32 x i16> %x, i32 0
458  %x1 = extractelement <32 x i16> %x, i32 1
459  %x01 = add i16 %x1, %x0
460  ret i16 %x01
461}
462
463define i32 @extract_extract_v16i32_sub_i32(<16 x i32> %x) {
464; SSE3-LABEL: extract_extract_v16i32_sub_i32:
465; SSE3:       # %bb.0:
466; SSE3-NEXT:    movd %xmm0, %eax
467; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
468; SSE3-NEXT:    movd %xmm0, %ecx
469; SSE3-NEXT:    subl %ecx, %eax
470; SSE3-NEXT:    retq
471;
472; AVX-LABEL: extract_extract_v16i32_sub_i32:
473; AVX:       # %bb.0:
474; AVX-NEXT:    vmovd %xmm0, %eax
475; AVX-NEXT:    vpextrd $1, %xmm0, %ecx
476; AVX-NEXT:    subl %ecx, %eax
477; AVX-NEXT:    vzeroupper
478; AVX-NEXT:    retq
479  %x0 = extractelement <16 x i32> %x, i32 0
480  %x1 = extractelement <16 x i32> %x, i32 1
481  %x01 = sub i32 %x0, %x1
482  ret i32 %x01
483}
484
485define i32 @extract_extract_v16i32_sub_i32_commute(<16 x i32> %x) {
486; SSE3-LABEL: extract_extract_v16i32_sub_i32_commute:
487; SSE3:       # %bb.0:
488; SSE3-NEXT:    movd %xmm0, %ecx
489; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
490; SSE3-NEXT:    movd %xmm0, %eax
491; SSE3-NEXT:    subl %ecx, %eax
492; SSE3-NEXT:    retq
493;
494; AVX-LABEL: extract_extract_v16i32_sub_i32_commute:
495; AVX:       # %bb.0:
496; AVX-NEXT:    vmovd %xmm0, %ecx
497; AVX-NEXT:    vpextrd $1, %xmm0, %eax
498; AVX-NEXT:    subl %ecx, %eax
499; AVX-NEXT:    vzeroupper
500; AVX-NEXT:    retq
501  %x0 = extractelement <16 x i32> %x, i32 0
502  %x1 = extractelement <16 x i32> %x, i32 1
503  %x01 = sub i32 %x1, %x0
504  ret i32 %x01
505}
506
507define i16 @extract_extract_v32i16_sub_i16(<32 x i16> %x) {
508; SSE3-LABEL: extract_extract_v32i16_sub_i16:
509; SSE3:       # %bb.0:
510; SSE3-NEXT:    movd %xmm0, %eax
511; SSE3-NEXT:    pextrw $1, %xmm0, %ecx
512; SSE3-NEXT:    subl %ecx, %eax
513; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
514; SSE3-NEXT:    retq
515;
516; AVX-LABEL: extract_extract_v32i16_sub_i16:
517; AVX:       # %bb.0:
518; AVX-NEXT:    vmovd %xmm0, %eax
519; AVX-NEXT:    vpextrw $1, %xmm0, %ecx
520; AVX-NEXT:    subl %ecx, %eax
521; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
522; AVX-NEXT:    vzeroupper
523; AVX-NEXT:    retq
524  %x0 = extractelement <32 x i16> %x, i32 0
525  %x1 = extractelement <32 x i16> %x, i32 1
526  %x01 = sub i16 %x0, %x1
527  ret i16 %x01
528}
529
530define i16 @extract_extract_v32i16_sub_i16_commute(<32 x i16> %x) {
531; SSE3-LABEL: extract_extract_v32i16_sub_i16_commute:
532; SSE3:       # %bb.0:
533; SSE3-NEXT:    movd %xmm0, %ecx
534; SSE3-NEXT:    pextrw $1, %xmm0, %eax
535; SSE3-NEXT:    subl %ecx, %eax
536; SSE3-NEXT:    # kill: def $ax killed $ax killed $eax
537; SSE3-NEXT:    retq
538;
539; AVX-LABEL: extract_extract_v32i16_sub_i16_commute:
540; AVX:       # %bb.0:
541; AVX-NEXT:    vmovd %xmm0, %ecx
542; AVX-NEXT:    vpextrw $1, %xmm0, %eax
543; AVX-NEXT:    subl %ecx, %eax
544; AVX-NEXT:    # kill: def $ax killed $ax killed $eax
545; AVX-NEXT:    vzeroupper
546; AVX-NEXT:    retq
547  %x0 = extractelement <32 x i16> %x, i32 0
548  %x1 = extractelement <32 x i16> %x, i32 1
549  %x01 = sub i16 %x1, %x0
550  ret i16 %x01
551}
552
553; Check output when 1 or both extracts have extra uses.
554
555define i32 @extract_extract_v4i32_add_i32_uses1(<4 x i32> %x, i32* %p) {
556; SSE3-LABEL: extract_extract_v4i32_add_i32_uses1:
557; SSE3:       # %bb.0:
558; SSE3-NEXT:    movd %xmm0, %ecx
559; SSE3-NEXT:    movd %xmm0, (%rdi)
560; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
561; SSE3-NEXT:    movd %xmm0, %eax
562; SSE3-NEXT:    addl %ecx, %eax
563; SSE3-NEXT:    retq
564;
565; AVX-LABEL: extract_extract_v4i32_add_i32_uses1:
566; AVX:       # %bb.0:
567; AVX-NEXT:    vmovd %xmm0, %ecx
568; AVX-NEXT:    vmovd %xmm0, (%rdi)
569; AVX-NEXT:    vpextrd $1, %xmm0, %eax
570; AVX-NEXT:    addl %ecx, %eax
571; AVX-NEXT:    retq
572  %x0 = extractelement <4 x i32> %x, i32 0
573  store i32 %x0, i32* %p
574  %x1 = extractelement <4 x i32> %x, i32 1
575  %x01 = add i32 %x0, %x1
576  ret i32 %x01
577}
578
579define i32 @extract_extract_v4i32_add_i32_uses2(<4 x i32> %x, i32* %p) {
580; SSE3-LABEL: extract_extract_v4i32_add_i32_uses2:
581; SSE3:       # %bb.0:
582; SSE3-NEXT:    movd %xmm0, %ecx
583; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
584; SSE3-NEXT:    movd %xmm0, %eax
585; SSE3-NEXT:    addl %ecx, %eax
586; SSE3-NEXT:    movd %xmm0, (%rdi)
587; SSE3-NEXT:    retq
588;
589; AVX-LABEL: extract_extract_v4i32_add_i32_uses2:
590; AVX:       # %bb.0:
591; AVX-NEXT:    vmovd %xmm0, %ecx
592; AVX-NEXT:    vpextrd $1, %xmm0, %eax
593; AVX-NEXT:    addl %ecx, %eax
594; AVX-NEXT:    vpextrd $1, %xmm0, (%rdi)
595; AVX-NEXT:    retq
596  %x0 = extractelement <4 x i32> %x, i32 0
597  %x1 = extractelement <4 x i32> %x, i32 1
598  store i32 %x1, i32* %p
599  %x01 = add i32 %x0, %x1
600  ret i32 %x01
601}
602
603define i32 @extract_extract_v4i32_add_i32_uses3(<4 x i32> %x, i32* %p1, i32* %p2) {
604; SSE3-LABEL: extract_extract_v4i32_add_i32_uses3:
605; SSE3:       # %bb.0:
606; SSE3-NEXT:    movd %xmm0, %ecx
607; SSE3-NEXT:    movd %xmm0, (%rdi)
608; SSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[1,1,2,3]
609; SSE3-NEXT:    movd %xmm0, %eax
610; SSE3-NEXT:    addl %ecx, %eax
611; SSE3-NEXT:    movd %xmm0, (%rsi)
612; SSE3-NEXT:    retq
613;
614; AVX-LABEL: extract_extract_v4i32_add_i32_uses3:
615; AVX:       # %bb.0:
616; AVX-NEXT:    vmovd %xmm0, %ecx
617; AVX-NEXT:    vmovd %xmm0, (%rdi)
618; AVX-NEXT:    vpextrd $1, %xmm0, %eax
619; AVX-NEXT:    addl %ecx, %eax
620; AVX-NEXT:    vpextrd $1, %xmm0, (%rsi)
621; AVX-NEXT:    retq
622  %x0 = extractelement <4 x i32> %x, i32 0
623  store i32 %x0, i32* %p1
624  %x1 = extractelement <4 x i32> %x, i32 1
625  store i32 %x1, i32* %p2
626  %x01 = add i32 %x0, %x1
627  ret i32 %x01
628}
629
630