[llvm] [RISCV] Support Inline ASM for the bf16 type. (PR #80118)
Chuan-Yue Yuan via llvm-commits
llvm-commits at lists.llvm.org
Mon May 27 23:03:18 PDT 2024
https://github.com/circYuan updated https://github.com/llvm/llvm-project/pull/80118
>From daa224ad73986ca8788fbe4c988132ce07e9be24 Mon Sep 17 00:00:00 2001
From: Tony Chuan-Yue Yuan <yuan593 at andestech.com>
Date: Tue, 28 May 2024 13:56:15 +0800
Subject: [PATCH] [RISCV] Support Inline ASM for the bf16 type.
This patch makes the RISCV-V asm constraint `f` recognize the bfloat
type.
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 16 +++-
.../RISCV/inline-asm-f-constraint-bf16.ll | 77 +++++++++++++++++++
2 files changed, 92 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/RISCV/inline-asm-f-constraint-bf16.ll
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f0e5a7d393b6c..f5708f62661e7 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20155,7 +20155,8 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, &RISCV::GPRPairRegClass);
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
case 'f':
- if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16)
+ if ((Subtarget.hasStdExtZfhmin() && VT == MVT::f16) ||
+ (Subtarget.hasStdExtZfbfmin() && VT == MVT::bf16))
return std::make_pair(0U, &RISCV::FPR16RegClass);
if (Subtarget.hasStdExtF() && VT == MVT::f32)
return std::make_pair(0U, &RISCV::FPR32RegClass);
@@ -20273,6 +20274,11 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
unsigned HReg = RISCV::F0_H + RegNo;
return std::make_pair(HReg, &RISCV::FPR16RegClass);
}
+ if (Subtarget.hasStdExtZfbfmin() && VT == MVT::bf16){
+ unsigned RegNo = FReg - RISCV::F0_F;
+ unsigned HReg = RISCV::F0_H + RegNo;
+ return std::make_pair(HReg, &RISCV::FPR16RegClass);
+ }
}
}
@@ -20949,6 +20955,14 @@ bool RISCVTargetLowering::splitValueIntoRegisterParts(
return true;
}
+ // Since the inline asm only use the first type in the RegisterClass, the bf16
+ // inline asm would choose the f16 from FPR16RegClass for doing the copy, and
+ // we correct the behavior here to avoid generating wrong SelectionDAG.
+ if (ValueVT == MVT::bf16 && PartVT == MVT::f16){
+ Parts[0] = Val;
+ return true;
+ }
+
if (ValueVT.isScalableVector() && PartVT.isScalableVector()) {
LLVMContext &Context = *DAG.getContext();
EVT ValueEltVT = ValueVT.getVectorElementType();
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-bf16.ll b/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-bf16.ll
new file mode 100644
index 0000000000000..0fec5088192b5
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-bf16.ll
@@ -0,0 +1,77 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+f,+experimental-zfbfmin -target-abi=ilp32 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV32F %s
+; RUN: llc -mtriple=riscv64 -mattr=+f,+experimental-zfbfmin -target-abi=lp64 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV64F %s
+; RUN: llc -mtriple=riscv32 -mattr=+d,+experimental-zfbfmin -target-abi=ilp32 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV32F %s
+; RUN: llc -mtriple=riscv64 -mattr=+d,+experimental-zfbfmin -target-abi=lp64 -verify-machineinstrs < %s \
+; RUN: | FileCheck -check-prefix=RV64F %s
+
+ at gf = external global float
+
+define float @constraint_f_float(bfloat %a) nounwind {
+; RV32F-LABEL: constraint_f_float:
+; RV32F: # %bb.0:
+; RV32F-NEXT: fmv.h.x fa5, a0
+; RV32F-NEXT: #APP
+; RV32F-NEXT: fcvt.s.bf16 fa5, fa5
+; RV32F-NEXT: #NO_APP
+; RV32F-NEXT: fmv.x.w a0, fa5
+; RV32F-NEXT: ret
+;
+; RV64F-LABEL: constraint_f_float:
+; RV64F: # %bb.0:
+; RV64F-NEXT: fmv.h.x fa5, a0
+; RV64F-NEXT: #APP
+; RV64F-NEXT: fcvt.s.bf16 fa5, fa5
+; RV64F-NEXT: #NO_APP
+; RV64F-NEXT: fmv.x.w a0, fa5
+; RV64F-NEXT: ret
+ %1 = load float, float* @gf
+ %2 = tail call float asm "fcvt.s.bf16 $0, $1", "=f,f"(bfloat %a)
+ ret float %2
+}
+
+define float @constraint_f_float_abi_name(bfloat %a) nounwind {
+; RV32F-LABEL: constraint_f_float_abi_name:
+; RV32F: # %bb.0:
+; RV32F-NEXT: fmv.h.x fa0, a0
+; RV32F-NEXT: #APP
+; RV32F-NEXT: fcvt.s.bf16 ft0, fa0
+; RV32F-NEXT: #NO_APP
+; RV32F-NEXT: fmv.x.w a0, ft0
+; RV32F-NEXT: ret
+;
+; RV64F-LABEL: constraint_f_float_abi_name:
+; RV64F: # %bb.0:
+; RV64F-NEXT: fmv.h.x fa0, a0
+; RV64F-NEXT: #APP
+; RV64F-NEXT: fcvt.s.bf16 ft0, fa0
+; RV64F-NEXT: #NO_APP
+; RV64F-NEXT: fmv.x.w a0, ft0
+; RV64F-NEXT: ret
+ %1 = load float, float* @gf
+ %2 = tail call float asm "fcvt.s.bf16 $0, $1", "={ft0},{fa0}"(bfloat %a)
+ ret float %2
+}
+
+define bfloat @constraint_gpr(bfloat %x) {
+; RV32F-LABEL: constraint_gpr:
+; RV32F: # %bb.0:
+; RV32F-NEXT: .cfi_def_cfa_offset 0
+; RV32F-NEXT: #APP
+; RV32F-NEXT: mv a0, a0
+; RV32F-NEXT: #NO_APP
+; RV32F-NEXT: ret
+;
+; RV64F-LABEL: constraint_gpr:
+; RV64F: # %bb.0:
+; RV64F-NEXT: .cfi_def_cfa_offset 0
+; RV64F-NEXT: #APP
+; RV64F-NEXT: mv a0, a0
+; RV64F-NEXT: #NO_APP
+; RV64F-NEXT: ret
+ %1 = tail call bfloat asm sideeffect alignstack "mv $0, $1", "={x10},{x10}"(bfloat %x)
+ ret bfloat %1
+}
More information about the llvm-commits
mailing list