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; X32-LABEL: pinsrd_1:
8; X32:       ## BB#0:
9; X32-NEXT:    pinsrd $1, {{[0-9]+}}(%esp), %xmm0
10; X32-NEXT:    retl
11;
12; X64-LABEL: pinsrd_1:
13; X64:       ## BB#0:
14; X64-NEXT:    pinsrd $1, %edi, %xmm0
15; X64-NEXT:    retq
16  %tmp1 = insertelement <4 x i32> %tmp, i32 %s, i32 1
17  ret <4 x i32> %tmp1
18}
19
20define <16 x i8> @pinsrb_1(i8 %s, <16 x i8> %tmp) nounwind {
21; X32-LABEL: pinsrb_1:
22; X32:       ## BB#0:
23; X32-NEXT:    pinsrb $1, {{[0-9]+}}(%esp), %xmm0
24; X32-NEXT:    retl
25;
26; X64-LABEL: pinsrb_1:
27; X64:       ## BB#0:
28; X64-NEXT:    pinsrb $1, %edi, %xmm0
29; X64-NEXT:    retq
30  %tmp1 = insertelement <16 x i8> %tmp, i8 %s, i32 1
31  ret <16 x i8> %tmp1
32}
33
34define <2 x i64> @pmovzxbq_1() nounwind {
35; X32-LABEL: pmovzxbq_1:
36; X32:       ## BB#0: ## %entry
37; X32-NEXT:    movl L_g16$non_lazy_ptr, %eax
38; X32-NEXT:    pmovzxbq {{.*#+}} xmm0 = mem[0],zero,zero,zero,zero,zero,zero,zero,mem[1],zero,zero,zero,zero,zero,zero,zero
39; X32-NEXT:    retl
40;
41; X64-LABEL: pmovzxbq_1:
42; X64:       ## BB#0: ## %entry
43; X64-NEXT:    movq _g16@{{.*}}(%rip), %rax
44; X64-NEXT:    pmovzxbq {{.*#+}} xmm0 = mem[0],zero,zero,zero,zero,zero,zero,zero,mem[1],zero,zero,zero,zero,zero,zero,zero
45; X64-NEXT:    retq
46entry:
47	%0 = load i16, i16* @g16, align 2		; <i16> [#uses=1]
48	%1 = insertelement <8 x i16> undef, i16 %0, i32 0		; <<8 x i16>> [#uses=1]
49	%2 = bitcast <8 x i16> %1 to <16 x i8>		; <<16 x i8>> [#uses=1]
50	%3 = tail call <2 x i64> @llvm.x86.sse41.pmovzxbq(<16 x i8> %2) nounwind readnone		; <<2 x i64>> [#uses=1]
51	ret <2 x i64> %3
52}
53
54declare <2 x i64> @llvm.x86.sse41.pmovzxbq(<16 x i8>) nounwind readnone
55
56define i32 @extractps_1(<4 x float> %v) nounwind {
57; X32-LABEL: extractps_1:
58; X32:       ## BB#0:
59; X32-NEXT:    extractps $3, %xmm0, %eax
60; X32-NEXT:    retl
61;
62; X64-LABEL: extractps_1:
63; X64:       ## BB#0:
64; X64-NEXT:    extractps $3, %xmm0, %eax
65; X64-NEXT:    retq
66  %s = extractelement <4 x float> %v, i32 3
67  %i = bitcast float %s to i32
68  ret i32 %i
69}
70define i32 @extractps_2(<4 x float> %v) nounwind {
71; X32-LABEL: extractps_2:
72; X32:       ## BB#0:
73; X32-NEXT:    extractps $3, %xmm0, %eax
74; X32-NEXT:    retl
75;
76; X64-LABEL: extractps_2:
77; X64:       ## BB#0:
78; X64-NEXT:    extractps $3, %xmm0, %eax
79; X64-NEXT:    retq
80  %t = bitcast <4 x float> %v to <4 x i32>
81  %s = extractelement <4 x i32> %t, i32 3
82  ret i32 %s
83}
84
85
86; The non-store form of extractps puts its result into a GPR.
87; This makes it suitable for an extract from a <4 x float> that
88; is bitcasted to i32, but unsuitable for much of anything else.
89
90define float @ext_1(<4 x float> %v) nounwind {
91; X32-LABEL: ext_1:
92; X32:       ## BB#0:
93; X32-NEXT:    pushl %eax
94; X32-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,1,2,3]
95; X32-NEXT:    addss LCPI5_0, %xmm0
96; X32-NEXT:    movss %xmm0, (%esp)
97; X32-NEXT:    flds (%esp)
98; X32-NEXT:    popl %eax
99; X32-NEXT:    retl
100;
101; X64-LABEL: ext_1:
102; X64:       ## BB#0:
103; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,1,2,3]
104; X64-NEXT:    addss {{.*}}(%rip), %xmm0
105; X64-NEXT:    retq
106  %s = extractelement <4 x float> %v, i32 3
107  %t = fadd float %s, 1.0
108  ret float %t
109}
110define float @ext_2(<4 x float> %v) nounwind {
111; X32-LABEL: ext_2:
112; X32:       ## BB#0:
113; X32-NEXT:    pushl %eax
114; X32-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,1,2,3]
115; X32-NEXT:    movss %xmm0, (%esp)
116; X32-NEXT:    flds (%esp)
117; X32-NEXT:    popl %eax
118; X32-NEXT:    retl
119;
120; X64-LABEL: ext_2:
121; X64:       ## BB#0:
122; X64-NEXT:    shufps {{.*#+}} xmm0 = xmm0[3,1,2,3]
123; X64-NEXT:    retq
124  %s = extractelement <4 x float> %v, i32 3
125  ret float %s
126}
127define i32 @ext_3(<4 x i32> %v) nounwind {
128; X32-LABEL: ext_3:
129; X32:       ## BB#0:
130; X32-NEXT:    pextrd $3, %xmm0, %eax
131; X32-NEXT:    retl
132;
133; X64-LABEL: ext_3:
134; X64:       ## BB#0:
135; X64-NEXT:    pextrd $3, %xmm0, %eax
136; X64-NEXT:    retq
137  %i = extractelement <4 x i32> %v, i32 3
138  ret i32 %i
139}
140
141define <4 x float> @insertps_1(<4 x float> %t1, <4 x float> %t2) nounwind {
142; X32-LABEL: insertps_1:
143; X32:       ## BB#0:
144; X32-NEXT:    insertps {{.*#+}} xmm0 = zero,xmm1[0],zero,xmm0[3]
145; X32-NEXT:    retl
146;
147; X64-LABEL: insertps_1:
148; X64:       ## BB#0:
149; X64-NEXT:    insertps {{.*#+}} xmm0 = zero,xmm1[0],zero,xmm0[3]
150; X64-NEXT:    retq
151  %tmp1 = call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %t1, <4 x float> %t2, i32 21) nounwind readnone
152  ret <4 x float> %tmp1
153}
154
155declare <4 x float> @llvm.x86.sse41.insertps(<4 x float>, <4 x float>, i32) nounwind readnone
156
157; When optimizing for speed, prefer blendps over insertps even if it means we have to
158; generate a separate movss to load the scalar operand.
159define <4 x float> @blendps_not_insertps_1(<4 x float> %t1, float %t2) nounwind {
160; X32-LABEL: blendps_not_insertps_1:
161; X32:       ## BB#0:
162; X32-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
163; X32-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
164; X32-NEXT:    retl
165;
166; X64-LABEL: blendps_not_insertps_1:
167; X64:       ## BB#0:
168; X64-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
169; X64-NEXT:    retq
170  %tmp1 = insertelement <4 x float> %t1, float %t2, i32 0
171  ret <4 x float> %tmp1
172}
173
174; When optimizing for size, generate an insertps if there's a load fold opportunity.
175; The difference between i386 and x86-64 ABIs for the float operand means we should
176; generate an insertps for X32 but not for X64!
177define <4 x float> @insertps_or_blendps(<4 x float> %t1, float %t2) minsize nounwind {
178; X32-LABEL: insertps_or_blendps:
179; X32:       ## BB#0:
180; X32-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
181; X32-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
182; X32-NEXT:    retl
183;
184; X64-LABEL: insertps_or_blendps:
185; X64:       ## BB#0:
186; X64-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
187; X64-NEXT:    retq
188  %tmp1 = insertelement <4 x float> %t1, float %t2, i32 0
189  ret <4 x float> %tmp1
190}
191
192; An insert into the low 32-bits of a vector from the low 32-bits of another vector
193; is always just a blendps because blendps is never more expensive than insertps.
194define <4 x float> @blendps_not_insertps_2(<4 x float> %t1, <4 x float> %t2) nounwind {
195; X32-LABEL: blendps_not_insertps_2:
196; X32:       ## BB#0:
197; X32-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
198; X32-NEXT:    retl
199;
200; X64-LABEL: blendps_not_insertps_2:
201; X64:       ## BB#0:
202; X64-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1,2,3]
203; X64-NEXT:    retq
204  %tmp2 = extractelement <4 x float> %t2, i32 0
205  %tmp1 = insertelement <4 x float> %t1, float %tmp2, i32 0
206  ret <4 x float> %tmp1
207}
208
209define i32 @ptestz_1(<2 x i64> %t1, <2 x i64> %t2) nounwind {
210; X32-LABEL: ptestz_1:
211; X32:       ## BB#0:
212; X32-NEXT:    xorl %eax, %eax
213; X32-NEXT:    ptest %xmm1, %xmm0
214; X32-NEXT:    sete %al
215; X32-NEXT:    retl
216;
217; X64-LABEL: ptestz_1:
218; X64:       ## BB#0:
219; X64-NEXT:    xorl %eax, %eax
220; X64-NEXT:    ptest %xmm1, %xmm0
221; X64-NEXT:    sete %al
222; X64-NEXT:    retq
223  %tmp1 = call i32 @llvm.x86.sse41.ptestz(<2 x i64> %t1, <2 x i64> %t2) nounwind readnone
224  ret i32 %tmp1
225}
226
227define i32 @ptestz_2(<2 x i64> %t1, <2 x i64> %t2) nounwind {
228; X32-LABEL: ptestz_2:
229; X32:       ## BB#0:
230; X32-NEXT:    ptest %xmm1, %xmm0
231; X32-NEXT:    sbbl %eax, %eax
232; X32-NEXT:    andl $1, %eax
233; X32-NEXT:    retl
234;
235; X64-LABEL: ptestz_2:
236; X64:       ## BB#0:
237; X64-NEXT:    ptest %xmm1, %xmm0
238; X64-NEXT:    sbbl %eax, %eax
239; X64-NEXT:    andl $1, %eax
240; X64-NEXT:    retq
241  %tmp1 = call i32 @llvm.x86.sse41.ptestc(<2 x i64> %t1, <2 x i64> %t2) nounwind readnone
242  ret i32 %tmp1
243}
244
245define i32 @ptestz_3(<2 x i64> %t1, <2 x i64> %t2) nounwind {
246; X32-LABEL: ptestz_3:
247; X32:       ## BB#0:
248; X32-NEXT:    xorl %eax, %eax
249; X32-NEXT:    ptest %xmm1, %xmm0
250; X32-NEXT:    seta %al
251; X32-NEXT:    retl
252;
253; X64-LABEL: ptestz_3:
254; X64:       ## BB#0:
255; X64-NEXT:    xorl %eax, %eax
256; X64-NEXT:    ptest %xmm1, %xmm0
257; X64-NEXT:    seta %al
258; X64-NEXT:    retq
259  %tmp1 = call i32 @llvm.x86.sse41.ptestnzc(<2 x i64> %t1, <2 x i64> %t2) nounwind readnone
260  ret i32 %tmp1
261}
262
263
264declare i32 @llvm.x86.sse41.ptestz(<2 x i64>, <2 x i64>) nounwind readnone
265declare i32 @llvm.x86.sse41.ptestc(<2 x i64>, <2 x i64>) nounwind readnone
266declare i32 @llvm.x86.sse41.ptestnzc(<2 x i64>, <2 x i64>) nounwind readnone
267
268; This used to compile to insertps $0  + insertps $16.  insertps $0 is always
269; pointless.
270define <2 x float> @buildvector(<2 x float> %A, <2 x float> %B) nounwind  {
271; X32-LABEL: buildvector:
272; X32:       ## BB#0: ## %entry
273; X32-NEXT:    movshdup {{.*#+}} xmm2 = xmm0[1,1,3,3]
274; X32-NEXT:    movshdup {{.*#+}} xmm3 = xmm1[1,1,3,3]
275; X32-NEXT:    addss %xmm1, %xmm0
276; X32-NEXT:    addss %xmm2, %xmm3
277; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[2,3]
278; X32-NEXT:    retl
279;
280; X64-LABEL: buildvector:
281; X64:       ## BB#0: ## %entry
282; X64-NEXT:    movshdup {{.*#+}} xmm2 = xmm0[1,1,3,3]
283; X64-NEXT:    movshdup {{.*#+}} xmm3 = xmm1[1,1,3,3]
284; X64-NEXT:    addss %xmm1, %xmm0
285; X64-NEXT:    addss %xmm2, %xmm3
286; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],xmm3[0],xmm0[2,3]
287; X64-NEXT:    retq
288entry:
289  %tmp7 = extractelement <2 x float> %A, i32 0
290  %tmp5 = extractelement <2 x float> %A, i32 1
291  %tmp3 = extractelement <2 x float> %B, i32 0
292  %tmp1 = extractelement <2 x float> %B, i32 1
293  %add.r = fadd float %tmp7, %tmp3
294  %add.i = fadd float %tmp5, %tmp1
295  %tmp11 = insertelement <2 x float> undef, float %add.r, i32 0
296  %tmp9 = insertelement <2 x float> %tmp11, float %add.i, i32 1
297  ret <2 x float> %tmp9
298}
299
300define <4 x float> @insertps_from_shufflevector_1(<4 x float> %a, <4 x float>* nocapture readonly %pb) {
301; X32-LABEL: insertps_from_shufflevector_1:
302; X32:       ## BB#0: ## %entry
303; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
304; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
305; X32-NEXT:    retl
306;
307; X64-LABEL: insertps_from_shufflevector_1:
308; X64:       ## BB#0: ## %entry
309; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
310; X64-NEXT:    retq
311entry:
312  %0 = load <4 x float>, <4 x float>* %pb, align 16
313  %vecinit6 = shufflevector <4 x float> %a, <4 x float> %0, <4 x i32> <i32 0, i32 1, i32 2, i32 4>
314  ret <4 x float> %vecinit6
315}
316
317define <4 x float> @insertps_from_shufflevector_2(<4 x float> %a, <4 x float> %b) {
318; X32-LABEL: insertps_from_shufflevector_2:
319; X32:       ## BB#0: ## %entry
320; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[1],xmm0[3]
321; X32-NEXT:    retl
322;
323; X64-LABEL: insertps_from_shufflevector_2:
324; X64:       ## BB#0: ## %entry
325; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1],xmm1[1],xmm0[3]
326; X64-NEXT:    retq
327entry:
328  %vecinit6 = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 1, i32 5, i32 3>
329  ret <4 x float> %vecinit6
330}
331
332; For loading an i32 from memory into an xmm register we use pinsrd
333; instead of insertps
334define <4 x i32> @pinsrd_from_shufflevector_i32(<4 x i32> %a, <4 x i32>* nocapture readonly %pb) {
335; X32-LABEL: pinsrd_from_shufflevector_i32:
336; X32:       ## BB#0: ## %entry
337; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
338; X32-NEXT:    pshufd {{.*#+}} xmm1 = mem[0,1,2,0]
339; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5],xmm1[6,7]
340; X32-NEXT:    retl
341;
342; X64-LABEL: pinsrd_from_shufflevector_i32:
343; X64:       ## BB#0: ## %entry
344; X64-NEXT:    pshufd {{.*#+}} xmm1 = mem[0,1,2,0]
345; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5],xmm1[6,7]
346; X64-NEXT:    retq
347entry:
348  %0 = load <4 x i32>, <4 x i32>* %pb, align 16
349  %vecinit6 = shufflevector <4 x i32> %a, <4 x i32> %0, <4 x i32> <i32 0, i32 1, i32 2, i32 4>
350  ret <4 x i32> %vecinit6
351}
352
353define <4 x i32> @insertps_from_shufflevector_i32_2(<4 x i32> %a, <4 x i32> %b) {
354; X32-LABEL: insertps_from_shufflevector_i32_2:
355; X32:       ## BB#0: ## %entry
356; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[2,3,0,1]
357; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3],xmm0[4,5,6,7]
358; X32-NEXT:    retl
359;
360; X64-LABEL: insertps_from_shufflevector_i32_2:
361; X64:       ## BB#0: ## %entry
362; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[2,3,0,1]
363; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3],xmm0[4,5,6,7]
364; X64-NEXT:    retq
365entry:
366  %vecinit6 = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 7, i32 2, i32 3>
367  ret <4 x i32> %vecinit6
368}
369
370define <4 x float> @insertps_from_load_ins_elt_undef(<4 x float> %a, float* %b) {
371; X32-LABEL: insertps_from_load_ins_elt_undef:
372; X32:       ## BB#0:
373; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
374; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],mem[0],xmm0[2,3]
375; X32-NEXT:    retl
376;
377; X64-LABEL: insertps_from_load_ins_elt_undef:
378; X64:       ## BB#0:
379; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],mem[0],xmm0[2,3]
380; X64-NEXT:    retq
381  %1 = load float, float* %b, align 4
382  %2 = insertelement <4 x float> undef, float %1, i32 0
383  %result = shufflevector <4 x float> %a, <4 x float> %2, <4 x i32> <i32 0, i32 4, i32 2, i32 3>
384  ret <4 x float> %result
385}
386
387; TODO: Like on pinsrd_from_shufflevector_i32, remove this mov instr
388define <4 x i32> @insertps_from_load_ins_elt_undef_i32(<4 x i32> %a, i32* %b) {
389; X32-LABEL: insertps_from_load_ins_elt_undef_i32:
390; X32:       ## BB#0:
391; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
392; X32-NEXT:    movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
393; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,0,1]
394; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5],xmm0[6,7]
395; X32-NEXT:    retl
396;
397; X64-LABEL: insertps_from_load_ins_elt_undef_i32:
398; X64:       ## BB#0:
399; X64-NEXT:    movd {{.*#+}} xmm1 = mem[0],zero,zero,zero
400; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,0,1]
401; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5],xmm0[6,7]
402; X64-NEXT:    retq
403  %1 = load i32, i32* %b, align 4
404  %2 = insertelement <4 x i32> undef, i32 %1, i32 0
405  %result = shufflevector <4 x i32> %a, <4 x i32> %2, <4 x i32> <i32 0, i32 1, i32 4, i32 3>
406  ret <4 x i32> %result
407}
408
409;;;;;; Shuffles optimizable with a single insertps or blend instruction
410define <4 x float> @shuf_XYZ0(<4 x float> %x, <4 x float> %a) {
411; X32-LABEL: shuf_XYZ0:
412; X32:       ## BB#0:
413; X32-NEXT:    xorps %xmm1, %xmm1
414; X32-NEXT:    blendps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[3]
415; X32-NEXT:    retl
416;
417; X64-LABEL: shuf_XYZ0:
418; X64:       ## BB#0:
419; X64-NEXT:    xorps %xmm1, %xmm1
420; X64-NEXT:    blendps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[3]
421; X64-NEXT:    retq
422  %vecext = extractelement <4 x float> %x, i32 0
423  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
424  %vecext1 = extractelement <4 x float> %x, i32 1
425  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
426  %vecext3 = extractelement <4 x float> %x, i32 2
427  %vecinit4 = insertelement <4 x float> %vecinit2, float %vecext3, i32 2
428  %vecinit5 = insertelement <4 x float> %vecinit4, float 0.0, i32 3
429  ret <4 x float> %vecinit5
430}
431
432define <4 x float> @shuf_XY00(<4 x float> %x, <4 x float> %a) {
433; X32-LABEL: shuf_XY00:
434; X32:       ## BB#0:
435; X32-NEXT:    movq {{.*#+}} xmm0 = xmm0[0],zero
436; X32-NEXT:    retl
437;
438; X64-LABEL: shuf_XY00:
439; X64:       ## BB#0:
440; X64-NEXT:    movq {{.*#+}} xmm0 = xmm0[0],zero
441; X64-NEXT:    retq
442  %vecext = extractelement <4 x float> %x, i32 0
443  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
444  %vecext1 = extractelement <4 x float> %x, i32 1
445  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
446  %vecinit3 = insertelement <4 x float> %vecinit2, float 0.0, i32 2
447  %vecinit4 = insertelement <4 x float> %vecinit3, float 0.0, i32 3
448  ret <4 x float> %vecinit4
449}
450
451define <4 x float> @shuf_XYY0(<4 x float> %x, <4 x float> %a) {
452; X32-LABEL: shuf_XYY0:
453; X32:       ## BB#0:
454; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,1],zero
455; X32-NEXT:    retl
456;
457; X64-LABEL: shuf_XYY0:
458; X64:       ## BB#0:
459; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,1],zero
460; X64-NEXT:    retq
461  %vecext = extractelement <4 x float> %x, i32 0
462  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
463  %vecext1 = extractelement <4 x float> %x, i32 1
464  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
465  %vecinit4 = insertelement <4 x float> %vecinit2, float %vecext1, i32 2
466  %vecinit5 = insertelement <4 x float> %vecinit4, float 0.0, i32 3
467  ret <4 x float> %vecinit5
468}
469
470define <4 x float> @shuf_XYW0(<4 x float> %x, <4 x float> %a) {
471; X32-LABEL: shuf_XYW0:
472; X32:       ## BB#0:
473; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,3],zero
474; X32-NEXT:    retl
475;
476; X64-LABEL: shuf_XYW0:
477; X64:       ## BB#0:
478; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,3],zero
479; X64-NEXT:    retq
480  %vecext = extractelement <4 x float> %x, i32 0
481  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
482  %vecext1 = extractelement <4 x float> %x, i32 1
483  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
484  %vecext2 = extractelement <4 x float> %x, i32 3
485  %vecinit3 = insertelement <4 x float> %vecinit2, float %vecext2, i32 2
486  %vecinit4 = insertelement <4 x float> %vecinit3, float 0.0, i32 3
487  ret <4 x float> %vecinit4
488}
489
490define <4 x float> @shuf_W00W(<4 x float> %x, <4 x float> %a) {
491; X32-LABEL: shuf_W00W:
492; X32:       ## BB#0:
493; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[3],zero,zero,xmm0[3]
494; X32-NEXT:    retl
495;
496; X64-LABEL: shuf_W00W:
497; X64:       ## BB#0:
498; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[3],zero,zero,xmm0[3]
499; X64-NEXT:    retq
500  %vecext = extractelement <4 x float> %x, i32 3
501  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
502  %vecinit2 = insertelement <4 x float> %vecinit, float 0.0, i32 1
503  %vecinit3 = insertelement <4 x float> %vecinit2, float 0.0, i32 2
504  %vecinit4 = insertelement <4 x float> %vecinit3, float %vecext, i32 3
505  ret <4 x float> %vecinit4
506}
507
508define <4 x float> @shuf_X00A(<4 x float> %x, <4 x float> %a) {
509; X32-LABEL: shuf_X00A:
510; X32:       ## BB#0:
511; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,zero,xmm1[0]
512; X32-NEXT:    retl
513;
514; X64-LABEL: shuf_X00A:
515; X64:       ## BB#0:
516; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,zero,xmm1[0]
517; X64-NEXT:    retq
518  %vecext = extractelement <4 x float> %x, i32 0
519  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
520  %vecinit1 = insertelement <4 x float> %vecinit, float 0.0, i32 1
521  %vecinit2 = insertelement <4 x float> %vecinit1, float 0.0, i32 2
522  %vecinit4 = shufflevector <4 x float> %vecinit2, <4 x float> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 4>
523  ret <4 x float> %vecinit4
524}
525
526define <4 x float> @shuf_X00X(<4 x float> %x, <4 x float> %a) {
527; X32-LABEL: shuf_X00X:
528; X32:       ## BB#0:
529; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,zero,xmm0[0]
530; X32-NEXT:    retl
531;
532; X64-LABEL: shuf_X00X:
533; X64:       ## BB#0:
534; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,zero,xmm0[0]
535; X64-NEXT:    retq
536  %vecext = extractelement <4 x float> %x, i32 0
537  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
538  %vecinit1 = insertelement <4 x float> %vecinit, float 0.0, i32 1
539  %vecinit2 = insertelement <4 x float> %vecinit1, float 0.0, i32 2
540  %vecinit4 = shufflevector <4 x float> %vecinit2, <4 x float> %x, <4 x i32> <i32 0, i32 1, i32 2, i32 4>
541  ret <4 x float> %vecinit4
542}
543
544define <4 x float> @shuf_X0YC(<4 x float> %x, <4 x float> %a) {
545; X32-LABEL: shuf_X0YC:
546; X32:       ## BB#0:
547; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
548; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[2]
549; X32-NEXT:    retl
550;
551; X64-LABEL: shuf_X0YC:
552; X64:       ## BB#0:
553; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero
554; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm1[2]
555; X64-NEXT:    retq
556  %vecext = extractelement <4 x float> %x, i32 0
557  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
558  %vecinit1 = insertelement <4 x float> %vecinit, float 0.0, i32 1
559  %vecinit3 = shufflevector <4 x float> %vecinit1, <4 x float> %x, <4 x i32> <i32 0, i32 1, i32 5, i32 undef>
560  %vecinit5 = shufflevector <4 x float> %vecinit3, <4 x float> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 6>
561  ret <4 x float> %vecinit5
562}
563
564define <4 x i32> @i32_shuf_XYZ0(<4 x i32> %x, <4 x i32> %a) {
565; X32-LABEL: i32_shuf_XYZ0:
566; X32:       ## BB#0:
567; X32-NEXT:    pxor %xmm1, %xmm1
568; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5],xmm1[6,7]
569; X32-NEXT:    retl
570;
571; X64-LABEL: i32_shuf_XYZ0:
572; X64:       ## BB#0:
573; X64-NEXT:    pxor %xmm1, %xmm1
574; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5],xmm1[6,7]
575; X64-NEXT:    retq
576  %vecext = extractelement <4 x i32> %x, i32 0
577  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
578  %vecext1 = extractelement <4 x i32> %x, i32 1
579  %vecinit2 = insertelement <4 x i32> %vecinit, i32 %vecext1, i32 1
580  %vecext3 = extractelement <4 x i32> %x, i32 2
581  %vecinit4 = insertelement <4 x i32> %vecinit2, i32 %vecext3, i32 2
582  %vecinit5 = insertelement <4 x i32> %vecinit4, i32 0, i32 3
583  ret <4 x i32> %vecinit5
584}
585
586define <4 x i32> @i32_shuf_XY00(<4 x i32> %x, <4 x i32> %a) {
587; X32-LABEL: i32_shuf_XY00:
588; X32:       ## BB#0:
589; X32-NEXT:    movq {{.*#+}} xmm0 = xmm0[0],zero
590; X32-NEXT:    retl
591;
592; X64-LABEL: i32_shuf_XY00:
593; X64:       ## BB#0:
594; X64-NEXT:    movq {{.*#+}} xmm0 = xmm0[0],zero
595; X64-NEXT:    retq
596  %vecext = extractelement <4 x i32> %x, i32 0
597  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
598  %vecext1 = extractelement <4 x i32> %x, i32 1
599  %vecinit2 = insertelement <4 x i32> %vecinit, i32 %vecext1, i32 1
600  %vecinit3 = insertelement <4 x i32> %vecinit2, i32 0, i32 2
601  %vecinit4 = insertelement <4 x i32> %vecinit3, i32 0, i32 3
602  ret <4 x i32> %vecinit4
603}
604
605define <4 x i32> @i32_shuf_XYY0(<4 x i32> %x, <4 x i32> %a) {
606; X32-LABEL: i32_shuf_XYY0:
607; X32:       ## BB#0:
608; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm0[0,1,1,3]
609; X32-NEXT:    pxor %xmm0, %xmm0
610; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm1[0,1,2,3,4,5],xmm0[6,7]
611; X32-NEXT:    retl
612;
613; X64-LABEL: i32_shuf_XYY0:
614; X64:       ## BB#0:
615; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm0[0,1,1,3]
616; X64-NEXT:    pxor %xmm0, %xmm0
617; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm1[0,1,2,3,4,5],xmm0[6,7]
618; X64-NEXT:    retq
619  %vecext = extractelement <4 x i32> %x, i32 0
620  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
621  %vecext1 = extractelement <4 x i32> %x, i32 1
622  %vecinit2 = insertelement <4 x i32> %vecinit, i32 %vecext1, i32 1
623  %vecinit4 = insertelement <4 x i32> %vecinit2, i32 %vecext1, i32 2
624  %vecinit5 = insertelement <4 x i32> %vecinit4, i32 0, i32 3
625  ret <4 x i32> %vecinit5
626}
627
628define <4 x i32> @i32_shuf_XYW0(<4 x i32> %x, <4 x i32> %a) {
629; X32-LABEL: i32_shuf_XYW0:
630; X32:       ## BB#0:
631; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm0[0,1,3,3]
632; X32-NEXT:    pxor %xmm0, %xmm0
633; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm1[0,1,2,3,4,5],xmm0[6,7]
634; X32-NEXT:    retl
635;
636; X64-LABEL: i32_shuf_XYW0:
637; X64:       ## BB#0:
638; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm0[0,1,3,3]
639; X64-NEXT:    pxor %xmm0, %xmm0
640; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm1[0,1,2,3,4,5],xmm0[6,7]
641; X64-NEXT:    retq
642  %vecext = extractelement <4 x i32> %x, i32 0
643  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
644  %vecext1 = extractelement <4 x i32> %x, i32 1
645  %vecinit2 = insertelement <4 x i32> %vecinit, i32 %vecext1, i32 1
646  %vecext2 = extractelement <4 x i32> %x, i32 3
647  %vecinit3 = insertelement <4 x i32> %vecinit2, i32 %vecext2, i32 2
648  %vecinit4 = insertelement <4 x i32> %vecinit3, i32 0, i32 3
649  ret <4 x i32> %vecinit4
650}
651
652define <4 x i32> @i32_shuf_W00W(<4 x i32> %x, <4 x i32> %a) {
653; X32-LABEL: i32_shuf_W00W:
654; X32:       ## BB#0:
655; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm0[3,1,2,3]
656; X32-NEXT:    pxor %xmm0, %xmm0
657; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3,4,5],xmm1[6,7]
658; X32-NEXT:    retl
659;
660; X64-LABEL: i32_shuf_W00W:
661; X64:       ## BB#0:
662; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm0[3,1,2,3]
663; X64-NEXT:    pxor %xmm0, %xmm0
664; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm1[0,1],xmm0[2,3,4,5],xmm1[6,7]
665; X64-NEXT:    retq
666  %vecext = extractelement <4 x i32> %x, i32 3
667  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
668  %vecinit2 = insertelement <4 x i32> %vecinit, i32 0, i32 1
669  %vecinit3 = insertelement <4 x i32> %vecinit2, i32 0, i32 2
670  %vecinit4 = insertelement <4 x i32> %vecinit3, i32 %vecext, i32 3
671  ret <4 x i32> %vecinit4
672}
673
674define <4 x i32> @i32_shuf_X00A(<4 x i32> %x, <4 x i32> %a) {
675; X32-LABEL: i32_shuf_X00A:
676; X32:       ## BB#0:
677; X32-NEXT:    pxor %xmm2, %xmm2
678; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3,4,5,6,7]
679; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,2,0]
680; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5],xmm1[6,7]
681; X32-NEXT:    retl
682;
683; X64-LABEL: i32_shuf_X00A:
684; X64:       ## BB#0:
685; X64-NEXT:    pxor %xmm2, %xmm2
686; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm2[2,3,4,5,6,7]
687; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,2,0]
688; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,5],xmm1[6,7]
689; X64-NEXT:    retq
690  %vecext = extractelement <4 x i32> %x, i32 0
691  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
692  %vecinit1 = insertelement <4 x i32> %vecinit, i32 0, i32 1
693  %vecinit2 = insertelement <4 x i32> %vecinit1, i32 0, i32 2
694  %vecinit4 = shufflevector <4 x i32> %vecinit2, <4 x i32> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 4>
695  ret <4 x i32> %vecinit4
696}
697
698define <4 x i32> @i32_shuf_X00X(<4 x i32> %x, <4 x i32> %a) {
699; X32-LABEL: i32_shuf_X00X:
700; X32:       ## BB#0:
701; X32-NEXT:    pxor %xmm1, %xmm1
702; X32-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,1,2,0]
703; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3,4,5],xmm0[6,7]
704; X32-NEXT:    retl
705;
706; X64-LABEL: i32_shuf_X00X:
707; X64:       ## BB#0:
708; X64-NEXT:    pxor %xmm1, %xmm1
709; X64-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,1,2,0]
710; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1],xmm1[2,3,4,5],xmm0[6,7]
711; X64-NEXT:    retq
712  %vecext = extractelement <4 x i32> %x, i32 0
713  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
714  %vecinit1 = insertelement <4 x i32> %vecinit, i32 0, i32 1
715  %vecinit2 = insertelement <4 x i32> %vecinit1, i32 0, i32 2
716  %vecinit4 = shufflevector <4 x i32> %vecinit2, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 2, i32 4>
717  ret <4 x i32> %vecinit4
718}
719
720define <4 x i32> @i32_shuf_X0YC(<4 x i32> %x, <4 x i32> %a) {
721; X32-LABEL: i32_shuf_X0YC:
722; X32:       ## BB#0:
723; X32-NEXT:    pmovzxdq {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero
724; X32-NEXT:    pshufd {{.*#+}} xmm0 = xmm1[0,1,2,2]
725; X32-NEXT:    pblendw {{.*#+}} xmm0 = xmm2[0,1,2,3,4,5],xmm0[6,7]
726; X32-NEXT:    retl
727;
728; X64-LABEL: i32_shuf_X0YC:
729; X64:       ## BB#0:
730; X64-NEXT:    pmovzxdq {{.*#+}} xmm2 = xmm0[0],zero,xmm0[1],zero
731; X64-NEXT:    pshufd {{.*#+}} xmm0 = xmm1[0,1,2,2]
732; X64-NEXT:    pblendw {{.*#+}} xmm0 = xmm2[0,1,2,3,4,5],xmm0[6,7]
733; X64-NEXT:    retq
734  %vecext = extractelement <4 x i32> %x, i32 0
735  %vecinit = insertelement <4 x i32> undef, i32 %vecext, i32 0
736  %vecinit1 = insertelement <4 x i32> %vecinit, i32 0, i32 1
737  %vecinit3 = shufflevector <4 x i32> %vecinit1, <4 x i32> %x, <4 x i32> <i32 0, i32 1, i32 5, i32 undef>
738  %vecinit5 = shufflevector <4 x i32> %vecinit3, <4 x i32> %a, <4 x i32> <i32 0, i32 1, i32 2, i32 6>
739  ret <4 x i32> %vecinit5
740}
741
742;; Test for a bug in the first implementation of LowerBuildVectorv4x32
743define < 4 x float> @test_insertps_no_undef(<4 x float> %x) {
744; X32-LABEL: test_insertps_no_undef:
745; X32:       ## BB#0:
746; X32-NEXT:    xorps %xmm1, %xmm1
747; X32-NEXT:    blendps {{.*#+}} xmm1 = xmm0[0,1,2],xmm1[3]
748; X32-NEXT:    maxps %xmm1, %xmm0
749; X32-NEXT:    retl
750;
751; X64-LABEL: test_insertps_no_undef:
752; X64:       ## BB#0:
753; X64-NEXT:    xorps %xmm1, %xmm1
754; X64-NEXT:    blendps {{.*#+}} xmm1 = xmm0[0,1,2],xmm1[3]
755; X64-NEXT:    maxps %xmm1, %xmm0
756; X64-NEXT:    retq
757  %vecext = extractelement <4 x float> %x, i32 0
758  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
759  %vecext1 = extractelement <4 x float> %x, i32 1
760  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
761  %vecext3 = extractelement <4 x float> %x, i32 2
762  %vecinit4 = insertelement <4 x float> %vecinit2, float %vecext3, i32 2
763  %vecinit5 = insertelement <4 x float> %vecinit4, float 0.0, i32 3
764  %mask = fcmp olt <4 x float> %vecinit5, %x
765  %res = select  <4 x i1> %mask, <4 x float> %x, <4 x float>%vecinit5
766  ret <4 x float> %res
767}
768
769define <8 x i16> @blendvb_fallback(<8 x i1> %mask, <8 x i16> %x, <8 x i16> %y) {
770; X32-LABEL: blendvb_fallback:
771; X32:       ## BB#0:
772; X32-NEXT:    psllw $15, %xmm0
773; X32-NEXT:    psraw $15, %xmm0
774; X32-NEXT:    pblendvb %xmm1, %xmm2
775; X32-NEXT:    movdqa %xmm2, %xmm0
776; X32-NEXT:    retl
777;
778; X64-LABEL: blendvb_fallback:
779; X64:       ## BB#0:
780; X64-NEXT:    psllw $15, %xmm0
781; X64-NEXT:    psraw $15, %xmm0
782; X64-NEXT:    pblendvb %xmm1, %xmm2
783; X64-NEXT:    movdqa %xmm2, %xmm0
784; X64-NEXT:    retq
785  %ret = select <8 x i1> %mask, <8 x i16> %x, <8 x i16> %y
786  ret <8 x i16> %ret
787}
788
789; On X32, account for the argument's move to registers
790define <4 x float> @insertps_from_vector_load(<4 x float> %a, <4 x float>* nocapture readonly %pb) {
791; X32-LABEL: insertps_from_vector_load:
792; X32:       ## BB#0:
793; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
794; X32-NEXT:    insertps    $48, (%{{...}}), {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
795; X32-NEXT:    retl
796;
797; X64-LABEL: insertps_from_vector_load:
798; X64:       ## BB#0:
799; X64-NEXT:    insertps    $48, (%{{...}}), {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
800; X64-NEXT:    retq
801  %1 = load <4 x float>, <4 x float>* %pb, align 16
802  %2 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %a, <4 x float> %1, i32 48)
803  ret <4 x float> %2
804}
805
806;; Use a non-zero CountS for insertps
807;; Try to match a bit more of the instr, since we need the load's offset.
808define <4 x float> @insertps_from_vector_load_offset(<4 x float> %a, <4 x float>* nocapture readonly %pb) {
809; X32-LABEL: insertps_from_vector_load_offset:
810; X32:       ## BB#0:
811; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
812; X32-NEXT:    insertps    $32, 4(%{{...}}), {{.*#+}} xmm0 = xmm0[0,1],mem[0],xmm0[3]
813; X32-NEXT:    retl
814;
815; X64-LABEL: insertps_from_vector_load_offset:
816; X64:       ## BB#0:
817; X64-NEXT:    insertps    $32, 4(%{{...}}), {{.*#+}} xmm0 = xmm0[0,1],mem[0],xmm0[3]
818; X64-NEXT:    retq
819  %1 = load <4 x float>, <4 x float>* %pb, align 16
820  %2 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %a, <4 x float> %1, i32 96)
821  ret <4 x float> %2
822}
823
824;; Try to match a bit more of the instr, since we need the load's offset.
825define <4 x float> @insertps_from_vector_load_offset_2(<4 x float> %a, <4 x float>* nocapture readonly %pb, i64 %index) {
826; X32-LABEL: insertps_from_vector_load_offset_2:
827; X32:       ## BB#0:
828; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
829; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
830; X32-NEXT:    shll $4, %ecx
831; X32-NEXT:    insertps    $0, 12(%{{...}},%{{...}}), {{.*#+}} xmm0 = mem[0],xmm0[1,2,3]
832; X32-NEXT:    retl
833;
834; X64-LABEL: insertps_from_vector_load_offset_2:
835; X64:       ## BB#0:
836; X64-NEXT:    shlq $4, %rsi
837; X64-NEXT:    insertps    $0, 12(%{{...}},%{{...}}), {{.*#+}} xmm0 = mem[0],xmm0[1,2,3]
838; X64-NEXT:    retq
839  %1 = getelementptr inbounds <4 x float>, <4 x float>* %pb, i64 %index
840  %2 = load <4 x float>, <4 x float>* %1, align 16
841  %3 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %a, <4 x float> %2, i32 192)
842  ret <4 x float> %3
843}
844
845define <4 x float> @insertps_from_broadcast_loadf32(<4 x float> %a, float* nocapture readonly %fb, i64 %index) {
846; X32-LABEL: insertps_from_broadcast_loadf32:
847; X32:       ## BB#0:
848; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
849; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
850; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
851; X32-NEXT:    retl
852;
853; X64-LABEL: insertps_from_broadcast_loadf32:
854; X64:       ## BB#0:
855; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
856; X64-NEXT:    retq
857  %1 = getelementptr inbounds float, float* %fb, i64 %index
858  %2 = load float, float* %1, align 4
859  %3 = insertelement <4 x float> undef, float %2, i32 0
860  %4 = insertelement <4 x float> %3, float %2, i32 1
861  %5 = insertelement <4 x float> %4, float %2, i32 2
862  %6 = insertelement <4 x float> %5, float %2, i32 3
863  %7 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %a, <4 x float> %6, i32 48)
864  ret <4 x float> %7
865}
866
867define <4 x float> @insertps_from_broadcast_loadv4f32(<4 x float> %a, <4 x float>* nocapture readonly %b) {
868; X32-LABEL: insertps_from_broadcast_loadv4f32:
869; X32:       ## BB#0:
870; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
871; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
872; X32-NEXT:    retl
873;
874; X64-LABEL: insertps_from_broadcast_loadv4f32:
875; X64:       ## BB#0:
876; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],mem[0]
877; X64-NEXT:    retq
878  %1 = load <4 x float>, <4 x float>* %b, align 4
879  %2 = extractelement <4 x float> %1, i32 0
880  %3 = insertelement <4 x float> undef, float %2, i32 0
881  %4 = insertelement <4 x float> %3, float %2, i32 1
882  %5 = insertelement <4 x float> %4, float %2, i32 2
883  %6 = insertelement <4 x float> %5, float %2, i32 3
884  %7 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %a, <4 x float> %6, i32 48)
885  ret <4 x float> %7
886}
887
888define <4 x float> @insertps_from_broadcast_multiple_use(<4 x float> %a, <4 x float> %b, <4 x float> %c, <4 x float> %d, float* nocapture readonly %fb, i64 %index) {
889; X32-LABEL: insertps_from_broadcast_multiple_use:
890; X32:       ## BB#0:
891; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
892; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
893; X32-NEXT:    movss {{.*#+}} xmm4 = mem[0],zero,zero,zero
894; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm4[0]
895; X32-NEXT:    insertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm4[0]
896; X32-NEXT:    insertps {{.*#+}} xmm2 = xmm2[0,1,2],xmm4[0]
897; X32-NEXT:    insertps {{.*#+}} xmm3 = xmm3[0,1,2],xmm4[0]
898; X32-NEXT:    addps %xmm1, %xmm0
899; X32-NEXT:    addps %xmm2, %xmm3
900; X32-NEXT:    addps %xmm3, %xmm0
901; X32-NEXT:    retl
902;
903; X64-LABEL: insertps_from_broadcast_multiple_use:
904; X64:       ## BB#0:
905; X64-NEXT:    movss {{.*#+}} xmm4 = mem[0],zero,zero,zero
906; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0,1,2],xmm4[0]
907; X64-NEXT:    insertps {{.*#+}} xmm1 = xmm1[0,1,2],xmm4[0]
908; X64-NEXT:    insertps {{.*#+}} xmm2 = xmm2[0,1,2],xmm4[0]
909; X64-NEXT:    insertps {{.*#+}} xmm3 = xmm3[0,1,2],xmm4[0]
910; X64-NEXT:    addps %xmm1, %xmm0
911; X64-NEXT:    addps %xmm2, %xmm3
912; X64-NEXT:    addps %xmm3, %xmm0
913; X64-NEXT:    retq
914  %1 = getelementptr inbounds float, float* %fb, i64 %index
915  %2 = load float, float* %1, align 4
916  %3 = insertelement <4 x float> undef, float %2, i32 0
917  %4 = insertelement <4 x float> %3, float %2, i32 1
918  %5 = insertelement <4 x float> %4, float %2, i32 2
919  %6 = insertelement <4 x float> %5, float %2, i32 3
920  %7 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %a, <4 x float> %6, i32 48)
921  %8 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %b, <4 x float> %6, i32 48)
922  %9 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %c, <4 x float> %6, i32 48)
923  %10 = tail call <4 x float> @llvm.x86.sse41.insertps(<4 x float> %d, <4 x float> %6, i32 48)
924  %11 = fadd <4 x float> %7, %8
925  %12 = fadd <4 x float> %9, %10
926  %13 = fadd <4 x float> %11, %12
927  ret <4 x float> %13
928}
929
930define <4 x float> @insertps_with_undefs(<4 x float> %a, float* %b) {
931; X32-LABEL: insertps_with_undefs:
932; X32:       ## BB#0:
933; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
934; X32-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
935; X32-NEXT:    unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm0[0]
936; X32-NEXT:    movapd %xmm1, %xmm0
937; X32-NEXT:    retl
938;
939; X64-LABEL: insertps_with_undefs:
940; X64:       ## BB#0:
941; X64-NEXT:    movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
942; X64-NEXT:    unpcklpd {{.*#+}} xmm1 = xmm1[0],xmm0[0]
943; X64-NEXT:    movapd %xmm1, %xmm0
944; X64-NEXT:    retq
945  %1 = load float, float* %b, align 4
946  %2 = insertelement <4 x float> undef, float %1, i32 0
947  %result = shufflevector <4 x float> %a, <4 x float> %2, <4 x i32> <i32 4, i32 undef, i32 0, i32 7>
948  ret <4 x float> %result
949}
950
951; Test for a bug in X86ISelLowering.cpp:getINSERTPS where we were using
952; the destination index to change the load, instead of the source index.
953define <4 x float> @pr20087(<4 x float> %a, <4 x float> *%ptr) {
954; X32-LABEL: pr20087:
955; X32:       ## BB#0:
956; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
957; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm0[2],mem[0]
958; X32-NEXT:    retl
959;
960; X64-LABEL: pr20087:
961; X64:       ## BB#0:
962; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm0[2],mem[0]
963; X64-NEXT:    retq
964  %load = load <4 x float> , <4 x float> *%ptr
965  %ret = shufflevector <4 x float> %load, <4 x float> %a, <4 x i32> <i32 4, i32 undef, i32 6, i32 2>
966  ret <4 x float> %ret
967}
968
969; Edge case for insertps where we end up with a shuffle with mask=<0, 7, -1, -1>
970define void @insertps_pr20411(<4 x i32> %shuffle109, <4 x i32> %shuffle116, i32* noalias nocapture %RET) #1 {
971; X32-LABEL: insertps_pr20411:
972; X32:       ## BB#0:
973; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
974; X32-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[2,3,0,1]
975; X32-NEXT:    pblendw {{.*#+}} xmm1 = xmm0[0,1],xmm1[2,3],xmm0[4,5,6,7]
976; X32-NEXT:    movdqu %xmm1, (%eax)
977; X32-NEXT:    retl
978;
979; X64-LABEL: insertps_pr20411:
980; X64:       ## BB#0:
981; X64-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[2,3,0,1]
982; X64-NEXT:    pblendw {{.*#+}} xmm1 = xmm0[0,1],xmm1[2,3],xmm0[4,5,6,7]
983; X64-NEXT:    movdqu %xmm1, (%rdi)
984; X64-NEXT:    retq
985  %shuffle117 = shufflevector <4 x i32> %shuffle109, <4 x i32> %shuffle116, <4 x i32> <i32 0, i32 7, i32 undef, i32 undef>
986  %ptrcast = bitcast i32* %RET to <4 x i32>*
987  store <4 x i32> %shuffle117, <4 x i32>* %ptrcast, align 4
988  ret void
989}
990
991define <4 x float> @insertps_4(<4 x float> %A, <4 x float> %B) {
992; X32-LABEL: insertps_4:
993; X32:       ## BB#0: ## %entry
994; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm1[2],zero
995; X32-NEXT:    retl
996;
997; X64-LABEL: insertps_4:
998; X64:       ## BB#0: ## %entry
999; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm1[2],zero
1000; X64-NEXT:    retq
1001entry:
1002  %vecext = extractelement <4 x float> %A, i32 0
1003  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
1004  %vecinit1 = insertelement <4 x float> %vecinit, float 0.000000e+00, i32 1
1005  %vecext2 = extractelement <4 x float> %B, i32 2
1006  %vecinit3 = insertelement <4 x float> %vecinit1, float %vecext2, i32 2
1007  %vecinit4 = insertelement <4 x float> %vecinit3, float 0.000000e+00, i32 3
1008  ret <4 x float> %vecinit4
1009}
1010
1011define <4 x float> @insertps_5(<4 x float> %A, <4 x float> %B) {
1012; X32-LABEL: insertps_5:
1013; X32:       ## BB#0: ## %entry
1014; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],xmm1[1],zero,zero
1015; X32-NEXT:    retl
1016;
1017; X64-LABEL: insertps_5:
1018; X64:       ## BB#0: ## %entry
1019; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],xmm1[1],zero,zero
1020; X64-NEXT:    retq
1021entry:
1022  %vecext = extractelement <4 x float> %A, i32 0
1023  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
1024  %vecext1 = extractelement <4 x float> %B, i32 1
1025  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
1026  %vecinit3 = insertelement <4 x float> %vecinit2, float 0.000000e+00, i32 2
1027  %vecinit4 = insertelement <4 x float> %vecinit3, float 0.000000e+00, i32 3
1028  ret <4 x float> %vecinit4
1029}
1030
1031define <4 x float> @insertps_6(<4 x float> %A, <4 x float> %B) {
1032; X32-LABEL: insertps_6:
1033; X32:       ## BB#0: ## %entry
1034; X32-NEXT:    insertps {{.*#+}} xmm0 = zero,xmm0[1],xmm1[2],zero
1035; X32-NEXT:    retl
1036;
1037; X64-LABEL: insertps_6:
1038; X64:       ## BB#0: ## %entry
1039; X64-NEXT:    insertps {{.*#+}} xmm0 = zero,xmm0[1],xmm1[2],zero
1040; X64-NEXT:    retq
1041entry:
1042  %vecext = extractelement <4 x float> %A, i32 1
1043  %vecinit = insertelement <4 x float> <float 0.000000e+00, float undef, float undef, float undef>, float %vecext, i32 1
1044  %vecext1 = extractelement <4 x float> %B, i32 2
1045  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 2
1046  %vecinit3 = insertelement <4 x float> %vecinit2, float 0.000000e+00, i32 3
1047  ret <4 x float> %vecinit3
1048}
1049
1050define <4 x float> @insertps_7(<4 x float> %A, <4 x float> %B) {
1051; X32-LABEL: insertps_7:
1052; X32:       ## BB#0: ## %entry
1053; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm1[1],zero
1054; X32-NEXT:    retl
1055;
1056; X64-LABEL: insertps_7:
1057; X64:       ## BB#0: ## %entry
1058; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm1[1],zero
1059; X64-NEXT:    retq
1060entry:
1061  %vecext = extractelement <4 x float> %A, i32 0
1062  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
1063  %vecinit1 = insertelement <4 x float> %vecinit, float 0.000000e+00, i32 1
1064  %vecext2 = extractelement <4 x float> %B, i32 1
1065  %vecinit3 = insertelement <4 x float> %vecinit1, float %vecext2, i32 2
1066  %vecinit4 = insertelement <4 x float> %vecinit3, float 0.000000e+00, i32 3
1067  ret <4 x float> %vecinit4
1068}
1069
1070define <4 x float> @insertps_8(<4 x float> %A, <4 x float> %B) {
1071; X32-LABEL: insertps_8:
1072; X32:       ## BB#0: ## %entry
1073; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],zero,zero
1074; X32-NEXT:    retl
1075;
1076; X64-LABEL: insertps_8:
1077; X64:       ## BB#0: ## %entry
1078; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],xmm1[0],zero,zero
1079; X64-NEXT:    retq
1080entry:
1081  %vecext = extractelement <4 x float> %A, i32 0
1082  %vecinit = insertelement <4 x float> undef, float %vecext, i32 0
1083  %vecext1 = extractelement <4 x float> %B, i32 0
1084  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 1
1085  %vecinit3 = insertelement <4 x float> %vecinit2, float 0.000000e+00, i32 2
1086  %vecinit4 = insertelement <4 x float> %vecinit3, float 0.000000e+00, i32 3
1087  ret <4 x float> %vecinit4
1088}
1089
1090define <4 x float> @insertps_9(<4 x float> %A, <4 x float> %B) {
1091; X32-LABEL: insertps_9:
1092; X32:       ## BB#0: ## %entry
1093; X32-NEXT:    insertps {{.*#+}} xmm1 = zero,xmm0[0],xmm1[2],zero
1094; X32-NEXT:    movaps %xmm1, %xmm0
1095; X32-NEXT:    retl
1096;
1097; X64-LABEL: insertps_9:
1098; X64:       ## BB#0: ## %entry
1099; X64-NEXT:    insertps {{.*#+}} xmm1 = zero,xmm0[0],xmm1[2],zero
1100; X64-NEXT:    movaps %xmm1, %xmm0
1101; X64-NEXT:    retq
1102entry:
1103  %vecext = extractelement <4 x float> %A, i32 0
1104  %vecinit = insertelement <4 x float> <float 0.000000e+00, float undef, float undef, float undef>, float %vecext, i32 1
1105  %vecext1 = extractelement <4 x float> %B, i32 2
1106  %vecinit2 = insertelement <4 x float> %vecinit, float %vecext1, i32 2
1107  %vecinit3 = insertelement <4 x float> %vecinit2, float 0.000000e+00, i32 3
1108  ret <4 x float> %vecinit3
1109}
1110
1111define <4 x float> @insertps_10(<4 x float> %A)
1112; X32-LABEL: insertps_10:
1113; X32:       ## BB#0:
1114; X32-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm0[0],zero
1115; X32-NEXT:    retl
1116;
1117; X64-LABEL: insertps_10:
1118; X64:       ## BB#0:
1119; X64-NEXT:    insertps {{.*#+}} xmm0 = xmm0[0],zero,xmm0[0],zero
1120; X64-NEXT:    retq
1121{
1122  %vecext = extractelement <4 x float> %A, i32 0
1123  %vecbuild1 = insertelement <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00>, float %vecext, i32 0
1124  %vecbuild2 = insertelement <4 x float> %vecbuild1, float %vecext, i32 2
1125  ret <4 x float> %vecbuild2
1126}
1127
1128define <4 x float> @build_vector_to_shuffle_1(<4 x float> %A) {
1129; X32-LABEL: build_vector_to_shuffle_1:
1130; X32:       ## BB#0: ## %entry
1131; X32-NEXT:    xorps %xmm1, %xmm1
1132; X32-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2],xmm0[3]
1133; X32-NEXT:    retl
1134;
1135; X64-LABEL: build_vector_to_shuffle_1:
1136; X64:       ## BB#0: ## %entry
1137; X64-NEXT:    xorps %xmm1, %xmm1
1138; X64-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2],xmm0[3]
1139; X64-NEXT:    retq
1140entry:
1141  %vecext = extractelement <4 x float> %A, i32 1
1142  %vecinit = insertelement <4 x float> zeroinitializer, float %vecext, i32 1
1143  %vecinit1 = insertelement <4 x float> %vecinit, float 0.0, i32 2
1144  %vecinit3 = shufflevector <4 x float> %vecinit1, <4 x float> %A, <4 x i32> <i32 0, i32 1, i32 2, i32 7>
1145  ret <4 x float> %vecinit3
1146}
1147
1148define <4 x float> @build_vector_to_shuffle_2(<4 x float> %A) {
1149; X32-LABEL: build_vector_to_shuffle_2:
1150; X32:       ## BB#0: ## %entry
1151; X32-NEXT:    xorps %xmm1, %xmm1
1152; X32-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2,3]
1153; X32-NEXT:    retl
1154;
1155; X64-LABEL: build_vector_to_shuffle_2:
1156; X64:       ## BB#0: ## %entry
1157; X64-NEXT:    xorps %xmm1, %xmm1
1158; X64-NEXT:    blendps {{.*#+}} xmm0 = xmm1[0],xmm0[1],xmm1[2,3]
1159; X64-NEXT:    retq
1160entry:
1161  %vecext = extractelement <4 x float> %A, i32 1
1162  %vecinit = insertelement <4 x float> zeroinitializer, float %vecext, i32 1
1163  %vecinit1 = insertelement <4 x float> %vecinit, float 0.0, i32 2
1164  ret <4 x float> %vecinit1
1165}
1166