1; RUN: llc < %s -mtriple=i686-apple-darwin9 -mattr=sse4.1 -mcpu=penryn | FileCheck %s -check-prefix=X32
2; RUN: llc < %s -mtriple=x86_64-apple-darwin9 -mattr=sse4.1 -mcpu=penryn | FileCheck %s -check-prefix=X64
3
4@g16 = external global i16
5
6define <4 x i32> @pinsrd_1(i32 %s, <4 x i32> %tmp) nounwind {
7        %tmp1 = insertelement <4 x i32> %tmp, i32 %s, i32 1
8        ret <4 x i32> %tmp1
9; X32-LABEL: pinsrd_1:
10; X32:    pinsrd $1, 4(%esp), %xmm0
11
12; X64-LABEL: pinsrd_1:
13; X64:    pinsrd $1, %edi, %xmm0
14}
15
16define <16 x i8> @pinsrb_1(i8 %s, <16 x i8> %tmp) nounwind {
17        %tmp1 = insertelement <16 x i8> %tmp, i8 %s, i32 1
18        ret <16 x i8> %tmp1
19; X32-LABEL: pinsrb_1:
20; X32:    pinsrb $1, 4(%esp), %xmm0
21
22; X64-LABEL: pinsrb_1:
23; X64:    pinsrb $1, %edi, %xmm0
24}
25
26
27define <2 x i64> @pmovsxbd_1(i32* %p) nounwind {
28entry:
29	%0 = load i32* %p, align 4
30	%1 = insertelement <4 x i32> undef, i32 %0, i32 0
31	%2 = insertelement <4 x i32> %1, i32 0, i32 1
32	%3 = insertelement <4 x i32> %2, i32 0, i32 2
33	%4 = insertelement <4 x i32> %3, i32 0, i32 3
34	%5 = bitcast <4 x i32> %4 to <16 x i8>
35	%6 = tail call <4 x i32> @llvm.x86.sse41.pmovsxbd(<16 x i8> %5) nounwind readnone
36	%7 = bitcast <4 x i32> %6 to <2 x i64>
37	ret <2 x i64> %7
38
39; X32: _pmovsxbd_1:
40; X32:   movl      4(%esp), %eax
41; X32:   pmovsxbd   (%eax), %xmm0
42
43; X64: _pmovsxbd_1:
44; X64:   pmovsxbd   (%rdi), %xmm0
45}
46
47define <2 x i64> @pmovsxwd_1(i64* %p) nounwind readonly {
48entry:
49	%0 = load i64* %p		; <i64> [#uses=1]
50	%tmp2 = insertelement <2 x i64> zeroinitializer, i64 %0, i32 0		; <<2 x i64>> [#uses=1]
51	%1 = bitcast <2 x i64> %tmp2 to <8 x i16>		; <<8 x i16>> [#uses=1]
52	%2 = tail call <4 x i32> @llvm.x86.sse41.pmovsxwd(<8 x i16> %1) nounwind readnone		; <<4 x i32>> [#uses=1]
53	%3 = bitcast <4 x i32> %2 to <2 x i64>		; <<2 x i64>> [#uses=1]
54	ret <2 x i64> %3
55
56; X32: _pmovsxwd_1:
57; X32:   movl 4(%esp), %eax
58; X32:   pmovsxwd (%eax), %xmm0
59
60; X64: _pmovsxwd_1:
61; X64:   pmovsxwd (%rdi), %xmm0
62}
63
64
65
66
67define <2 x i64> @pmovzxbq_1() nounwind {
68entry:
69	%0 = load i16* @g16, align 2		; <i16> [#uses=1]
70	%1 = insertelement <8 x i16> undef, i16 %0, i32 0		; <<8 x i16>> [#uses=1]
71	%2 = bitcast <8 x i16> %1 to <16 x i8>		; <<16 x i8>> [#uses=1]
72	%3 = tail call <2 x i64> @llvm.x86.sse41.pmovzxbq(<16 x i8> %2) nounwind readnone		; <<2 x i64>> [#uses=1]
73	ret <2 x i64> %3
74
75; X32: _pmovzxbq_1:
76; X32:   movl	L_g16$non_lazy_ptr, %eax
77; X32:   pmovzxbq	(%eax), %xmm0
78
79; X64: _pmovzxbq_1:
80; X64:   movq	_g16@GOTPCREL(%rip), %rax
81; X64:   pmovzxbq	(%rax), %xmm0
82}
83
84declare <4 x i32> @llvm.x86.sse41.pmovsxbd(<16 x i8>) nounwind readnone
85declare <4 x i32> @llvm.x86.sse41.pmovsxwd(<8 x i16>) nounwind readnone
86declare <2 x i64> @llvm.x86.sse41.pmovzxbq(<16 x i8>) nounwind readnone
87
88
89
90
91define i32 @extractps_1(<4 x float> %v) nounwind {
92  %s = extractelement <4 x float> %v, i32 3
93  %i = bitcast float %s to i32
94  ret i32 %i
95
96; X32: _extractps_1:
97; X32:	  extractps	$3, %xmm0, %eax
98
99; X64: _extractps_1:
100; X64:	  extractps	$3, %xmm0, %eax
101}
102define i32 @extractps_2(<4 x float> %v) nounwind {
103  %t = bitcast <4 x float> %v to <4 x i32>
104  %s = extractelement <4 x i32> %t, i32 3
105  ret i32 %s
106
107; X32: _extractps_2:
108; X32:	  extractps	$3, %xmm0, %eax
109
110; X64: _extractps_2:
111; X64:	  extractps	$3, %xmm0, %eax
112}
113
114
115; The non-store form of extractps puts its result into a GPR.
116; This makes it suitable for an extract from a <4 x float> that
117; is bitcasted to i32, but unsuitable for much of anything else.
118
119define float @ext_1(<4 x float> %v) nounwind {
120  %s = extractelement <4 x float> %v, i32 3
121  %t = fadd float %s, 1.0
122  ret float %t
123
124; X32: _ext_1:
125; X32:	  pshufd	$3, %xmm0, %xmm0
126; X32:	  addss	LCPI7_0, %xmm0
127
128; X64: _ext_1:
129; X64:	  pshufd	$3, %xmm0, %xmm0
130; X64:	  addss	LCPI7_0(%rip), %xmm0
131}
132define float @ext_2(<4 x float> %v) nounwind {
133  %s = extractelement <4 x float> %v, i32 3
134  ret float %s
135
136; X32: _ext_2:
137; X32:	  pshufd	$3, %xmm0, %xmm0
138
139; X64: _ext_2:
140; X64:	  pshufd	$3, %xmm0, %xmm0
141}
142define i32 @ext_3(<4 x i32> %v) nounwind {
143  %i = extractelement <4 x i32> %v, i32 3
144  ret i32 %i
145
146; X32: _ext_3:
147; X32:	  pextrd	$3, %xmm0, %eax
148
149; X64: _ext_3:
150; X64:	  pextrd	$3, %xmm0, %eax
151}
152
153define <4 x float> @insertps_1(<4 x float> %t1, <4 x float> %t2) nounwind {
154        %tmp1 = call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %t1, <4 x float> %t2, i32 1) nounwind readnone
155        ret <4 x float> %tmp1
156; X32: _insertps_1:
157; X32:    insertps  $1, %xmm1, %xmm0
158
159; X64: _insertps_1:
160; X64:    insertps  $1, %xmm1, %xmm0
161}
162
163declare <4 x float> @llvm.x86.sse41.insertps(<4 x float>, <4 x float>, i32) nounwind readnone
164
165define <4 x float> @insertps_2(<4 x float> %t1, float %t2) nounwind {
166        %tmp1 = insertelement <4 x float> %t1, float %t2, i32 0
167        ret <4 x float> %tmp1
168; X32: _insertps_2:
169; X32:    insertps  $0, 4(%esp), %xmm0
170
171; X64: _insertps_2:
172; X64:    insertps  $0, %xmm1, %xmm0
173}
174
175define <4 x float> @insertps_3(<4 x float> %t1, <4 x float> %t2) nounwind {
176        %tmp2 = extractelement <4 x float> %t2, i32 0
177        %tmp1 = insertelement <4 x float> %t1, float %tmp2, i32 0
178        ret <4 x float> %tmp1
179; X32: _insertps_3:
180; X32:    insertps  $0, %xmm1, %xmm0
181
182; X64: _insertps_3:
183; X64:    insertps  $0, %xmm1, %xmm0
184}
185
186define i32 @ptestz_1(<2 x i64> %t1, <2 x i64> %t2) nounwind {
187        %tmp1 = call i32 @llvm.x86.sse41.ptestz(<2 x i64> %t1, <2 x i64> %t2) nounwind readnone
188        ret i32 %tmp1
189; X32: _ptestz_1:
190; X32:    ptest 	%xmm1, %xmm0
191; X32:    sete	%al
192
193; X64: _ptestz_1:
194; X64:    ptest 	%xmm1, %xmm0
195; X64:    sete	%al
196}
197
198define i32 @ptestz_2(<2 x i64> %t1, <2 x i64> %t2) nounwind {
199        %tmp1 = call i32 @llvm.x86.sse41.ptestc(<2 x i64> %t1, <2 x i64> %t2) nounwind readnone
200        ret i32 %tmp1
201; X32: _ptestz_2:
202; X32:    ptest 	%xmm1, %xmm0
203; X32:    sbbl	%eax
204
205; X64: _ptestz_2:
206; X64:    ptest 	%xmm1, %xmm0
207; X64:    sbbl	%eax
208}
209
210define i32 @ptestz_3(<2 x i64> %t1, <2 x i64> %t2) nounwind {
211        %tmp1 = call i32 @llvm.x86.sse41.ptestnzc(<2 x i64> %t1, <2 x i64> %t2) nounwind readnone
212        ret i32 %tmp1
213; X32: _ptestz_3:
214; X32:    ptest 	%xmm1, %xmm0
215; X32:    seta	%al
216
217; X64: _ptestz_3:
218; X64:    ptest 	%xmm1, %xmm0
219; X64:    seta	%al
220}
221
222
223declare i32 @llvm.x86.sse41.ptestz(<2 x i64>, <2 x i64>) nounwind readnone
224declare i32 @llvm.x86.sse41.ptestc(<2 x i64>, <2 x i64>) nounwind readnone
225declare i32 @llvm.x86.sse41.ptestnzc(<2 x i64>, <2 x i64>) nounwind readnone
226
227; This used to compile to insertps $0  + insertps $16.  insertps $0 is always
228; pointless.
229define <2 x float> @buildvector(<2 x float> %A, <2 x float> %B) nounwind  {
230entry:
231  %tmp7 = extractelement <2 x float> %A, i32 0
232  %tmp5 = extractelement <2 x float> %A, i32 1
233  %tmp3 = extractelement <2 x float> %B, i32 0
234  %tmp1 = extractelement <2 x float> %B, i32 1
235  %add.r = fadd float %tmp7, %tmp3
236  %add.i = fadd float %tmp5, %tmp1
237  %tmp11 = insertelement <2 x float> undef, float %add.r, i32 0
238  %tmp9 = insertelement <2 x float> %tmp11, float %add.i, i32 1
239  ret <2 x float> %tmp9
240; X32-LABEL: buildvector:
241; X32-NOT: insertps $0
242; X32: insertps $16
243; X32-NOT: insertps $0
244; X32: ret
245; X64-LABEL: buildvector:
246; X64-NOT: insertps $0
247; X64: insertps $16
248; X64-NOT: insertps $0
249; X64: ret
250}
251
252