| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 |
| ; RUN: llc -mtriple=amdgpu9.50 < %s | FileCheck --check-prefixes=GFX950 %s |
| ; RUN: llc -mtriple=amdgpu12.50 -mattr=-real-true16 < %s | FileCheck --check-prefixes=GFX1250 %s |
| |
| define amdgpu_ps void @strict_fptrunc_f32_to_bf16(float %a, ptr %out) #0 { |
| ; GFX950-LABEL: strict_fptrunc_f32_to_bf16: |
| ; GFX950: ; %bb.0: |
| ; GFX950-NEXT: v_mov_b32_e32 v3, v2 |
| ; GFX950-NEXT: v_mov_b32_e32 v2, v1 |
| ; GFX950-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0 |
| ; GFX950-NEXT: flat_store_short v[2:3], v0 |
| ; GFX950-NEXT: s_endpgm |
| ; |
| ; GFX1250-LABEL: strict_fptrunc_f32_to_bf16: |
| ; GFX1250: ; %bb.0: |
| ; GFX1250-NEXT: global_wb |
| ; GFX1250-NEXT: v_nop |
| ; GFX1250-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0 |
| ; GFX1250-NEXT: v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v2, v1 |
| ; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0 |
| ; GFX1250-NEXT: flat_store_b16 v[2:3], v0 |
| ; GFX1250-NEXT: s_endpgm |
| %cvt = call bfloat @llvm.experimental.constrained.fptrunc.bf16.f32(float %a, metadata !"round.tonearest", metadata !"fpexcept.strict") |
| store bfloat %cvt, ptr %out |
| ret void |
| } |
| |
| define amdgpu_ps void @strict_fptrunc_f64_to_bf16(double %a, ptr %out) #0 { |
| ; GFX950-LABEL: strict_fptrunc_f64_to_bf16: |
| ; GFX950: ; %bb.0: |
| ; GFX950-NEXT: v_cvt_f32_f64_e32 v6, v[0:1] |
| ; GFX950-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 |
| ; GFX950-NEXT: v_and_b32_e32 v7, 1, v6 |
| ; GFX950-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[0:1]|, |v[4:5]| |
| ; GFX950-NEXT: v_cmp_nlg_f64_e32 vcc, v[0:1], v[4:5] |
| ; GFX950-NEXT: v_cmp_eq_u32_e64 s[0:1], 1, v7 |
| ; GFX950-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[2:3] |
| ; GFX950-NEXT: v_add_u32_e32 v0, v6, v0 |
| ; GFX950-NEXT: s_or_b64 vcc, vcc, s[0:1] |
| ; GFX950-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc |
| ; GFX950-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0 |
| ; GFX950-NEXT: flat_store_short v[2:3], v0 |
| ; GFX950-NEXT: s_endpgm |
| ; |
| ; GFX1250-LABEL: strict_fptrunc_f64_to_bf16: |
| ; GFX1250: ; %bb.0: |
| ; GFX1250-NEXT: global_wb |
| ; GFX1250-NEXT: v_nop |
| ; GFX1250-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0 |
| ; GFX1250-NEXT: v_cvt_f32_f64_e32 v6, v[0:1] |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) |
| ; GFX1250-NEXT: v_cvt_f64_f32_e32 v[4:5], v6 |
| ; GFX1250-NEXT: v_cmp_gt_f64_e64 s0, |v[0:1]|, |v[4:5]| |
| ; GFX1250-NEXT: v_cmp_nlg_f64_e32 vcc_lo, v[0:1], v[4:5] |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1) |
| ; GFX1250-NEXT: v_cndmask_b32_e64 v0, -1, 1, s0 |
| ; GFX1250-NEXT: v_dual_add_nc_u32 v0, v6, v0 :: v_dual_bitop2_b32 v7, 1, v6 bitop3:0x40 |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_2) | instid1(VALU_DEP_1) |
| ; GFX1250-NEXT: v_cmp_eq_u32_e64 s0, 1, v7 |
| ; GFX1250-NEXT: s_or_b32 vcc_lo, vcc_lo, s0 |
| ; GFX1250-NEXT: v_cndmask_b32_e32 v0, v0, v6, vcc_lo |
| ; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, s0 |
| ; GFX1250-NEXT: flat_store_b16 v[2:3], v0 |
| ; GFX1250-NEXT: s_endpgm |
| %cvt = call bfloat @llvm.experimental.constrained.fptrunc.bf16.f64(double %a, metadata !"round.tonearest", metadata !"fpexcept.strict") |
| store bfloat %cvt, ptr %out |
| ret void |
| } |
| |
| define amdgpu_ps void @strict_fptrunc_v2f32_to_v2bf16(<2 x float> %a, ptr %out) #0 { |
| ; GFX950-LABEL: strict_fptrunc_v2f32_to_v2bf16: |
| ; GFX950: ; %bb.0: |
| ; GFX950-NEXT: v_cvt_pk_bf16_f32 v0, v0, v1 |
| ; GFX950-NEXT: flat_store_dword v[2:3], v0 |
| ; GFX950-NEXT: s_endpgm |
| ; |
| ; GFX1250-LABEL: strict_fptrunc_v2f32_to_v2bf16: |
| ; GFX1250: ; %bb.0: |
| ; GFX1250-NEXT: global_wb |
| ; GFX1250-NEXT: v_nop |
| ; GFX1250-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0 |
| ; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, v1 |
| ; GFX1250-NEXT: flat_store_b32 v[2:3], v0 |
| ; GFX1250-NEXT: s_endpgm |
| %cvt = call <2 x bfloat> @llvm.experimental.constrained.fptrunc.v2bf16.v2f32(<2 x float> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") |
| store <2 x bfloat> %cvt, ptr %out |
| ret void |
| } |
| |
| define amdgpu_ps void @strict_fptrunc_v2f64_to_v2bf16(<2 x double> %a, ptr %out) #0 { |
| ; GFX950-LABEL: strict_fptrunc_v2f64_to_v2bf16: |
| ; GFX950: ; %bb.0: |
| ; GFX950-NEXT: v_cvt_f32_f64_e32 v8, v[2:3] |
| ; GFX950-NEXT: v_and_b32_e32 v6, 1, v8 |
| ; GFX950-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6 |
| ; GFX950-NEXT: v_cvt_f64_f32_e32 v[6:7], v8 |
| ; GFX950-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[2:3]|, |v[6:7]| |
| ; GFX950-NEXT: v_cmp_nlg_f64_e64 s[0:1], v[2:3], v[6:7] |
| ; GFX950-NEXT: v_cvt_f32_f64_e32 v9, v[0:1] |
| ; GFX950-NEXT: v_cndmask_b32_e64 v2, -1, 1, s[2:3] |
| ; GFX950-NEXT: v_add_u32_e32 v2, v8, v2 |
| ; GFX950-NEXT: s_or_b64 vcc, vcc, s[0:1] |
| ; GFX950-NEXT: v_cndmask_b32_e32 v6, v2, v8, vcc |
| ; GFX950-NEXT: v_cvt_f64_f32_e32 v[2:3], v9 |
| ; GFX950-NEXT: v_and_b32_e32 v10, 1, v9 |
| ; GFX950-NEXT: v_cmp_gt_f64_e64 s[2:3], |v[0:1]|, |v[2:3]| |
| ; GFX950-NEXT: v_cmp_ne_u32_e32 vcc, 0, v10 |
| ; GFX950-NEXT: v_cmp_nlg_f64_e64 s[0:1], v[0:1], v[2:3] |
| ; GFX950-NEXT: v_cndmask_b32_e64 v0, -1, 1, s[2:3] |
| ; GFX950-NEXT: v_add_u32_e32 v0, v9, v0 |
| ; GFX950-NEXT: s_or_b64 vcc, vcc, s[0:1] |
| ; GFX950-NEXT: v_cndmask_b32_e32 v0, v0, v9, vcc |
| ; GFX950-NEXT: v_cvt_pk_bf16_f32 v0, v0, v6 |
| ; GFX950-NEXT: flat_store_dword v[4:5], v0 |
| ; GFX950-NEXT: s_endpgm |
| ; |
| ; GFX1250-LABEL: strict_fptrunc_v2f64_to_v2bf16: |
| ; GFX1250: ; %bb.0: |
| ; GFX1250-NEXT: global_wb |
| ; GFX1250-NEXT: v_nop |
| ; GFX1250-NEXT: s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0 |
| ; GFX1250-NEXT: v_cvt_f32_f64_e32 v10, v[2:3] |
| ; GFX1250-NEXT: v_cvt_f32_f64_e32 v11, v[0:1] |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) |
| ; GFX1250-NEXT: v_cvt_f64_f32_e32 v[6:7], v10 |
| ; GFX1250-NEXT: v_cvt_f64_f32_e32 v[8:9], v11 |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(SKIP_1) | instid1(VALU_DEP_3) |
| ; GFX1250-NEXT: v_cmp_gt_f64_e64 s1, |v[2:3]|, |v[6:7]| |
| ; GFX1250-NEXT: v_cmp_nlg_f64_e32 vcc_lo, v[2:3], v[6:7] |
| ; GFX1250-NEXT: v_cmp_nlg_f64_e64 s0, v[0:1], v[8:9] |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_3) | instskip(SKIP_1) | instid1(VALU_DEP_2) |
| ; GFX1250-NEXT: v_cndmask_b32_e64 v2, -1, 1, s1 |
| ; GFX1250-NEXT: v_cmp_gt_f64_e64 s1, |v[0:1]|, |v[8:9]| |
| ; GFX1250-NEXT: v_dual_add_nc_u32 v1, v10, v2 :: v_dual_bitop2_b32 v13, 1, v11 bitop3:0x40 |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_3) |
| ; GFX1250-NEXT: v_cmp_ne_u32_e64 s2, 0, v13 |
| ; GFX1250-NEXT: v_cndmask_b32_e64 v0, -1, 1, s1 |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) |
| ; GFX1250-NEXT: v_dual_add_nc_u32 v0, v11, v0 :: v_dual_bitop2_b32 v12, 1, v10 bitop3:0x40 |
| ; GFX1250-NEXT: v_cmp_ne_u32_e64 s1, 0, v12 |
| ; GFX1250-NEXT: s_or_b32 vcc_lo, s1, vcc_lo |
| ; GFX1250-NEXT: v_cndmask_b32_e32 v1, v1, v10, vcc_lo |
| ; GFX1250-NEXT: s_or_b32 vcc_lo, s2, s0 |
| ; GFX1250-NEXT: v_cndmask_b32_e32 v0, v0, v11, vcc_lo |
| ; GFX1250-NEXT: s_delay_alu instid0(VALU_DEP_1) |
| ; GFX1250-NEXT: v_cvt_pk_bf16_f32 v0, v0, v1 |
| ; GFX1250-NEXT: flat_store_b32 v[4:5], v0 |
| ; GFX1250-NEXT: s_endpgm |
| %cvt = call <2 x bfloat> @llvm.experimental.constrained.fptrunc.v2bf16.v2f64(<2 x double> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") |
| store <2 x bfloat> %cvt, ptr %out |
| ret void |
| } |
| |
| declare bfloat @llvm.experimental.constrained.fptrunc.bf16.f32(float, metadata, metadata) |
| declare bfloat @llvm.experimental.constrained.fptrunc.bf16.f64(double, metadata, metadata) |
| declare <2 x bfloat> @llvm.experimental.constrained.fptrunc.v2bf16.v2f32(<2 x float>, metadata, metadata) |
| declare <2 x bfloat> @llvm.experimental.constrained.fptrunc.v2bf16.v2f64(<2 x double>, metadata, metadata) |
| |
| attributes #0 = { strictfp } |