; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 ; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f | FileCheck %s --check-prefixes=CHECK,AVX512,AVX512F ; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512f,+avx512fp16 | FileCheck %s --check-prefixes=CHECK,AVX512,AVX512FP16 ; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512vl | FileCheck %s --check-prefixes=CHECK,AVX512VL,AVX512VLF ; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx512vl,+avx512fp16 | FileCheck %s --check-prefixes=CHECK,AVX512VLFP16 define half @test_half(half %x, i32 %exp) nounwind { ; AVX512F-LABEL: test_half: ; AVX512F: # %bb.0: # %entry ; AVX512F-NEXT: vcvtsi2ss %edi, %xmm15, %xmm1 ; AVX512F-NEXT: vcvtph2ps %xmm0, %xmm0 ; AVX512F-NEXT: vscalefss %xmm1, %xmm0, %xmm0 ; AVX512F-NEXT: vcvtps2ph $4, %xmm0, %xmm0 ; AVX512F-NEXT: retq ; ; AVX512FP16-LABEL: test_half: ; AVX512FP16: # %bb.0: # %entry ; AVX512FP16-NEXT: vcvtsi2sh %edi, %xmm31, %xmm1 ; AVX512FP16-NEXT: vscalefsh %xmm1, %xmm0, %xmm0 ; AVX512FP16-NEXT: retq ; ; AVX512VL-LABEL: test_half: ; AVX512VL: # %bb.0: # %entry ; AVX512VL-NEXT: vcvtsi2ss %edi, %xmm15, %xmm1 ; AVX512VL-NEXT: vcvtph2ps %xmm0, %xmm0 ; AVX512VL-NEXT: vscalefss %xmm1, %xmm0, %xmm0 ; AVX512VL-NEXT: vcvtps2ph $4, %xmm0, %xmm0 ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_half: ; AVX512VLFP16: # %bb.0: # %entry ; AVX512VLFP16-NEXT: vcvtsi2sh %edi, %xmm31, %xmm1 ; AVX512VLFP16-NEXT: vscalefsh %xmm1, %xmm0, %xmm0 ; AVX512VLFP16-NEXT: retq entry: %r = tail call fast half @llvm.ldexp.f16.i32(half %x, i32 %exp) ret half %r } declare half @llvm.ldexp.f16.i32(half, i32) memory(none) define float @test_float(float %x, i32 %exp) nounwind { ; CHECK-LABEL: test_float: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vcvtsi2ss %edi, %xmm15, %xmm1 ; CHECK-NEXT: vscalefss %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: retq entry: %r = tail call fast float @ldexpf(float %x, i32 %exp) ret float %r } declare float @ldexpf(float, i32) memory(none) define double @test_double(double %x, i32 %exp) nounwind { ; CHECK-LABEL: test_double: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: vcvtsi2sd %edi, %xmm15, %xmm1 ; CHECK-NEXT: vscalefsd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: retq entry: %r = tail call fast double @ldexp(double %x, i32 %exp) ret double %r } declare double @ldexp(double, i32) memory(none) define fp128 @testExpl(fp128 %x, i32 %exp) nounwind { ; CHECK-LABEL: testExpl: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: jmp ldexpl@PLT # TAILCALL entry: %r = tail call fast fp128 @ldexpl(fp128 %x, i32 %exp) ret fp128 %r } declare fp128 @ldexpl(fp128, i32) memory(none) define <8 x half> @test_ldexp_8xhalf(<8 x half> %x, <8 x i16> %exp) nounwind { ; AVX512F-LABEL: test_ldexp_8xhalf: ; AVX512F: # %bb.0: ; AVX512F-NEXT: vcvtph2ps %xmm0, %ymm0 ; AVX512F-NEXT: vpmovsxwd %xmm1, %ymm1 ; AVX512F-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512F-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512F-NEXT: vcvtps2ph $4, %ymm0, %xmm0 ; AVX512F-NEXT: vzeroupper ; AVX512F-NEXT: retq ; ; AVX512FP16-LABEL: test_ldexp_8xhalf: ; AVX512FP16: # %bb.0: ; AVX512FP16-NEXT: vxorps %xmm2, %xmm2, %xmm2 ; AVX512FP16-NEXT: vinsertf32x4 $0, %xmm0, %zmm2, %zmm0 ; AVX512FP16-NEXT: vmovaps %xmm1, %xmm1 ; AVX512FP16-NEXT: vcvtw2ph %zmm1, %zmm1 ; AVX512FP16-NEXT: vscalefph %zmm1, %zmm0, %zmm0 ; AVX512FP16-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0 ; AVX512FP16-NEXT: vzeroupper ; AVX512FP16-NEXT: retq ; ; AVX512VL-LABEL: test_ldexp_8xhalf: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vcvtph2ps %xmm0, %ymm0 ; AVX512VL-NEXT: vpmovsxwd %xmm1, %ymm1 ; AVX512VL-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512VL-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512VL-NEXT: vcvtps2ph $4, %ymm0, %xmm0 ; AVX512VL-NEXT: vzeroupper ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_ldexp_8xhalf: ; AVX512VLFP16: # %bb.0: ; AVX512VLFP16-NEXT: vcvtw2ph %xmm1, %xmm1 ; AVX512VLFP16-NEXT: vscalefph %xmm1, %xmm0, %xmm0 ; AVX512VLFP16-NEXT: retq %r = call <8 x half> @llvm.ldexp.v8f16.v8i16(<8 x half> %x, <8 x i16> %exp) ret <8 x half> %r } declare <8 x half> @llvm.ldexp.v8f16.v8i16(<8 x half>, <8 x i16>) define <4 x float> @test_ldexp_4xfloat(<4 x float> %x, <4 x i32> %exp) nounwind { ; AVX512-LABEL: test_ldexp_4xfloat: ; AVX512: # %bb.0: ; AVX512-NEXT: vmovaps %xmm0, %xmm0 ; AVX512-NEXT: vmovaps %xmm1, %xmm1 ; AVX512-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 killed $zmm0 ; AVX512-NEXT: vzeroupper ; AVX512-NEXT: retq ; ; AVX512VL-LABEL: test_ldexp_4xfloat: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vcvtdq2ps %xmm1, %xmm1 ; AVX512VL-NEXT: vscalefps %xmm1, %xmm0, %xmm0 ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_ldexp_4xfloat: ; AVX512VLFP16: # %bb.0: ; AVX512VLFP16-NEXT: vcvtdq2ps %xmm1, %xmm1 ; AVX512VLFP16-NEXT: vscalefps %xmm1, %xmm0, %xmm0 ; AVX512VLFP16-NEXT: retq %r = call <4 x float> @llvm.ldexp.v4f32.v4i32(<4 x float> %x, <4 x i32> %exp) ret <4 x float> %r } declare <4 x float> @llvm.ldexp.v4f32.v4i32(<4 x float>, <4 x i32>) define <2 x double> @test_ldexp_2xdouble(<2 x double> %x, <2 x i32> %exp) nounwind { ; CHECK-LABEL: test_ldexp_2xdouble: ; CHECK: # %bb.0: ; CHECK-NEXT: vcvtdq2pd %xmm1, %xmm2 ; CHECK-NEXT: vscalefsd %xmm2, %xmm0, %xmm2 ; CHECK-NEXT: vshufpd {{.*#+}} xmm0 = xmm0[1,0] ; CHECK-NEXT: vshufps {{.*#+}} xmm1 = xmm1[1,1,1,1] ; CHECK-NEXT: vcvtdq2pd %xmm1, %xmm1 ; CHECK-NEXT: vscalefsd %xmm1, %xmm0, %xmm0 ; CHECK-NEXT: vunpcklpd {{.*#+}} xmm0 = xmm2[0],xmm0[0] ; CHECK-NEXT: retq %r = call <2 x double> @llvm.ldexp.v2f64.v2i32(<2 x double> %x, <2 x i32> %exp) ret <2 x double> %r } declare <2 x double> @llvm.ldexp.v2f64.v2i32(<2 x double>, <2 x i32>) define <16 x half> @test_ldexp_16xhalf(<16 x half> %x, <16 x i16> %exp) nounwind { ; AVX512F-LABEL: test_ldexp_16xhalf: ; AVX512F: # %bb.0: ; AVX512F-NEXT: vcvtph2ps %ymm0, %zmm0 ; AVX512F-NEXT: vpmovsxwd %ymm1, %zmm1 ; AVX512F-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512F-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512F-NEXT: vcvtps2ph $4, %zmm0, %ymm0 ; AVX512F-NEXT: retq ; ; AVX512FP16-LABEL: test_ldexp_16xhalf: ; AVX512FP16: # %bb.0: ; AVX512FP16-NEXT: vxorps %xmm2, %xmm2, %xmm2 ; AVX512FP16-NEXT: vinsertf64x4 $0, %ymm0, %zmm2, %zmm0 ; AVX512FP16-NEXT: vmovaps %ymm1, %ymm1 ; AVX512FP16-NEXT: vcvtw2ph %zmm1, %zmm1 ; AVX512FP16-NEXT: vscalefph %zmm1, %zmm0, %zmm0 ; AVX512FP16-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0 ; AVX512FP16-NEXT: retq ; ; AVX512VL-LABEL: test_ldexp_16xhalf: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vcvtph2ps %ymm0, %zmm0 ; AVX512VL-NEXT: vpmovsxwd %ymm1, %zmm1 ; AVX512VL-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512VL-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512VL-NEXT: vcvtps2ph $4, %zmm0, %ymm0 ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_ldexp_16xhalf: ; AVX512VLFP16: # %bb.0: ; AVX512VLFP16-NEXT: vcvtw2ph %ymm1, %ymm1 ; AVX512VLFP16-NEXT: vscalefph %ymm1, %ymm0, %ymm0 ; AVX512VLFP16-NEXT: retq %r = call <16 x half> @llvm.ldexp.v16f16.v16i16(<16 x half> %x, <16 x i16> %exp) ret <16 x half> %r } declare <16 x half> @llvm.ldexp.v16f16.v16i16(<16 x half>, <16 x i16>) define <8 x float> @test_ldexp_8xfloat(<8 x float> %x, <8 x i32> %exp) nounwind { ; AVX512-LABEL: test_ldexp_8xfloat: ; AVX512: # %bb.0: ; AVX512-NEXT: vmovaps %ymm0, %ymm0 ; AVX512-NEXT: vmovaps %ymm1, %ymm1 ; AVX512-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0 ; AVX512-NEXT: retq ; ; AVX512VL-LABEL: test_ldexp_8xfloat: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vcvtdq2ps %ymm1, %ymm1 ; AVX512VL-NEXT: vscalefps %ymm1, %ymm0, %ymm0 ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_ldexp_8xfloat: ; AVX512VLFP16: # %bb.0: ; AVX512VLFP16-NEXT: vcvtdq2ps %ymm1, %ymm1 ; AVX512VLFP16-NEXT: vscalefps %ymm1, %ymm0, %ymm0 ; AVX512VLFP16-NEXT: retq %r = call <8 x float> @llvm.ldexp.v8f32.v8i32(<8 x float> %x, <8 x i32> %exp) ret <8 x float> %r } declare <8 x float> @llvm.ldexp.v8f32.v8i32(<8 x float>, <8 x i32>) define <4 x double> @test_ldexp_4xdouble(<4 x double> %x, <4 x i32> %exp) nounwind { ; AVX512-LABEL: test_ldexp_4xdouble: ; AVX512: # %bb.0: ; AVX512-NEXT: vmovapd %ymm0, %ymm0 ; AVX512-NEXT: vmovaps %xmm1, %xmm1 ; AVX512-NEXT: vcvtdq2pd %ymm1, %zmm1 ; AVX512-NEXT: vscalefpd %zmm1, %zmm0, %zmm0 ; AVX512-NEXT: # kill: def $ymm0 killed $ymm0 killed $zmm0 ; AVX512-NEXT: retq ; ; AVX512VL-LABEL: test_ldexp_4xdouble: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vcvtdq2pd %xmm1, %ymm1 ; AVX512VL-NEXT: vscalefpd %ymm1, %ymm0, %ymm0 ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_ldexp_4xdouble: ; AVX512VLFP16: # %bb.0: ; AVX512VLFP16-NEXT: vcvtdq2pd %xmm1, %ymm1 ; AVX512VLFP16-NEXT: vscalefpd %ymm1, %ymm0, %ymm0 ; AVX512VLFP16-NEXT: retq %r = call <4 x double> @llvm.ldexp.v4f64.v4i32(<4 x double> %x, <4 x i32> %exp) ret <4 x double> %r } declare <4 x double> @llvm.ldexp.v4f64.v4i32(<4 x double>, <4 x i32>) define <32 x half> @test_ldexp_32xhalf(<32 x half> %x, <32 x i16> %exp) nounwind { ; AVX512F-LABEL: test_ldexp_32xhalf: ; AVX512F: # %bb.0: ; AVX512F-NEXT: vcvtph2ps %ymm0, %zmm2 ; AVX512F-NEXT: vpmovsxwd %ymm1, %zmm3 ; AVX512F-NEXT: vcvtdq2ps %zmm3, %zmm3 ; AVX512F-NEXT: vscalefps %zmm3, %zmm2, %zmm2 ; AVX512F-NEXT: vcvtps2ph $4, %zmm2, %ymm2 ; AVX512F-NEXT: vextractf64x4 $1, %zmm0, %ymm0 ; AVX512F-NEXT: vcvtph2ps %ymm0, %zmm0 ; AVX512F-NEXT: vextracti64x4 $1, %zmm1, %ymm1 ; AVX512F-NEXT: vpmovsxwd %ymm1, %zmm1 ; AVX512F-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512F-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512F-NEXT: vcvtps2ph $4, %zmm0, %ymm0 ; AVX512F-NEXT: vinsertf64x4 $1, %ymm0, %zmm2, %zmm0 ; AVX512F-NEXT: retq ; ; AVX512FP16-LABEL: test_ldexp_32xhalf: ; AVX512FP16: # %bb.0: ; AVX512FP16-NEXT: vcvtw2ph %zmm1, %zmm1 ; AVX512FP16-NEXT: vscalefph %zmm1, %zmm0, %zmm0 ; AVX512FP16-NEXT: retq ; ; AVX512VL-LABEL: test_ldexp_32xhalf: ; AVX512VL: # %bb.0: ; AVX512VL-NEXT: vcvtph2ps %ymm0, %zmm2 ; AVX512VL-NEXT: vpmovsxwd %ymm1, %zmm3 ; AVX512VL-NEXT: vcvtdq2ps %zmm3, %zmm3 ; AVX512VL-NEXT: vscalefps %zmm3, %zmm2, %zmm2 ; AVX512VL-NEXT: vcvtps2ph $4, %zmm2, %ymm2 ; AVX512VL-NEXT: vextractf64x4 $1, %zmm0, %ymm0 ; AVX512VL-NEXT: vcvtph2ps %ymm0, %zmm0 ; AVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm1 ; AVX512VL-NEXT: vpmovsxwd %ymm1, %zmm1 ; AVX512VL-NEXT: vcvtdq2ps %zmm1, %zmm1 ; AVX512VL-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; AVX512VL-NEXT: vcvtps2ph $4, %zmm0, %ymm0 ; AVX512VL-NEXT: vinsertf64x4 $1, %ymm0, %zmm2, %zmm0 ; AVX512VL-NEXT: retq ; ; AVX512VLFP16-LABEL: test_ldexp_32xhalf: ; AVX512VLFP16: # %bb.0: ; AVX512VLFP16-NEXT: vcvtw2ph %zmm1, %zmm1 ; AVX512VLFP16-NEXT: vscalefph %zmm1, %zmm0, %zmm0 ; AVX512VLFP16-NEXT: retq %r = call <32 x half> @llvm.ldexp.v32f16.v32i16(<32 x half> %x, <32 x i16> %exp) ret <32 x half> %r } declare <32 x half> @llvm.ldexp.v32f16.v32i16(<32 x half>, <32 x i16>) define <16 x float> @test_ldexp_16xfloat(<16 x float> %x, <16 x i32> %exp) nounwind { ; CHECK-LABEL: test_ldexp_16xfloat: ; CHECK: # %bb.0: ; CHECK-NEXT: vcvtdq2ps %zmm1, %zmm1 ; CHECK-NEXT: vscalefps %zmm1, %zmm0, %zmm0 ; CHECK-NEXT: retq %r = call <16 x float> @llvm.ldexp.v16f32.v16i32(<16 x float> %x, <16 x i32> %exp) ret <16 x float> %r } declare <16 x float> @llvm.ldexp.v16f32.v16i32(<16 x float>, <16 x i32>) define <8 x double> @test_ldexp_8xdouble(<8 x double> %x, <8 x i32> %exp) nounwind { ; CHECK-LABEL: test_ldexp_8xdouble: ; CHECK: # %bb.0: ; CHECK-NEXT: vcvtdq2pd %ymm1, %zmm1 ; CHECK-NEXT: vscalefpd %zmm1, %zmm0, %zmm0 ; CHECK-NEXT: retq %r = call <8 x double> @llvm.ldexp.v8f64.v8i32(<8 x double> %x, <8 x i32> %exp) ret <8 x double> %r } declare <8 x double> @llvm.ldexp.v8f64.v8i32(<8 x double>, <8 x i32>) ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: ; AVX512VLF: {{.*}}