[llvm] [RISCV] Add isel for bitcasting between bfloat and half types (PR #158828)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 16 01:32:49 PDT 2025


https://github.com/yingwang-bj created https://github.com/llvm/llvm-project/pull/158828

There is no RISCV isel for bitcast between f16 and bf16 which will trigger "cannot select" fatal error.

>From c3302f0344e8944f635cfa0dadc7a3a8ff5abcbc Mon Sep 17 00:00:00 2001
From: Ying Wang <wy446777 at alibaba-inc.com>
Date: Tue, 16 Sep 2025 16:12:44 +0800
Subject: [PATCH] [RISCV] Add isel for bitcasting between bfloat and half types

---
 .../lib/Target/RISCV/RISCVInstrInfoZfbfmin.td |  7 ++
 llvm/test/CodeGen/RISCV/bfloat-convert.ll     | 68 +++++++++++++++++++
 2 files changed, 75 insertions(+)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td
index 8f0768f91c370..2fcc2151ee014 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZfbfmin.td
@@ -70,3 +70,10 @@ def : Pat<(bf16 (fpround FPR64:$rs1)),
 def : Pat<(fpextend (bf16 FPR16:$rs1)),
           (FCVT_D_S (FCVT_S_BF16 FPR16:$rs1, FRM_DYN), FRM_RNE)>;
 }
+
+let Predicates = [HasStdExtZfh, HasStdExtZfbfmin] in {
+// bf16 -> f16
+def : Pat<(f16 (bitconvert (bf16 FPR16:$src))), (f16 FPR16:$src)>;
+// f16 -> bf16
+def : Pat<(bf16 (bitconvert (f16 FPR16:$src))), (bf16 FPR16:$src)>;
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/RISCV/bfloat-convert.ll b/llvm/test/CodeGen/RISCV/bfloat-convert.ll
index 6207a17734d62..cb0a9f0ff45bf 100644
--- a/llvm/test/CodeGen/RISCV/bfloat-convert.ll
+++ b/llvm/test/CodeGen/RISCV/bfloat-convert.ll
@@ -1833,3 +1833,71 @@ start:
   %0 = tail call i32 @llvm.fptosi.sat.i32.bf16(bfloat %a)
   ret i32 %0
 }
+
+define bfloat @fcvt_bf16_h(half %a) nounwind {
+; CHECK32ZFBFMIN-LABEL: fcvt_bf16_h:
+; CHECK32ZFBFMIN:       # %bb.0:
+; CHECK32ZFBFMIN-NEXT:    fmv.x.w a0, fa0
+; CHECK32ZFBFMIN-NEXT:    fmv.h.x fa0, a0
+; CHECK32ZFBFMIN-NEXT:    ret
+;
+; RV32ID-LABEL: fcvt_bf16_h:
+; RV32ID:       # %bb.0:
+; RV32ID-NEXT:    fmv.x.w a0, fa0
+; RV32ID-NEXT:    lui a1, 1048560
+; RV32ID-NEXT:    or a0, a0, a1
+; RV32ID-NEXT:    fmv.w.x fa0, a0
+; RV32ID-NEXT:    ret
+;
+; CHECK64ZFBFMIN-LABEL: fcvt_bf16_h:
+; CHECK64ZFBFMIN:       # %bb.0:
+; CHECK64ZFBFMIN-NEXT:    fmv.x.w a0, fa0
+; CHECK64ZFBFMIN-NEXT:    fmv.h.x fa0, a0
+; CHECK64ZFBFMIN-NEXT:    ret
+;
+; RV64ID-LABEL: fcvt_bf16_h:
+; RV64ID:       # %bb.0:
+; RV64ID-NEXT:    fmv.x.w a0, fa0
+; RV64ID-NEXT:    lui a1, 1048560
+; RV64ID-NEXT:    or a0, a0, a1
+; RV64ID-NEXT:    fmv.w.x fa0, a0
+; RV64ID-NEXT:    ret
+  %r = bitcast half %a to bfloat
+  ret bfloat %r
+}
+
+define half @test_h_bf16(bfloat %a) nounwind {
+; CHECK32ZFBFMIN-LABEL: test_h_bf16:
+; CHECK32ZFBFMIN:       # %bb.0:
+; CHECK32ZFBFMIN-NEXT:    fmv.x.h a0, fa0
+; CHECK32ZFBFMIN-NEXT:    lui a1, 1048560
+; CHECK32ZFBFMIN-NEXT:    or a0, a0, a1
+; CHECK32ZFBFMIN-NEXT:    fmv.w.x fa0, a0
+; CHECK32ZFBFMIN-NEXT:    ret
+;
+; RV32ID-LABEL: test_h_bf16:
+; RV32ID:       # %bb.0:
+; RV32ID-NEXT:    fmv.x.w a0, fa0
+; RV32ID-NEXT:    lui a1, 1048560
+; RV32ID-NEXT:    or a0, a0, a1
+; RV32ID-NEXT:    fmv.w.x fa0, a0
+; RV32ID-NEXT:    ret
+;
+; CHECK64ZFBFMIN-LABEL: test_h_bf16:
+; CHECK64ZFBFMIN:       # %bb.0:
+; CHECK64ZFBFMIN-NEXT:    fmv.x.h a0, fa0
+; CHECK64ZFBFMIN-NEXT:    lui a1, 1048560
+; CHECK64ZFBFMIN-NEXT:    or a0, a0, a1
+; CHECK64ZFBFMIN-NEXT:    fmv.w.x fa0, a0
+; CHECK64ZFBFMIN-NEXT:    ret
+;
+; RV64ID-LABEL: test_h_bf16:
+; RV64ID:       # %bb.0:
+; RV64ID-NEXT:    fmv.x.w a0, fa0
+; RV64ID-NEXT:    lui a1, 1048560
+; RV64ID-NEXT:    or a0, a0, a1
+; RV64ID-NEXT:    fmv.w.x fa0, a0
+; RV64ID-NEXT:    ret
+  %r = bitcast bfloat %a to half
+  ret half %r
+}



More information about the llvm-commits mailing list