[llvm] [AMDGPU][GlobalISel] Add BF16 widening to V2BF16 for packed instructions (PR #214370)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 9 03:03:58 PDT 2026
================
@@ -0,0 +1,261 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -global-isel=0 -mtriple=amdgpu12.5 -mattr=+real-true16 -o - %s | FileCheck --check-prefixes=GCN,SDAG,SDAG-TRUE16 %s
+; RUN: llc -global-isel=0 -mtriple=amdgpu12.5 -mattr=-real-true16 -o - %s | FileCheck --check-prefixes=GCN,SDAG,SDAG-FAKE16 %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu12.5 -mattr=+real-true16 -o - %s | FileCheck --check-prefixes=GCN,GISEL,GISEL-TRUE16 %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu12.5 -mattr=-real-true16 -o - %s | FileCheck --check-prefixes=GCN,GISEL,GISEL-FAKE16 %s
+
+; Test BF16 operations that have packed BF16 instruction variants.
+; Tests both scalar BF16 (widened to V2BF16) and native V2BF16 types.
+; Operations tested: FADD, FMUL, FMA, FCANONICALIZE
+; TODO: Add tests for FMAXNUM, FMINNUM, FNEG, FABS once GlobalISel support is added
+
+define bfloat @test_fadd_bf16(bfloat %a, bfloat %b) {
+; SDAG-LABEL: test_fadd_bf16:
+; SDAG: ; %bb.0:
+; SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; SDAG-NEXT: s_wait_kmcnt 0x0
+; SDAG-NEXT: v_pk_add_bf16 v0, v0, v1
+; SDAG-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-TRUE16-LABEL: test_fadd_bf16:
+; GISEL-TRUE16: ; %bb.0:
+; GISEL-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-TRUE16-NEXT: v_pk_add_bf16 v0, v0, v1
+; GISEL-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-FAKE16-LABEL: test_fadd_bf16:
+; GISEL-FAKE16: ; %bb.0:
+; GISEL-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v0, 0xffff, v0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v1, 0xffff, v1
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v0, s0, 16, v0
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v1, s0, 16, v1
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GISEL-FAKE16-NEXT: v_pk_add_bf16 v0, v0, v1
+; GISEL-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %result = fadd bfloat %a, %b
+ ret bfloat %result
+}
+
+define <2 x bfloat> @test_fadd_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) {
+; GCN-LABEL: test_fadd_v2bf16:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_wait_loadcnt_dscnt 0x0
+; GCN-NEXT: s_wait_kmcnt 0x0
+; GCN-NEXT: v_pk_add_bf16 v0, v0, v1
+; GCN-NEXT: s_set_pc_i64 s[30:31]
+ %result = fadd <2 x bfloat> %a, %b
+ ret <2 x bfloat> %result
+}
+
+define bfloat @test_fmul_bf16(bfloat %a, bfloat %b) {
+; SDAG-LABEL: test_fmul_bf16:
+; SDAG: ; %bb.0:
+; SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; SDAG-NEXT: s_wait_kmcnt 0x0
+; SDAG-NEXT: v_pk_mul_bf16 v0, v0, v1
+; SDAG-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-TRUE16-LABEL: test_fmul_bf16:
+; GISEL-TRUE16: ; %bb.0:
+; GISEL-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-TRUE16-NEXT: v_pk_mul_bf16 v0, v0, v1
+; GISEL-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-FAKE16-LABEL: test_fmul_bf16:
+; GISEL-FAKE16: ; %bb.0:
+; GISEL-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v0, 0xffff, v0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v1, 0xffff, v1
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v0, s0, 16, v0
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v1, s0, 16, v1
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GISEL-FAKE16-NEXT: v_pk_mul_bf16 v0, v0, v1
+; GISEL-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %result = fmul bfloat %a, %b
+ ret bfloat %result
+}
+
+define <2 x bfloat> @test_fmul_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b) {
+; GCN-LABEL: test_fmul_v2bf16:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_wait_loadcnt_dscnt 0x0
+; GCN-NEXT: s_wait_kmcnt 0x0
+; GCN-NEXT: v_pk_mul_bf16 v0, v0, v1
+; GCN-NEXT: s_set_pc_i64 s[30:31]
+ %result = fmul <2 x bfloat> %a, %b
+ ret <2 x bfloat> %result
+}
+
+define bfloat @test_fma_bf16(bfloat %a, bfloat %b, bfloat %c) {
+; SDAG-LABEL: test_fma_bf16:
+; SDAG: ; %bb.0:
+; SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; SDAG-NEXT: s_wait_kmcnt 0x0
+; SDAG-NEXT: v_fma_mixlo_bf16 v0, v0, v1, v2 op_sel_hi:[1,1,1]
+; SDAG-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-TRUE16-LABEL: test_fma_bf16:
+; GISEL-TRUE16: ; %bb.0:
+; GISEL-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-TRUE16-NEXT: v_pk_fma_bf16 v0, v0, v1, v2
+; GISEL-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-FAKE16-LABEL: test_fma_bf16:
+; GISEL-FAKE16: ; %bb.0:
+; GISEL-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v0, 0xffff, v0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v1, 0xffff, v1
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v2, 0xffff, v2
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_3) | instskip(NEXT) | instid1(VALU_DEP_3)
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v0, s0, 16, v0
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v1, s0, 16, v1
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_3) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v2, s0, 16, v2
+; GISEL-FAKE16-NEXT: v_pk_fma_bf16 v0, v0, v1, v2
+; GISEL-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %result = call bfloat @llvm.fma.bf16(bfloat %a, bfloat %b, bfloat %c)
+ ret bfloat %result
+}
+
+define <2 x bfloat> @test_fma_v2bf16(<2 x bfloat> %a, <2 x bfloat> %b, <2 x bfloat> %c) {
+; GCN-LABEL: test_fma_v2bf16:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_wait_loadcnt_dscnt 0x0
+; GCN-NEXT: s_wait_kmcnt 0x0
+; GCN-NEXT: v_pk_fma_bf16 v0, v0, v1, v2
+; GCN-NEXT: s_set_pc_i64 s[30:31]
+ %result = call <2 x bfloat> @llvm.fma.v2bf16(<2 x bfloat> %a, <2 x bfloat> %b, <2 x bfloat> %c)
+ ret <2 x bfloat> %result
+}
+
+define bfloat @test_canonicalize_bf16(bfloat %a) {
+; SDAG-LABEL: test_canonicalize_bf16:
+; SDAG: ; %bb.0:
+; SDAG-NEXT: s_wait_loadcnt_dscnt 0x0
+; SDAG-NEXT: s_wait_kmcnt 0x0
+; SDAG-NEXT: v_pk_mul_bf16 v0, 1.0, v0 op_sel_hi:[0,1]
+; SDAG-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-TRUE16-LABEL: test_canonicalize_bf16:
+; GISEL-TRUE16: ; %bb.0:
+; GISEL-TRUE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-TRUE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-TRUE16-NEXT: v_pk_mul_bf16 v0, 1.0, v0 op_sel_hi:[0,1]
+; GISEL-TRUE16-NEXT: s_set_pc_i64 s[30:31]
+;
+; GISEL-FAKE16-LABEL: test_canonicalize_bf16:
+; GISEL-FAKE16: ; %bb.0:
+; GISEL-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
+; GISEL-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GISEL-FAKE16-NEXT: v_and_b32_e32 v0, 0xffff, v0
+; GISEL-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GISEL-FAKE16-NEXT: v_lshl_or_b32 v0, s0, 16, v0
+; GISEL-FAKE16-NEXT: v_pk_mul_bf16 v0, 1.0, v0 op_sel_hi:[0,1]
+; GISEL-FAKE16-NEXT: s_set_pc_i64 s[30:31]
+ %result = call bfloat @llvm.canonicalize.bf16(bfloat %a)
+ ret bfloat %result
+}
+
+define <2 x bfloat> @test_canonicalize_v2bf16(<2 x bfloat> %a) {
+; GCN-LABEL: test_canonicalize_v2bf16:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_wait_loadcnt_dscnt 0x0
+; GCN-NEXT: s_wait_kmcnt 0x0
+; GCN-NEXT: v_pk_mul_bf16 v0, 1.0, v0 op_sel_hi:[0,1]
+; GCN-NEXT: s_set_pc_i64 s[30:31]
+ %result = call <2 x bfloat> @llvm.canonicalize.v2bf16(<2 x bfloat> %a)
+ ret <2 x bfloat> %result
+}
+
+define bfloat @test_complex_bf16(bfloat %a, bfloat %b, bfloat %c) {
----------------
arsenm wrote:
The test name says packed but these are scalar tests? I'd hope this would be covered by adding bf16 cases to existing individual operation tests
https://github.com/llvm/llvm-project/pull/214370
More information about the llvm-commits
mailing list