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