601 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-unknown -mattr=+sse2 | FileCheck %s --check-prefix=X86-SSE23; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+ssse3 | FileCheck %s --check-prefixes=X64,X64-SSSE34; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx | FileCheck %s --check-prefixes=X64,X64-AVX,X64-AVX15; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx2 | FileCheck %s --check-prefixes=X64,X64-AVX,X64-AVX26 7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"8 9define i32 @t(ptr %val) nounwind {10; X86-SSE2-LABEL: t:11; X86-SSE2: # %bb.0:12; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax13; X86-SSE2-NEXT: movl 8(%eax), %eax14; X86-SSE2-NEXT: retl15;16; X64-LABEL: t:17; X64: # %bb.0:18; X64-NEXT: movl 8(%rdi), %eax19; X64-NEXT: retq20 %tmp2 = load <2 x i64>, ptr %val, align 16 ; <<2 x i64>> [#uses=1]21 %tmp3 = bitcast <2 x i64> %tmp2 to <4 x i32> ; <<4 x i32>> [#uses=1]22 %tmp4 = extractelement <4 x i32> %tmp3, i32 2 ; <i32> [#uses=1]23 ret i32 %tmp424}25 26; Case where extractelement of load ends up as undef.27; (Making sure this doesn't crash.)28define i32 @t2(ptr %xp) {29; X86-SSE2-LABEL: t2:30; X86-SSE2: # %bb.0:31; X86-SSE2-NEXT: retl32;33; X64-LABEL: t2:34; X64: # %bb.0:35; X64-NEXT: retq36 %x = load <8 x i32>, ptr %xp37 %Shuff68 = shufflevector <8 x i32> %x, <8 x i32> undef, <8 x i32> <i32 undef, i32 7, i32 9, i32 undef, i32 13, i32 15, i32 1, i32 3>38 %y = extractelement <8 x i32> %Shuff68, i32 039 ret i32 %y40}41 42; This case could easily end up inf-looping in the DAG combiner due to an43; low alignment load of the vector which prevents us from reliably forming a44; narrow load.45 46define void @t3(ptr %a0) {47; X86-SSE2-LABEL: t3:48; X86-SSE2: # %bb.0: # %bb49; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax50; X86-SSE2-NEXT: movups (%eax), %xmm051; X86-SSE2-NEXT: movhps %xmm0, (%eax)52; X86-SSE2-NEXT: retl53;54; X64-SSSE3-LABEL: t3:55; X64-SSSE3: # %bb.0: # %bb56; X64-SSSE3-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero57; X64-SSSE3-NEXT: movsd %xmm0, (%rax)58; X64-SSSE3-NEXT: retq59;60; X64-AVX-LABEL: t3:61; X64-AVX: # %bb.0: # %bb62; X64-AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero63; X64-AVX-NEXT: vmovsd %xmm0, (%rax)64; X64-AVX-NEXT: retq65bb:66 %tmp13 = load <2 x double>, ptr %a0, align 167 %.sroa.3.24.vec.extract = extractelement <2 x double> %tmp13, i32 168 store double %.sroa.3.24.vec.extract, ptr undef, align 869 ret void70}71 72; Case where a load is unary shuffled, then bitcast (to a type with the same73; number of elements) before extractelement.74; This is testing for an assertion - the extraction was assuming that the undef75; second shuffle operand was a post-bitcast type instead of a pre-bitcast type.76define i64 @t4(ptr %a) {77; X86-SSE2-LABEL: t4:78; X86-SSE2: # %bb.0:79; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx80; X86-SSE2-NEXT: movl (%ecx), %eax81; X86-SSE2-NEXT: movl 4(%ecx), %edx82; X86-SSE2-NEXT: retl83;84; X64-LABEL: t4:85; X64: # %bb.0:86; X64-NEXT: movq (%rdi), %rax87; X64-NEXT: retq88 %b = load <2 x double>, ptr %a, align 1689 %c = shufflevector <2 x double> %b, <2 x double> %b, <2 x i32> <i32 1, i32 0>90 %d = bitcast <2 x double> %c to <2 x i64>91 %e = extractelement <2 x i64> %d, i32 192 ret i64 %e93}94 95; Don't extract from a volatile.96define void @t5(ptr%a0, ptr%a1) {97; X86-SSE2-LABEL: t5:98; X86-SSE2: # %bb.0:99; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax100; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx101; X86-SSE2-NEXT: movaps (%ecx), %xmm0102; X86-SSE2-NEXT: movhps %xmm0, (%eax)103; X86-SSE2-NEXT: retl104;105; X64-SSSE3-LABEL: t5:106; X64-SSSE3: # %bb.0:107; X64-SSSE3-NEXT: movaps (%rdi), %xmm0108; X64-SSSE3-NEXT: movhps %xmm0, (%rsi)109; X64-SSSE3-NEXT: retq110;111; X64-AVX-LABEL: t5:112; X64-AVX: # %bb.0:113; X64-AVX-NEXT: vmovaps (%rdi), %xmm0114; X64-AVX-NEXT: vmovhps %xmm0, (%rsi)115; X64-AVX-NEXT: retq116 %vecload = load volatile <2 x double>, ptr %a0, align 16117 %vecext = extractelement <2 x double> %vecload, i32 1118 store volatile double %vecext, ptr %a1, align 8119 ret void120}121 122; Check for multiuse.123define float @t6(ptr%a0) {124; X86-SSE2-LABEL: t6:125; X86-SSE2: # %bb.0:126; X86-SSE2-NEXT: pushl %eax127; X86-SSE2-NEXT: .cfi_def_cfa_offset 8128; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax129; X86-SSE2-NEXT: movaps (%eax), %xmm0130; X86-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]131; X86-SSE2-NEXT: xorps %xmm1, %xmm1132; X86-SSE2-NEXT: cmpeqss %xmm0, %xmm1133; X86-SSE2-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0]134; X86-SSE2-NEXT: andps %xmm1, %xmm2135; X86-SSE2-NEXT: andnps %xmm0, %xmm1136; X86-SSE2-NEXT: orps %xmm2, %xmm1137; X86-SSE2-NEXT: movss %xmm1, (%esp)138; X86-SSE2-NEXT: flds (%esp)139; X86-SSE2-NEXT: popl %eax140; X86-SSE2-NEXT: .cfi_def_cfa_offset 4141; X86-SSE2-NEXT: retl142;143; X64-SSSE3-LABEL: t6:144; X64-SSSE3: # %bb.0:145; X64-SSSE3-NEXT: movshdup {{.*#+}} xmm1 = mem[1,1,3,3]146; X64-SSSE3-NEXT: xorps %xmm0, %xmm0147; X64-SSSE3-NEXT: cmpeqss %xmm1, %xmm0148; X64-SSSE3-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0]149; X64-SSSE3-NEXT: andps %xmm0, %xmm2150; X64-SSSE3-NEXT: andnps %xmm1, %xmm0151; X64-SSSE3-NEXT: orps %xmm2, %xmm0152; X64-SSSE3-NEXT: retq153;154; X64-AVX1-LABEL: t6:155; X64-AVX1: # %bb.0:156; X64-AVX1-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero157; X64-AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1158; X64-AVX1-NEXT: vcmpeqss %xmm1, %xmm0, %xmm1159; X64-AVX1-NEXT: vblendvps %xmm1, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0160; X64-AVX1-NEXT: retq161;162; X64-AVX2-LABEL: t6:163; X64-AVX2: # %bb.0:164; X64-AVX2-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero165; X64-AVX2-NEXT: vxorps %xmm1, %xmm1, %xmm1166; X64-AVX2-NEXT: vcmpeqss %xmm1, %xmm0, %xmm1167; X64-AVX2-NEXT: vbroadcastss {{.*#+}} xmm2 = [1.0E+0,1.0E+0,1.0E+0,1.0E+0]168; X64-AVX2-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0169; X64-AVX2-NEXT: retq170 %vecload = load <8 x float>, ptr %a0, align 32171 %vecext = extractelement <8 x float> %vecload, i32 1172 %cmp = fcmp oeq float %vecext, 0.000000e+00173 %cond = select i1 %cmp, float 1.000000e+00, float %vecext174 ret float %cond175}176 177define void @PR43971(ptr%a0, ptr%a1) {178; X86-SSE2-LABEL: PR43971:179; X86-SSE2: # %bb.0: # %entry180; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax181; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx182; X86-SSE2-NEXT: movaps 16(%ecx), %xmm0183; X86-SSE2-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]184; X86-SSE2-NEXT: xorps %xmm1, %xmm1185; X86-SSE2-NEXT: cmpltss %xmm0, %xmm1186; X86-SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero187; X86-SSE2-NEXT: andps %xmm1, %xmm2188; X86-SSE2-NEXT: andnps %xmm0, %xmm1189; X86-SSE2-NEXT: orps %xmm2, %xmm1190; X86-SSE2-NEXT: movss %xmm1, (%eax)191; X86-SSE2-NEXT: retl192;193; X64-SSSE3-LABEL: PR43971:194; X64-SSSE3: # %bb.0: # %entry195; X64-SSSE3-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero196; X64-SSSE3-NEXT: xorps %xmm1, %xmm1197; X64-SSSE3-NEXT: cmpltss %xmm0, %xmm1198; X64-SSSE3-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero199; X64-SSSE3-NEXT: andps %xmm1, %xmm2200; X64-SSSE3-NEXT: andnps %xmm0, %xmm1201; X64-SSSE3-NEXT: orps %xmm2, %xmm1202; X64-SSSE3-NEXT: movss %xmm1, (%rsi)203; X64-SSSE3-NEXT: retq204;205; X64-AVX-LABEL: PR43971:206; X64-AVX: # %bb.0: # %entry207; X64-AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero208; X64-AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1209; X64-AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm1210; X64-AVX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero211; X64-AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0212; X64-AVX-NEXT: vmovss %xmm0, (%rsi)213; X64-AVX-NEXT: retq214entry:215 %0 = load <8 x float>, ptr %a0, align 32216 %vecext = extractelement <8 x float> %0, i32 6217 %cmp = fcmp ogt float %vecext, 0.000000e+00218 %1 = load float, ptr %a1, align 4219 %cond = select i1 %cmp, float %1, float %vecext220 store float %cond, ptr %a1, align 4221 ret void222}223 224define float @PR43971_1(ptr%a0) nounwind {225; X86-SSE2-LABEL: PR43971_1:226; X86-SSE2: # %bb.0: # %entry227; X86-SSE2-NEXT: pushl %eax228; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax229; X86-SSE2-NEXT: movaps (%eax), %xmm0230; X86-SSE2-NEXT: shufps {{.*#+}} xmm0 = xmm0[1,1,1,1]231; X86-SSE2-NEXT: xorps %xmm1, %xmm1232; X86-SSE2-NEXT: cmpeqss %xmm0, %xmm1233; X86-SSE2-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0]234; X86-SSE2-NEXT: andps %xmm1, %xmm2235; X86-SSE2-NEXT: andnps %xmm0, %xmm1236; X86-SSE2-NEXT: orps %xmm2, %xmm1237; X86-SSE2-NEXT: movss %xmm1, (%esp)238; X86-SSE2-NEXT: flds (%esp)239; X86-SSE2-NEXT: popl %eax240; X86-SSE2-NEXT: retl241;242; X64-SSSE3-LABEL: PR43971_1:243; X64-SSSE3: # %bb.0: # %entry244; X64-SSSE3-NEXT: movshdup {{.*#+}} xmm1 = mem[1,1,3,3]245; X64-SSSE3-NEXT: xorps %xmm0, %xmm0246; X64-SSSE3-NEXT: cmpeqss %xmm1, %xmm0247; X64-SSSE3-NEXT: movss {{.*#+}} xmm2 = [1.0E+0,0.0E+0,0.0E+0,0.0E+0]248; X64-SSSE3-NEXT: andps %xmm0, %xmm2249; X64-SSSE3-NEXT: andnps %xmm1, %xmm0250; X64-SSSE3-NEXT: orps %xmm2, %xmm0251; X64-SSSE3-NEXT: retq252;253; X64-AVX1-LABEL: PR43971_1:254; X64-AVX1: # %bb.0: # %entry255; X64-AVX1-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero256; X64-AVX1-NEXT: vxorps %xmm1, %xmm1, %xmm1257; X64-AVX1-NEXT: vcmpeqss %xmm1, %xmm0, %xmm1258; X64-AVX1-NEXT: vblendvps %xmm1, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm0259; X64-AVX1-NEXT: retq260;261; X64-AVX2-LABEL: PR43971_1:262; X64-AVX2: # %bb.0: # %entry263; X64-AVX2-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero264; X64-AVX2-NEXT: vxorps %xmm1, %xmm1, %xmm1265; X64-AVX2-NEXT: vcmpeqss %xmm1, %xmm0, %xmm1266; X64-AVX2-NEXT: vbroadcastss {{.*#+}} xmm2 = [1.0E+0,1.0E+0,1.0E+0,1.0E+0]267; X64-AVX2-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0268; X64-AVX2-NEXT: retq269entry:270 %0 = load <8 x float>, ptr %a0, align 32271 %vecext = extractelement <8 x float> %0, i32 1272 %cmp = fcmp oeq float %vecext, 0.000000e+00273 %cond = select i1 %cmp, float 1.000000e+00, float %vecext274 ret float %cond275}276 277define i32 @PR85419(ptr %p0) {278; X86-SSE2-LABEL: PR85419:279; X86-SSE2: # %bb.0:280; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx281; X86-SSE2-NEXT: movl (%ecx), %edx282; X86-SSE2-NEXT: xorl %eax, %eax283; X86-SSE2-NEXT: orl 4(%ecx), %edx284; X86-SSE2-NEXT: je .LBB8_2285; X86-SSE2-NEXT: # %bb.1:286; X86-SSE2-NEXT: movl 8(%ecx), %eax287; X86-SSE2-NEXT: .LBB8_2:288; X86-SSE2-NEXT: retl289;290; X64-LABEL: PR85419:291; X64: # %bb.0:292; X64-NEXT: xorl %eax, %eax293; X64-NEXT: cmpq $0, (%rdi)294; X64-NEXT: je .LBB8_2295; X64-NEXT: # %bb.1:296; X64-NEXT: movl 8(%rdi), %eax297; X64-NEXT: .LBB8_2:298; X64-NEXT: retq299 %load = load <2 x i64>, ptr %p0, align 16300 %vecext.i = extractelement <2 x i64> %load, i64 0301 %cmp = icmp eq i64 %vecext.i, 0302 %.cast = bitcast <2 x i64> %load to <4 x i32>303 %vecext.i2 = extractelement <4 x i32> %.cast, i64 2304 %retval.0 = select i1 %cmp, i32 0, i32 %vecext.i2305 ret i32 %retval.0306}307 308; Test for bad extractions from a VBROADCAST_LOAD of the <2 x i16> non-uniform constant bitcast as <4 x i32>.309define void @subextract_broadcast_load_constant(ptr nocapture %0, ptr nocapture %1, ptr nocapture %2) nounwind {310; X86-SSE2-LABEL: subextract_broadcast_load_constant:311; X86-SSE2: # %bb.0:312; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax313; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx314; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %edx315; X86-SSE2-NEXT: movl $-1583308898, (%edx) # imm = 0xA1A09F9E316; X86-SSE2-NEXT: movw $-24674, (%ecx) # imm = 0x9F9E317; X86-SSE2-NEXT: movw $-24160, (%eax) # imm = 0xA1A0318; X86-SSE2-NEXT: retl319;320; X64-LABEL: subextract_broadcast_load_constant:321; X64: # %bb.0:322; X64-NEXT: movl $-1583308898, (%rdi) # imm = 0xA1A09F9E323; X64-NEXT: movw $-24674, (%rsi) # imm = 0x9F9E324; X64-NEXT: movw $-24160, (%rdx) # imm = 0xA1A0325; X64-NEXT: retq326 store i8 -98, ptr %0, align 1327 %4 = getelementptr inbounds i8, ptr %0, i64 1328 store i8 -97, ptr %4, align 1329 %5 = getelementptr inbounds i8, ptr %0, i64 2330 store i8 -96, ptr %5, align 1331 %6 = getelementptr inbounds i8, ptr %0, i64 3332 store i8 -95, ptr %6, align 1333 %7 = load <2 x i16>, ptr %0, align 4334 %8 = extractelement <2 x i16> %7, i32 0335 store i16 %8, ptr %1, align 2336 %9 = extractelement <2 x i16> %7, i32 1337 store i16 %9, ptr %2, align 2338 ret void339}340 341; A scalar load is favored over a XMM->GPR register transfer in this example.342 343define i32 @multi_use_load_scalarization(ptr %p) nounwind {344; X86-SSE2-LABEL: multi_use_load_scalarization:345; X86-SSE2: # %bb.0:346; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx347; X86-SSE2-NEXT: movl (%ecx), %eax348; X86-SSE2-NEXT: movdqu (%ecx), %xmm0349; X86-SSE2-NEXT: pcmpeqd %xmm1, %xmm1350; X86-SSE2-NEXT: psubd %xmm1, %xmm0351; X86-SSE2-NEXT: movdqa %xmm0, (%ecx)352; X86-SSE2-NEXT: retl353;354; X64-SSSE3-LABEL: multi_use_load_scalarization:355; X64-SSSE3: # %bb.0:356; X64-SSSE3-NEXT: movl (%rdi), %eax357; X64-SSSE3-NEXT: movdqu (%rdi), %xmm0358; X64-SSSE3-NEXT: pcmpeqd %xmm1, %xmm1359; X64-SSSE3-NEXT: psubd %xmm1, %xmm0360; X64-SSSE3-NEXT: movdqa %xmm0, (%rdi)361; X64-SSSE3-NEXT: retq362;363; X64-AVX-LABEL: multi_use_load_scalarization:364; X64-AVX: # %bb.0:365; X64-AVX-NEXT: movl (%rdi), %eax366; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0367; X64-AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1368; X64-AVX-NEXT: vpsubd %xmm1, %xmm0, %xmm0369; X64-AVX-NEXT: vmovdqa %xmm0, (%rdi)370; X64-AVX-NEXT: retq371 %v = load <4 x i32>, ptr %p, align 1372 %v1 = add <4 x i32> %v, <i32 1, i32 1, i32 1, i32 1>373 store <4 x i32> %v1, ptr %p374 %r = extractelement <4 x i32> %v, i64 0375 ret i32 %r376}377 378define i32 @multi_use_volatile_load_scalarization(ptr %p) nounwind {379; X86-SSE2-LABEL: multi_use_volatile_load_scalarization:380; X86-SSE2: # %bb.0:381; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %ecx382; X86-SSE2-NEXT: movdqu (%ecx), %xmm0383; X86-SSE2-NEXT: pcmpeqd %xmm1, %xmm1384; X86-SSE2-NEXT: movd %xmm0, %eax385; X86-SSE2-NEXT: psubd %xmm1, %xmm0386; X86-SSE2-NEXT: movdqa %xmm0, (%ecx)387; X86-SSE2-NEXT: retl388;389; X64-SSSE3-LABEL: multi_use_volatile_load_scalarization:390; X64-SSSE3: # %bb.0:391; X64-SSSE3-NEXT: movdqu (%rdi), %xmm0392; X64-SSSE3-NEXT: pcmpeqd %xmm1, %xmm1393; X64-SSSE3-NEXT: movd %xmm0, %eax394; X64-SSSE3-NEXT: psubd %xmm1, %xmm0395; X64-SSSE3-NEXT: movdqa %xmm0, (%rdi)396; X64-SSSE3-NEXT: retq397;398; X64-AVX-LABEL: multi_use_volatile_load_scalarization:399; X64-AVX: # %bb.0:400; X64-AVX-NEXT: vmovdqu (%rdi), %xmm0401; X64-AVX-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1402; X64-AVX-NEXT: vpsubd %xmm1, %xmm0, %xmm1403; X64-AVX-NEXT: vmovdqa %xmm1, (%rdi)404; X64-AVX-NEXT: vmovd %xmm0, %eax405; X64-AVX-NEXT: retq406 %v = load volatile <4 x i32>, ptr %p, align 1407 %v1 = add <4 x i32> %v, <i32 1, i32 1, i32 1, i32 1>408 store <4 x i32> %v1, ptr %p409 %r = extractelement <4 x i32> %v, i64 0410 ret i32 %r411}412 413; This test is reduced from a C source example that showed a miscompile:414; https://github.com/llvm/llvm-project/issues/53695415; The scalarized loads from 'zero' in the AVX asm must occur before416; the vector store to 'zero' overwrites the values.417; If compiled to a binary, this test should return 0 if correct.418 419@n1 = local_unnamed_addr global <8 x i32> <i32 0, i32 42, i32 6, i32 0, i32 0, i32 0, i32 0, i32 0>, align 32420@zero = internal unnamed_addr global <8 x i32> zeroinitializer, align 32421 422define i32 @main() nounwind {423; X86-SSE2-LABEL: main:424; X86-SSE2: # %bb.0:425; X86-SSE2-NEXT: pushl %ebp426; X86-SSE2-NEXT: movl %esp, %ebp427; X86-SSE2-NEXT: pushl %edi428; X86-SSE2-NEXT: pushl %esi429; X86-SSE2-NEXT: andl $-32, %esp430; X86-SSE2-NEXT: subl $64, %esp431; X86-SSE2-NEXT: movaps n1+16, %xmm0432; X86-SSE2-NEXT: movaps n1, %xmm1433; X86-SSE2-NEXT: movl zero+4, %ecx434; X86-SSE2-NEXT: movl zero+8, %eax435; X86-SSE2-NEXT: movaps %xmm1, zero436; X86-SSE2-NEXT: movaps %xmm0, zero+16437; X86-SSE2-NEXT: movaps {{.*#+}} xmm0 = [2,2,2,2]438; X86-SSE2-NEXT: movaps %xmm0, {{[0-9]+}}(%esp)439; X86-SSE2-NEXT: movaps %xmm0, (%esp)440; X86-SSE2-NEXT: movdqa (%esp), %xmm0441; X86-SSE2-NEXT: movaps {{[0-9]+}}(%esp), %xmm1442; X86-SSE2-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]443; X86-SSE2-NEXT: movd %xmm1, %esi444; X86-SSE2-NEXT: xorl %edx, %edx445; X86-SSE2-NEXT: divl %esi446; X86-SSE2-NEXT: movl %eax, %esi447; X86-SSE2-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1]448; X86-SSE2-NEXT: movd %xmm0, %edi449; X86-SSE2-NEXT: movl %ecx, %eax450; X86-SSE2-NEXT: xorl %edx, %edx451; X86-SSE2-NEXT: divl %edi452; X86-SSE2-NEXT: addl %esi, %eax453; X86-SSE2-NEXT: leal -8(%ebp), %esp454; X86-SSE2-NEXT: popl %esi455; X86-SSE2-NEXT: popl %edi456; X86-SSE2-NEXT: popl %ebp457; X86-SSE2-NEXT: retl458;459; X64-SSSE3-LABEL: main:460; X64-SSSE3: # %bb.0:461; X64-SSSE3-NEXT: pushq %rbp462; X64-SSSE3-NEXT: movq %rsp, %rbp463; X64-SSSE3-NEXT: andq $-32, %rsp464; X64-SSSE3-NEXT: subq $64, %rsp465; X64-SSSE3-NEXT: movq n1@GOTPCREL(%rip), %rax466; X64-SSSE3-NEXT: movaps (%rax), %xmm0467; X64-SSSE3-NEXT: movaps 16(%rax), %xmm1468; X64-SSSE3-NEXT: movl zero+4(%rip), %ecx469; X64-SSSE3-NEXT: movl zero+8(%rip), %eax470; X64-SSSE3-NEXT: movaps %xmm0, zero(%rip)471; X64-SSSE3-NEXT: movaps %xmm1, zero+16(%rip)472; X64-SSSE3-NEXT: movaps {{.*#+}} xmm0 = [2,2,2,2]473; X64-SSSE3-NEXT: movaps %xmm0, {{[0-9]+}}(%rsp)474; X64-SSSE3-NEXT: movaps %xmm0, (%rsp)475; X64-SSSE3-NEXT: movdqa (%rsp), %xmm0476; X64-SSSE3-NEXT: movaps {{[0-9]+}}(%rsp), %xmm1477; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]478; X64-SSSE3-NEXT: movd %xmm1, %esi479; X64-SSSE3-NEXT: xorl %edx, %edx480; X64-SSSE3-NEXT: divl %esi481; X64-SSSE3-NEXT: movl %eax, %esi482; X64-SSSE3-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,1,1]483; X64-SSSE3-NEXT: movd %xmm0, %edi484; X64-SSSE3-NEXT: movl %ecx, %eax485; X64-SSSE3-NEXT: xorl %edx, %edx486; X64-SSSE3-NEXT: divl %edi487; X64-SSSE3-NEXT: addl %esi, %eax488; X64-SSSE3-NEXT: movq %rbp, %rsp489; X64-SSSE3-NEXT: popq %rbp490; X64-SSSE3-NEXT: retq491;492; X64-AVX-LABEL: main:493; X64-AVX: # %bb.0:494; X64-AVX-NEXT: pushq %rbp495; X64-AVX-NEXT: movq %rsp, %rbp496; X64-AVX-NEXT: andq $-32, %rsp497; X64-AVX-NEXT: subq $64, %rsp498; X64-AVX-NEXT: movq n1@GOTPCREL(%rip), %rax499; X64-AVX-NEXT: vmovaps (%rax), %ymm0500; X64-AVX-NEXT: movl zero+4(%rip), %ecx501; X64-AVX-NEXT: movl zero+8(%rip), %eax502; X64-AVX-NEXT: vmovaps %ymm0, zero(%rip)503; X64-AVX-NEXT: vbroadcastss {{.*#+}} ymm0 = [2,2,2,2,2,2,2,2]504; X64-AVX-NEXT: vmovaps %ymm0, (%rsp)505; X64-AVX-NEXT: vmovaps (%rsp), %ymm0506; X64-AVX-NEXT: vextractps $2, %xmm0, %esi507; X64-AVX-NEXT: xorl %edx, %edx508; X64-AVX-NEXT: divl %esi509; X64-AVX-NEXT: movl %eax, %esi510; X64-AVX-NEXT: vextractps $1, %xmm0, %edi511; X64-AVX-NEXT: movl %ecx, %eax512; X64-AVX-NEXT: xorl %edx, %edx513; X64-AVX-NEXT: divl %edi514; X64-AVX-NEXT: addl %esi, %eax515; X64-AVX-NEXT: movq %rbp, %rsp516; X64-AVX-NEXT: popq %rbp517; X64-AVX-NEXT: vzeroupper518; X64-AVX-NEXT: retq519 %stackptr = alloca <8 x i32>, align 32520 %z = load <8 x i32>, ptr @zero, align 32521 %t1 = load <8 x i32>, ptr @n1, align 32522 store <8 x i32> %t1, ptr @zero, align 32523 store volatile <8 x i32> <i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2>, ptr %stackptr, align 32524 %stackload = load volatile <8 x i32>, ptr %stackptr, align 32525 %div = udiv <8 x i32> %z, %stackload526 %e1 = extractelement <8 x i32> %div, i64 1527 %e2 = extractelement <8 x i32> %div, i64 2528 %r = add i32 %e1, %e2529 ret i32 %r530}531 532; A test for incorrect combine for single value extraction from VBROADCAST_LOAD.533; Wrong combine makes the second call (%t8) use the stored result in the534; previous instructions instead of %t4.535declare <2 x float> @ccosf(<2 x float>)536define dso_local <2 x float> @multiuse_of_single_value_from_vbroadcast_load(ptr %p, ptr %arr) nounwind {537; X86-SSE2-LABEL: multiuse_of_single_value_from_vbroadcast_load:538; X86-SSE2: # %bb.0:539; X86-SSE2-NEXT: pushl %esi540; X86-SSE2-NEXT: subl $16, %esp541; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax542; X86-SSE2-NEXT: movl {{[0-9]+}}(%esp), %esi543; X86-SSE2-NEXT: movups 24(%esi), %xmm0544; X86-SSE2-NEXT: movups %xmm0, (%esp) # 16-byte Spill545; X86-SSE2-NEXT: movhps %xmm0, (%eax)546; X86-SSE2-NEXT: movaps 32(%esi), %xmm0547; X86-SSE2-NEXT: calll ccosf@PLT548; X86-SSE2-NEXT: movlps %xmm0, 32(%esi)549; X86-SSE2-NEXT: movups (%esp), %xmm0 # 16-byte Reload550; X86-SSE2-NEXT: movhlps {{.*#+}} xmm0 = xmm0[1,1]551; X86-SSE2-NEXT: calll ccosf@PLT552; X86-SSE2-NEXT: addl $16, %esp553; X86-SSE2-NEXT: popl %esi554; X86-SSE2-NEXT: retl555;556; X64-SSSE3-LABEL: multiuse_of_single_value_from_vbroadcast_load:557; X64-SSSE3: # %bb.0:558; X64-SSSE3-NEXT: pushq %rbx559; X64-SSSE3-NEXT: subq $16, %rsp560; X64-SSSE3-NEXT: movq %rsi, %rbx561; X64-SSSE3-NEXT: movddup {{.*#+}} xmm0 = mem[0,0]562; X64-SSSE3-NEXT: movapd %xmm0, (%rsp) # 16-byte Spill563; X64-SSSE3-NEXT: movlpd %xmm0, (%rdi)564; X64-SSSE3-NEXT: movaps 32(%rsi), %xmm0565; X64-SSSE3-NEXT: callq ccosf@PLT566; X64-SSSE3-NEXT: movlps %xmm0, 32(%rbx)567; X64-SSSE3-NEXT: movaps (%rsp), %xmm0 # 16-byte Reload568; X64-SSSE3-NEXT: callq ccosf@PLT569; X64-SSSE3-NEXT: addq $16, %rsp570; X64-SSSE3-NEXT: popq %rbx571; X64-SSSE3-NEXT: retq572;573; X64-AVX-LABEL: multiuse_of_single_value_from_vbroadcast_load:574; X64-AVX: # %bb.0:575; X64-AVX-NEXT: pushq %rbx576; X64-AVX-NEXT: subq $16, %rsp577; X64-AVX-NEXT: movq %rsi, %rbx578; X64-AVX-NEXT: vmovddup {{.*#+}} xmm0 = mem[0,0]579; X64-AVX-NEXT: vmovaps %xmm0, (%rsp) # 16-byte Spill580; X64-AVX-NEXT: vmovlps %xmm0, (%rdi)581; X64-AVX-NEXT: vmovaps 32(%rsi), %xmm0582; X64-AVX-NEXT: callq ccosf@PLT583; X64-AVX-NEXT: vmovlps %xmm0, 32(%rbx)584; X64-AVX-NEXT: vmovaps (%rsp), %xmm0 # 16-byte Reload585; X64-AVX-NEXT: callq ccosf@PLT586; X64-AVX-NEXT: addq $16, %rsp587; X64-AVX-NEXT: popq %rbx588; X64-AVX-NEXT: retq589 %p1 = getelementptr [5 x <2 x float>], ptr %arr, i64 0, i64 3590 %p2 = getelementptr inbounds [5 x <2 x float>], ptr %arr, i64 0, i64 4, i32 0591 %t3 = load <4 x float>, ptr %p1, align 8592 %t4 = shufflevector <4 x float> %t3, <4 x float> poison, <2 x i32> <i32 2, i32 3>593 store <2 x float> %t4, ptr %p, align 16594 %t5 = load <4 x float>, ptr %p2, align 32595 %t6 = shufflevector <4 x float> %t5, <4 x float> poison, <2 x i32> <i32 0, i32 1>596 %t7 = call <2 x float> @ccosf(<2 x float> %t6)597 store <2 x float> %t7, ptr %p2, align 32598 %t8 = call <2 x float> @ccosf(<2 x float> %t4)599 ret <2 x float> %t8600}601