214 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=X863; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=X644 5; When extracting multiple consecutive elements from a larger6; vector into a smaller one, do it efficiently. We should use7; an EXTRACT_SUBVECTOR node internally rather than a bunch of8; single element extractions.9 10; Extracting the low elements only requires using the right kind of store.11define void @low_v8f32_to_v4f32(<8 x float> %v, ptr %ptr) {12; X86-LABEL: low_v8f32_to_v4f32:13; X86: # %bb.0:14; X86-NEXT: movl {{[0-9]+}}(%esp), %eax15; X86-NEXT: vmovaps %xmm0, (%eax)16; X86-NEXT: vzeroupper17; X86-NEXT: retl18;19; X64-LABEL: low_v8f32_to_v4f32:20; X64: # %bb.0:21; X64-NEXT: vmovaps %xmm0, (%rdi)22; X64-NEXT: vzeroupper23; X64-NEXT: retq24 %ext0 = extractelement <8 x float> %v, i32 025 %ext1 = extractelement <8 x float> %v, i32 126 %ext2 = extractelement <8 x float> %v, i32 227 %ext3 = extractelement <8 x float> %v, i32 328 %ins0 = insertelement <4 x float> undef, float %ext0, i32 029 %ins1 = insertelement <4 x float> %ins0, float %ext1, i32 130 %ins2 = insertelement <4 x float> %ins1, float %ext2, i32 231 %ins3 = insertelement <4 x float> %ins2, float %ext3, i32 332 store <4 x float> %ins3, ptr %ptr, align 1633 ret void34}35 36; Extracting the high elements requires just one AVX instruction.37define void @high_v8f32_to_v4f32(<8 x float> %v, ptr %ptr) {38; X86-LABEL: high_v8f32_to_v4f32:39; X86: # %bb.0:40; X86-NEXT: movl {{[0-9]+}}(%esp), %eax41; X86-NEXT: vextractf128 $1, %ymm0, (%eax)42; X86-NEXT: vzeroupper43; X86-NEXT: retl44;45; X64-LABEL: high_v8f32_to_v4f32:46; X64: # %bb.0:47; X64-NEXT: vextractf128 $1, %ymm0, (%rdi)48; X64-NEXT: vzeroupper49; X64-NEXT: retq50 %ext0 = extractelement <8 x float> %v, i32 451 %ext1 = extractelement <8 x float> %v, i32 552 %ext2 = extractelement <8 x float> %v, i32 653 %ext3 = extractelement <8 x float> %v, i32 754 %ins0 = insertelement <4 x float> undef, float %ext0, i32 055 %ins1 = insertelement <4 x float> %ins0, float %ext1, i32 156 %ins2 = insertelement <4 x float> %ins1, float %ext2, i32 257 %ins3 = insertelement <4 x float> %ins2, float %ext3, i32 358 store <4 x float> %ins3, ptr %ptr, align 1659 ret void60}61 62; Make sure element type doesn't alter the codegen. Note that63; if we were actually using the vector in this function and64; have AVX2, we should generate vextracti128 (the int version).65define void @high_v8i32_to_v4i32(<8 x i32> %v, ptr %ptr) {66; X86-LABEL: high_v8i32_to_v4i32:67; X86: # %bb.0:68; X86-NEXT: movl {{[0-9]+}}(%esp), %eax69; X86-NEXT: vextractf128 $1, %ymm0, (%eax)70; X86-NEXT: vzeroupper71; X86-NEXT: retl72;73; X64-LABEL: high_v8i32_to_v4i32:74; X64: # %bb.0:75; X64-NEXT: vextractf128 $1, %ymm0, (%rdi)76; X64-NEXT: vzeroupper77; X64-NEXT: retq78 %ext0 = extractelement <8 x i32> %v, i32 479 %ext1 = extractelement <8 x i32> %v, i32 580 %ext2 = extractelement <8 x i32> %v, i32 681 %ext3 = extractelement <8 x i32> %v, i32 782 %ins0 = insertelement <4 x i32> undef, i32 %ext0, i32 083 %ins1 = insertelement <4 x i32> %ins0, i32 %ext1, i32 184 %ins2 = insertelement <4 x i32> %ins1, i32 %ext2, i32 285 %ins3 = insertelement <4 x i32> %ins2, i32 %ext3, i32 386 store <4 x i32> %ins3, ptr %ptr, align 1687 ret void88}89 90; Make sure that element size doesn't alter the codegen.91define void @high_v4f64_to_v2f64(<4 x double> %v, ptr %ptr) {92; X86-LABEL: high_v4f64_to_v2f64:93; X86: # %bb.0:94; X86-NEXT: movl {{[0-9]+}}(%esp), %eax95; X86-NEXT: vextractf128 $1, %ymm0, (%eax)96; X86-NEXT: vzeroupper97; X86-NEXT: retl98;99; X64-LABEL: high_v4f64_to_v2f64:100; X64: # %bb.0:101; X64-NEXT: vextractf128 $1, %ymm0, (%rdi)102; X64-NEXT: vzeroupper103; X64-NEXT: retq104 %ext0 = extractelement <4 x double> %v, i32 2105 %ext1 = extractelement <4 x double> %v, i32 3106 %ins0 = insertelement <2 x double> undef, double %ext0, i32 0107 %ins1 = insertelement <2 x double> %ins0, double %ext1, i32 1108 store <2 x double> %ins1, ptr %ptr, align 16109 ret void110}111 112; PR25320 Make sure that a widened (possibly legalized) vector correctly zero-extends upper elements.113; FIXME - Ideally these should just call VMOVD/VMOVQ/VMOVSS/VMOVSD114 115define void @legal_vzmovl_2i32_8i32(ptr %in, ptr %out) {116; X86-LABEL: legal_vzmovl_2i32_8i32:117; X86: # %bb.0:118; X86-NEXT: movl {{[0-9]+}}(%esp), %eax119; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx120; X86-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero121; X86-NEXT: vxorps %xmm1, %xmm1, %xmm1122; X86-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]123; X86-NEXT: vmovaps %ymm0, (%eax)124; X86-NEXT: vzeroupper125; X86-NEXT: retl126;127; X64-LABEL: legal_vzmovl_2i32_8i32:128; X64: # %bb.0:129; X64-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero130; X64-NEXT: vxorps %xmm1, %xmm1, %xmm1131; X64-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]132; X64-NEXT: vmovaps %ymm0, (%rsi)133; X64-NEXT: vzeroupper134; X64-NEXT: retq135 %ld = load <2 x i32>, ptr %in, align 8136 %ext = extractelement <2 x i32> %ld, i64 0137 %ins = insertelement <8 x i32> <i32 undef, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, i32 %ext, i64 0138 store <8 x i32> %ins, ptr %out, align 32139 ret void140}141 142define void @legal_vzmovl_2i64_4i64(ptr %in, ptr %out) {143; X86-LABEL: legal_vzmovl_2i64_4i64:144; X86: # %bb.0:145; X86-NEXT: movl {{[0-9]+}}(%esp), %eax146; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx147; X86-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero148; X86-NEXT: vmovaps %ymm0, (%eax)149; X86-NEXT: vzeroupper150; X86-NEXT: retl151;152; X64-LABEL: legal_vzmovl_2i64_4i64:153; X64: # %bb.0:154; X64-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero155; X64-NEXT: vmovaps %ymm0, (%rsi)156; X64-NEXT: vzeroupper157; X64-NEXT: retq158 %ld = load <2 x i64>, ptr %in, align 8159 %ext = extractelement <2 x i64> %ld, i64 0160 %ins = insertelement <4 x i64> <i64 undef, i64 0, i64 0, i64 0>, i64 %ext, i64 0161 store <4 x i64> %ins, ptr %out, align 32162 ret void163}164 165define void @legal_vzmovl_2f32_8f32(ptr %in, ptr %out) {166; X86-LABEL: legal_vzmovl_2f32_8f32:167; X86: # %bb.0:168; X86-NEXT: movl {{[0-9]+}}(%esp), %eax169; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx170; X86-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero171; X86-NEXT: vxorps %xmm1, %xmm1, %xmm1172; X86-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]173; X86-NEXT: vmovaps %ymm0, (%eax)174; X86-NEXT: vzeroupper175; X86-NEXT: retl176;177; X64-LABEL: legal_vzmovl_2f32_8f32:178; X64: # %bb.0:179; X64-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero180; X64-NEXT: vxorps %xmm1, %xmm1, %xmm1181; X64-NEXT: vmovss {{.*#+}} xmm0 = xmm0[0],xmm1[1,2,3]182; X64-NEXT: vmovaps %ymm0, (%rsi)183; X64-NEXT: vzeroupper184; X64-NEXT: retq185 %ld = load <2 x float>, ptr %in, align 8186 %ext = extractelement <2 x float> %ld, i64 0187 %ins = insertelement <8 x float> <float undef, float 0.0, float 0.0, float 0.0, float 0.0, float 0.0, float 0.0, float 0.0>, float %ext, i64 0188 store <8 x float> %ins, ptr %out, align 32189 ret void190}191 192define void @legal_vzmovl_2f64_4f64(ptr %in, ptr %out) {193; X86-LABEL: legal_vzmovl_2f64_4f64:194; X86: # %bb.0:195; X86-NEXT: movl {{[0-9]+}}(%esp), %eax196; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx197; X86-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero198; X86-NEXT: vmovaps %ymm0, (%eax)199; X86-NEXT: vzeroupper200; X86-NEXT: retl201;202; X64-LABEL: legal_vzmovl_2f64_4f64:203; X64: # %bb.0:204; X64-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero205; X64-NEXT: vmovaps %ymm0, (%rsi)206; X64-NEXT: vzeroupper207; X64-NEXT: retq208 %ld = load <2 x double>, ptr %in, align 8209 %ext = extractelement <2 x double> %ld, i64 0210 %ins = insertelement <4 x double> <double undef, double 0.0, double 0.0, double 0.0>, double %ext, i64 0211 store <4 x double> %ins, ptr %out, align 32212 ret void213}214