| ; 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: vpmovsxwd %xmm1, %ymm1 |
| ; AVX512F-NEXT: vcvtph2ps %xmm0, %ymm0 |
| ; 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: 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: vpmovsxwd %xmm1, %ymm1 |
| ; AVX512VL-NEXT: vcvtph2ps %xmm0, %ymm0 |
| ; 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 %xmm1, %xmm1 |
| ; AVX512-NEXT: vmovaps %xmm0, %xmm0 |
| ; 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: vpmovsxwd %ymm1, %zmm1 |
| ; AVX512F-NEXT: vcvtph2ps %ymm0, %zmm0 |
| ; 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: 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: vpmovsxwd %ymm1, %zmm1 |
| ; AVX512VL-NEXT: vcvtph2ps %ymm0, %zmm0 |
| ; 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 %ymm1, %ymm1 |
| ; AVX512-NEXT: vmovaps %ymm0, %ymm0 |
| ; 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 %xmm1, %xmm1 |
| ; AVX512-NEXT: vmovapd %ymm0, %ymm0 |
| ; 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: vpmovsxwd %ymm1, %zmm2 |
| ; AVX512F-NEXT: vcvtph2ps %ymm0, %zmm3 |
| ; AVX512F-NEXT: vscalefps %zmm2, %zmm3, %zmm2 |
| ; AVX512F-NEXT: vcvtps2ph $4, %zmm2, %ymm2 |
| ; AVX512F-NEXT: vextracti64x4 $1, %zmm1, %ymm1 |
| ; AVX512F-NEXT: vpmovsxwd %ymm1, %zmm1 |
| ; AVX512F-NEXT: vextractf64x4 $1, %zmm0, %ymm0 |
| ; AVX512F-NEXT: vcvtph2ps %ymm0, %zmm0 |
| ; 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: vpmovsxwd %ymm1, %zmm2 |
| ; AVX512VL-NEXT: vcvtph2ps %ymm0, %zmm3 |
| ; AVX512VL-NEXT: vscalefps %zmm2, %zmm3, %zmm2 |
| ; AVX512VL-NEXT: vcvtps2ph $4, %zmm2, %ymm2 |
| ; AVX512VL-NEXT: vextracti64x4 $1, %zmm1, %ymm1 |
| ; AVX512VL-NEXT: vpmovsxwd %ymm1, %zmm1 |
| ; AVX512VL-NEXT: vextractf64x4 $1, %zmm0, %ymm0 |
| ; AVX512VL-NEXT: vcvtph2ps %ymm0, %zmm0 |
| ; 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: {{.*}} |