[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