| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: llc < %s -mtriple=amdgpu12.50-amd-amdhsa -mattr=+real-true16 | FileCheck -check-prefixes=GFX1250,GFX1250-TRUE16 %s | |
| ; RUN: llc < %s -mtriple=amdgpu12.50-amd-amdhsa -mattr=-real-true16 | FileCheck -check-prefixes=GFX1250,GFX1250-FAKE16 %s | |
| ; llvm.convert.from.arbitrary.fp from FP8/BF8 producing f16 result types, | |
| ; lowered via the gfx1250+ unscaled v_cvt_{pk_}f16_{fp8,bf8} instructions. | |
| ; Scalar Float8E4M3FN | |
| define half @from_fp8_f16_s(i8 %x) { | |
| ; GFX1250-TRUE16-LABEL: from_fp8_f16_s: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_cvt_f16_fp8_e32 v0.l, v0 | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_fp8_f16_s: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_cvt_f16_fp8_e32 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 %x, metadata !"Float8E4M3FN") | |
| ret half %r | |
| } | |
| ; Scalar Float8E5M2 | |
| define half @from_bf8_f16_s(i8 %x) { | |
| ; GFX1250-TRUE16-LABEL: from_bf8_f16_s: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_cvt_f16_bf8_e32 v0.l, v0 | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_bf8_f16_s: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_cvt_f16_bf8_e32 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call half @llvm.convert.from.arbitrary.fp.f16.i8(i8 %x, metadata !"Float8E5M2") | |
| ret half %r | |
| } | |
| ; Vector Float8E4M3FN | |
| define <2 x half> @from_fp8_v2f16(<2 x i8> %x) { | |
| ; GFX1250-TRUE16-LABEL: from_fp8_v2f16: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v1.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v1.l, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v0, v0.l | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_fp8_v2f16: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call <2 x half> @llvm.convert.from.arbitrary.fp.v2f16.v2i8(<2 x i8> %x, metadata !"Float8E4M3FN") | |
| ret <2 x half> %r | |
| } | |
| ; Vector Float8E5M2 | |
| define <2 x half> @from_bf8_v2f16(<2 x i8> %x) { | |
| ; GFX1250-TRUE16-LABEL: from_bf8_v2f16: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v1.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v1.l, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v0, v0.l | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_bf8_v2f16: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1) | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call <2 x half> @llvm.convert.from.arbitrary.fp.v2f16.v2i8(<2 x i8> %x, metadata !"Float8E5M2") | |
| ret <2 x half> %r | |
| } | |
| ; v3f16 Float8E4M3FN | |
| define <3 x half> @from_fp8_v3f16(<3 x i8> %x) { | |
| ; GFX1250-TRUE16-LABEL: from_fp8_v3f16: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l | |
| ; GFX1250-TRUE16-NEXT: v_and_b16 v1.l, 0xff, v2.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v1, v1.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v0, v0.l | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_fp8_v3f16: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: v_and_b32_e32 v1, 0xff, v2 | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v1, v1 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call <3 x half> @llvm.convert.from.arbitrary.fp.v3f16.v3i8(<3 x i8> %x, metadata !"Float8E4M3FN") | |
| ret <3 x half> %r | |
| } | |
| ; v3f16 Float8E5M2 | |
| define <3 x half> @from_bf8_v3f16(<3 x i8> %x) { | |
| ; GFX1250-TRUE16-LABEL: from_bf8_v3f16: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l | |
| ; GFX1250-TRUE16-NEXT: v_and_b16 v1.l, 0xff, v2.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v1, v1.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v0, v0.l | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_bf8_v3f16: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: v_and_b32_e32 v1, 0xff, v2 | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v1, v1 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call <3 x half> @llvm.convert.from.arbitrary.fp.v3f16.v3i8(<3 x i8> %x, metadata !"Float8E5M2") | |
| ret <3 x half> %r | |
| } | |
| ; v4f16 Float8E4M3FN | |
| define <4 x half> @from_fp8_v4f16(<4 x i8> %x) { | |
| ; GFX1250-TRUE16-LABEL: from_fp8_v4f16: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v3.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v1.l, v2.l, v1.l, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v0, v0.l | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_fp8 v1, v1.l | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_fp8_v4f16: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v3, 8, v3 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v1, v2, v3, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_fp8 v1, v1 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8> %x, metadata !"Float8E4M3FN") | |
| ret <4 x half> %r | |
| } | |
| ; v4f16 Float8E5M2 | |
| define <4 x half> @from_bf8_v4f16(<4 x i8> %x) { | |
| ; GFX1250-TRUE16-LABEL: from_bf8_v4f16: | |
| ; GFX1250-TRUE16: ; %bb.0: | |
| ; GFX1250-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v0.h, 8, v1.l | |
| ; GFX1250-TRUE16-NEXT: v_lshlrev_b16 v1.l, 8, v3.l | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v0.l, v0.l, v0.h, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: v_bitop3_b16 v1.l, v2.l, v1.l, 0xff bitop3:0xec | |
| ; GFX1250-TRUE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v0, v0.l | |
| ; GFX1250-TRUE16-NEXT: v_cvt_pk_f16_bf8 v1, v1.l | |
| ; GFX1250-TRUE16-NEXT: s_set_pc_i64 s[30:31] | |
| ; | |
| ; GFX1250-FAKE16-LABEL: from_bf8_v4f16: | |
| ; GFX1250-FAKE16: ; %bb.0: | |
| ; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v1, 8, v1 | |
| ; GFX1250-FAKE16-NEXT: v_lshlrev_b16 v3, 8, v3 | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v0, v0, v1, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: v_bitop3_b16 v1, v2, v3, 0xff bitop3:0xec | |
| ; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2) | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v0, v0 | |
| ; GFX1250-FAKE16-NEXT: v_cvt_pk_f16_bf8 v1, v1 | |
| ; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31] | |
| %r = call <4 x half> @llvm.convert.from.arbitrary.fp.v4f16.v4i8(<4 x i8> %x, metadata !"Float8E5M2") | |
| ret <4 x half> %r | |
| } | |
| ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: | |
| ; GFX1250: {{.*}} |