Skip to content

[RISCV] Implement Builtins for XAndesBFHCvt extension. #148804

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 16, 2025

Conversation

tclin914
Copy link
Contributor

XAndesBFHCvt provides two builtins functions for converting between float and bf16. Users can use them to convert bf16 values loaded from memory to float, perform arithmetic operations, then convert them back to bf16 and store them to memory.

The load/store and move operations for bf16 will be handled in a later patch.

XAndesBFHCvt provides two builtins functions for converting between
float and bf16. Users can use them to convert bf16 values loaded from
memory to float, perform arithmetic operations, then convert them back
to bf16 and store them to memory.

The load/store and move operations for bf16 will be handled in a later patch.
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang:codegen IR generation bugs: mangling, exceptions, etc. llvm:ir labels Jul 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 15, 2025

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-clang-codegen

Author: Jim Lin (tclin914)

Changes

XAndesBFHCvt provides two builtins functions for converting between float and bf16. Users can use them to convert bf16 values loaded from memory to float, perform arithmetic operations, then convert them back to bf16 and store them to memory.

The load/store and move operations for bf16 will be handled in a later patch.


Full diff: https://github.com/llvm/llvm-project/pull/148804.diff

11 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCV.td (+5)
  • (added) clang/include/clang/Basic/BuiltinsRISCVXAndes.td (+27)
  • (modified) clang/lib/CodeGen/TargetBuiltins/RISCV.cpp (+8)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_nds.h (+35)
  • (added) clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c (+25)
  • (added) clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c (+23)
  • (modified) llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td (+9)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td (+7)
  • (added) llvm/test/CodeGen/RISCV/xandesbfhcvt.ll (+27)
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td
index b2cd5648e008f..5927eaf80d57a 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -157,3 +157,8 @@ def pause : RISCVBuiltin<"void()">;
 // XCV extensions.
 //===----------------------------------------------------------------------===//
 include "clang/Basic/BuiltinsRISCVXCV.td"
+
+//===----------------------------------------------------------------------===//
+// XAndes extensions.
+//===----------------------------------------------------------------------===//
+include "clang/Basic/BuiltinsRISCVXAndes.td"
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXAndes.td b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td
new file mode 100644
index 0000000000000..ea9a7166bc6e8
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td
@@ -0,0 +1,27 @@
+//==- BuiltinsRISCVXAndes.td - RISC-V Andes Builtin database -----*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Andes-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+class RISCVXAndesBuiltin<string prototype, string features = ""> : TargetBuiltin {
+  let Spellings = ["__builtin_riscv_nds_" # NAME];
+  let Prototype = prototype;
+  let Features = features;
+}
+
+let Attributes = [NoThrow, Const] in {
+//===----------------------------------------------------------------------===//
+// XAndesBFHCvt extension.
+//===----------------------------------------------------------------------===//
+
+def fcvt_s_bf16 : RISCVXAndesBuiltin<"float(__bf16)", "xandesbfhcvt">;
+def fcvt_bf16_s : RISCVXAndesBuiltin<"__bf16(float)", "xandesbfhcvt">;
+} // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 89e3f6f203df3..63092139af4fa 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -413,6 +413,14 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
 
+  // XAndesBFHCvt
+  case RISCV::BI__builtin_riscv_nds_fcvt_s_bf16:
+    ID = Intrinsic::riscv_nds_fcvt_s_bf16;
+    break;
+  case RISCV::BI__builtin_riscv_nds_fcvt_bf16_s:
+    ID = Intrinsic::riscv_nds_fcvt_bf16_s;
+    break;
+
     // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
 
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index c96d209c1fc0c..76ac8409e568f 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -127,6 +127,7 @@ set(riscv_files
   riscv_bitmanip.h
   riscv_corev_alu.h
   riscv_crypto.h
+  riscv_nds.h
   riscv_ntlh.h
   sifive_vector.h
   andes_vector.h
diff --git a/clang/lib/Headers/riscv_nds.h b/clang/lib/Headers/riscv_nds.h
new file mode 100644
index 0000000000000..5ccef00e332ed
--- /dev/null
+++ b/clang/lib/Headers/riscv_nds.h
@@ -0,0 +1,35 @@
+/*===---- riscv_nds.h - Andes intrinsics -----------------------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_NDS_H
+#define __RISCV_NDS_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xandesbfhcvt)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ float __DEFAULT_FN_ATTRS __riscv_nds_fcvt_s_bf16(__bf16 bf) {
+  return __builtin_riscv_nds_fcvt_s_bf16(bf);
+}
+
+static __inline__ __bf16 __DEFAULT_FN_ATTRS __riscv_nds_fcvt_bf16_s(float sf) {
+  return __builtin_riscv_nds_fcvt_bf16_s(sf);
+}
+
+#endif // defined(__riscv_xandesbfhcvt)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_NDS_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c
new file mode 100644
index 0000000000000..49935217080e5
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c
@@ -0,0 +1,25 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+
+#include <riscv_nds.h>
+
+// CHECK-LABEL: @test_fcvt_s_bf16(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call float @llvm.riscv.nds.fcvt.s.bf16(bfloat [[BF:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float test_fcvt_s_bf16(__bf16 bf) {
+  return __riscv_nds_fcvt_s_bf16(bf);
+}
+
+// CHECK-LABEL: @test_fcvt_bf16_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call bfloat @llvm.riscv.nds.fcvt.bf16.s(float [[SF:%.*]])
+// CHECK-NEXT:    ret bfloat [[TMP0]]
+//
+__bf16 test_fcvt_bf16_s(float sf) {
+  return __riscv_nds_fcvt_bf16_s(sf);
+}
diff --git a/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c
new file mode 100644
index 0000000000000..ecb809f43b56a
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c
@@ -0,0 +1,23 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+
+// CHECK-LABEL: @test_fcvt_s_bf16(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call float @llvm.riscv.nds.fcvt.s.bf16(bfloat [[BF:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float test_fcvt_s_bf16(__bf16 bf) {
+  return __builtin_riscv_nds_fcvt_s_bf16(bf);
+}
+
+// CHECK-LABEL: @test_fcvt_bf16_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call bfloat @llvm.riscv.nds.fcvt.bf16.s(float [[SF:%.*]])
+// CHECK-NEXT:    ret bfloat [[TMP0]]
+//
+__bf16 test_fcvt_bf16_s(float sf) {
+  return __builtin_riscv_nds_fcvt_bf16_s(sf);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td
index 43f7f7e22fe94..9bb7855a709f3 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td
@@ -11,6 +11,15 @@
 //===----------------------------------------------------------------------===//
 
 let TargetPrefix = "riscv" in {
+  // Andes Scalar BFloat16 Conversion Extension
+  def int_riscv_nds_fcvt_s_bf16
+      : DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_bfloat_ty],
+                              [IntrNoMem, IntrSpeculatable]>;
+
+  def int_riscv_nds_fcvt_bf16_s
+      : DefaultAttrsIntrinsic<[llvm_bfloat_ty], [llvm_float_ty],
+                              [IntrNoMem, IntrSpeculatable]>;
+
   // Andes Vector BFloat16 Conversion Extension
   def int_riscv_nds_vfwcvt_s_bf16 : RISCVConversionUnMasked;
   def int_riscv_nds_vfncvt_bf16_s : RISCVConversionUnMaskedRoundingMode;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 359e529df46f3..45fcb27e2f88e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -129,7 +129,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
 
   if (Subtarget.hasStdExtZfhmin())
     addRegisterClass(MVT::f16, &RISCV::FPR16RegClass);
-  if (Subtarget.hasStdExtZfbfmin())
+  if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
     addRegisterClass(MVT::bf16, &RISCV::FPR16RegClass);
   if (Subtarget.hasStdExtF())
     addRegisterClass(MVT::f32, &RISCV::FPR32RegClass);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 38992b6c05d08..06b35163e9cf4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -767,6 +767,13 @@ def : Sh2AddPat<NDS_LEA_W_ZE>;
 def : Sh3AddPat<NDS_LEA_D_ZE>;
 } // Predicates = [HasVendorXAndesPerf, IsRV64]
 
+let Predicates = [HasVendorXAndesBFHCvt] in {
+def : Pat<(int_riscv_nds_fcvt_s_bf16 (bf16 FPR16:$rs)),
+          (NDS_FCVT_S_BF16 (bf16 FPR16:$rs))>;
+def : Pat<(bf16 (int_riscv_nds_fcvt_bf16_s FPR32:$rs)),
+          (NDS_FCVT_BF16_S FPR32:$rs)>;
+} // Predicates = [HasVendorXAndesBFHCvt]
+
 let Predicates = [HasVendorXAndesVBFHCvt] in {
 defm PseudoNDS_VFWCVT_S_BF16 : VPseudoVWCVT_S_BF16;
 defm PseudoNDS_VFNCVT_BF16_S : VPseudoVNCVT_BF16_S;
diff --git a/llvm/test/CodeGen/RISCV/xandesbfhcvt.ll b/llvm/test/CodeGen/RISCV/xandesbfhcvt.ll
new file mode 100644
index 0000000000000..5b8c6c11a0750
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xandesbfhcvt.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+xandesbfhcvt -target-abi ilp32f \
+; RUN:   -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+xandesbfhcvt -target-abi lp64f \
+; RUN:   -verify-machineinstrs < %s | FileCheck %s
+
+declare bfloat @llvm.riscv.nds.fcvt.bf16.s(float)
+
+define float @fcvt_s_bf16(bfloat %a) nounwind {
+; CHECK-LABEL: fcvt_s_bf16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.fcvt.s.bf16 fa0, fa0
+; CHECK-NEXT:    ret
+  %1 = call float @llvm.riscv.nds.fcvt.s.bf16(bfloat %a)
+  ret float %1
+}
+
+declare float @llvm.riscv.nds.fcvt.s.bf16(bfloat)
+
+define bfloat @fcvt_bf16_s(float %a) nounwind {
+; CHECK-LABEL: fcvt_bf16_s:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.fcvt.bf16.s fa0, fa0
+; CHECK-NEXT:    ret
+  %1 = call bfloat @llvm.riscv.nds.fcvt.bf16.s(float %a)
+  ret bfloat %1
+}

@llvmbot
Copy link
Member

llvmbot commented Jul 15, 2025

@llvm/pr-subscribers-backend-x86

Author: Jim Lin (tclin914)

Changes

XAndesBFHCvt provides two builtins functions for converting between float and bf16. Users can use them to convert bf16 values loaded from memory to float, perform arithmetic operations, then convert them back to bf16 and store them to memory.

The load/store and move operations for bf16 will be handled in a later patch.


Full diff: https://github.com/llvm/llvm-project/pull/148804.diff

11 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCV.td (+5)
  • (added) clang/include/clang/Basic/BuiltinsRISCVXAndes.td (+27)
  • (modified) clang/lib/CodeGen/TargetBuiltins/RISCV.cpp (+8)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_nds.h (+35)
  • (added) clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c (+25)
  • (added) clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c (+23)
  • (modified) llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td (+9)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+1-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td (+7)
  • (added) llvm/test/CodeGen/RISCV/xandesbfhcvt.ll (+27)
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td
index b2cd5648e008f..5927eaf80d57a 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCV.td
@@ -157,3 +157,8 @@ def pause : RISCVBuiltin<"void()">;
 // XCV extensions.
 //===----------------------------------------------------------------------===//
 include "clang/Basic/BuiltinsRISCVXCV.td"
+
+//===----------------------------------------------------------------------===//
+// XAndes extensions.
+//===----------------------------------------------------------------------===//
+include "clang/Basic/BuiltinsRISCVXAndes.td"
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXAndes.td b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td
new file mode 100644
index 0000000000000..ea9a7166bc6e8
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td
@@ -0,0 +1,27 @@
+//==- BuiltinsRISCVXAndes.td - RISC-V Andes Builtin database -----*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the Andes-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+class RISCVXAndesBuiltin<string prototype, string features = ""> : TargetBuiltin {
+  let Spellings = ["__builtin_riscv_nds_" # NAME];
+  let Prototype = prototype;
+  let Features = features;
+}
+
+let Attributes = [NoThrow, Const] in {
+//===----------------------------------------------------------------------===//
+// XAndesBFHCvt extension.
+//===----------------------------------------------------------------------===//
+
+def fcvt_s_bf16 : RISCVXAndesBuiltin<"float(__bf16)", "xandesbfhcvt">;
+def fcvt_bf16_s : RISCVXAndesBuiltin<"__bf16(float)", "xandesbfhcvt">;
+} // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
index 89e3f6f203df3..63092139af4fa 100644
--- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp
@@ -413,6 +413,14 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
 
+  // XAndesBFHCvt
+  case RISCV::BI__builtin_riscv_nds_fcvt_s_bf16:
+    ID = Intrinsic::riscv_nds_fcvt_s_bf16;
+    break;
+  case RISCV::BI__builtin_riscv_nds_fcvt_bf16_s:
+    ID = Intrinsic::riscv_nds_fcvt_bf16_s;
+    break;
+
     // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
 
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index c96d209c1fc0c..76ac8409e568f 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -127,6 +127,7 @@ set(riscv_files
   riscv_bitmanip.h
   riscv_corev_alu.h
   riscv_crypto.h
+  riscv_nds.h
   riscv_ntlh.h
   sifive_vector.h
   andes_vector.h
diff --git a/clang/lib/Headers/riscv_nds.h b/clang/lib/Headers/riscv_nds.h
new file mode 100644
index 0000000000000..5ccef00e332ed
--- /dev/null
+++ b/clang/lib/Headers/riscv_nds.h
@@ -0,0 +1,35 @@
+/*===---- riscv_nds.h - Andes intrinsics -----------------------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_NDS_H
+#define __RISCV_NDS_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xandesbfhcvt)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ float __DEFAULT_FN_ATTRS __riscv_nds_fcvt_s_bf16(__bf16 bf) {
+  return __builtin_riscv_nds_fcvt_s_bf16(bf);
+}
+
+static __inline__ __bf16 __DEFAULT_FN_ATTRS __riscv_nds_fcvt_bf16_s(float sf) {
+  return __builtin_riscv_nds_fcvt_bf16_s(sf);
+}
+
+#endif // defined(__riscv_xandesbfhcvt)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_NDS_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c
new file mode 100644
index 0000000000000..49935217080e5
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt-c-api.c
@@ -0,0 +1,25 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+
+#include <riscv_nds.h>
+
+// CHECK-LABEL: @test_fcvt_s_bf16(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call float @llvm.riscv.nds.fcvt.s.bf16(bfloat [[BF:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float test_fcvt_s_bf16(__bf16 bf) {
+  return __riscv_nds_fcvt_s_bf16(bf);
+}
+
+// CHECK-LABEL: @test_fcvt_bf16_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call bfloat @llvm.riscv.nds.fcvt.bf16.s(float [[SF:%.*]])
+// CHECK-NEXT:    ret bfloat [[TMP0]]
+//
+__bf16 test_fcvt_bf16_s(float sf) {
+  return __riscv_nds_fcvt_bf16_s(sf);
+}
diff --git a/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c
new file mode 100644
index 0000000000000..ecb809f43b56a
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xandesbfhcvt.c
@@ -0,0 +1,23 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesbfhcvt -emit-llvm %s -o - \
+// RUN:   -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s
+
+// CHECK-LABEL: @test_fcvt_s_bf16(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call float @llvm.riscv.nds.fcvt.s.bf16(bfloat [[BF:%.*]])
+// CHECK-NEXT:    ret float [[TMP0]]
+//
+float test_fcvt_s_bf16(__bf16 bf) {
+  return __builtin_riscv_nds_fcvt_s_bf16(bf);
+}
+
+// CHECK-LABEL: @test_fcvt_bf16_s(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = call bfloat @llvm.riscv.nds.fcvt.bf16.s(float [[SF:%.*]])
+// CHECK-NEXT:    ret bfloat [[TMP0]]
+//
+__bf16 test_fcvt_bf16_s(float sf) {
+  return __builtin_riscv_nds_fcvt_bf16_s(sf);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td
index 43f7f7e22fe94..9bb7855a709f3 100644
--- a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td
+++ b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td
@@ -11,6 +11,15 @@
 //===----------------------------------------------------------------------===//
 
 let TargetPrefix = "riscv" in {
+  // Andes Scalar BFloat16 Conversion Extension
+  def int_riscv_nds_fcvt_s_bf16
+      : DefaultAttrsIntrinsic<[llvm_float_ty], [llvm_bfloat_ty],
+                              [IntrNoMem, IntrSpeculatable]>;
+
+  def int_riscv_nds_fcvt_bf16_s
+      : DefaultAttrsIntrinsic<[llvm_bfloat_ty], [llvm_float_ty],
+                              [IntrNoMem, IntrSpeculatable]>;
+
   // Andes Vector BFloat16 Conversion Extension
   def int_riscv_nds_vfwcvt_s_bf16 : RISCVConversionUnMasked;
   def int_riscv_nds_vfncvt_bf16_s : RISCVConversionUnMaskedRoundingMode;
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 359e529df46f3..45fcb27e2f88e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -129,7 +129,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
 
   if (Subtarget.hasStdExtZfhmin())
     addRegisterClass(MVT::f16, &RISCV::FPR16RegClass);
-  if (Subtarget.hasStdExtZfbfmin())
+  if (Subtarget.hasStdExtZfbfmin() || Subtarget.hasVendorXAndesBFHCvt())
     addRegisterClass(MVT::bf16, &RISCV::FPR16RegClass);
   if (Subtarget.hasStdExtF())
     addRegisterClass(MVT::f32, &RISCV::FPR32RegClass);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 38992b6c05d08..06b35163e9cf4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -767,6 +767,13 @@ def : Sh2AddPat<NDS_LEA_W_ZE>;
 def : Sh3AddPat<NDS_LEA_D_ZE>;
 } // Predicates = [HasVendorXAndesPerf, IsRV64]
 
+let Predicates = [HasVendorXAndesBFHCvt] in {
+def : Pat<(int_riscv_nds_fcvt_s_bf16 (bf16 FPR16:$rs)),
+          (NDS_FCVT_S_BF16 (bf16 FPR16:$rs))>;
+def : Pat<(bf16 (int_riscv_nds_fcvt_bf16_s FPR32:$rs)),
+          (NDS_FCVT_BF16_S FPR32:$rs)>;
+} // Predicates = [HasVendorXAndesBFHCvt]
+
 let Predicates = [HasVendorXAndesVBFHCvt] in {
 defm PseudoNDS_VFWCVT_S_BF16 : VPseudoVWCVT_S_BF16;
 defm PseudoNDS_VFNCVT_BF16_S : VPseudoVNCVT_BF16_S;
diff --git a/llvm/test/CodeGen/RISCV/xandesbfhcvt.ll b/llvm/test/CodeGen/RISCV/xandesbfhcvt.ll
new file mode 100644
index 0000000000000..5b8c6c11a0750
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xandesbfhcvt.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+xandesbfhcvt -target-abi ilp32f \
+; RUN:   -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+xandesbfhcvt -target-abi lp64f \
+; RUN:   -verify-machineinstrs < %s | FileCheck %s
+
+declare bfloat @llvm.riscv.nds.fcvt.bf16.s(float)
+
+define float @fcvt_s_bf16(bfloat %a) nounwind {
+; CHECK-LABEL: fcvt_s_bf16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.fcvt.s.bf16 fa0, fa0
+; CHECK-NEXT:    ret
+  %1 = call float @llvm.riscv.nds.fcvt.s.bf16(bfloat %a)
+  ret float %1
+}
+
+declare float @llvm.riscv.nds.fcvt.s.bf16(bfloat)
+
+define bfloat @fcvt_bf16_s(float %a) nounwind {
+; CHECK-LABEL: fcvt_bf16_s:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    nds.fcvt.bf16.s fa0, fa0
+; CHECK-NEXT:    ret
+  %1 = call bfloat @llvm.riscv.nds.fcvt.bf16.s(float %a)
+  ret bfloat %1
+}

@topperc
Copy link
Collaborator

topperc commented Jul 15, 2025

Can't we use the fptrunc and fpext IR instructions for this?

@tclin914
Copy link
Contributor Author

Can't we use the fptrunc and fpext IR instructions for this?

Done. Thanks.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tclin914 tclin914 merged commit 3e4153c into llvm:main Jul 16, 2025
9 checks passed
@tclin914 tclin914 deleted the andes-bfhcvt-intrinsics branch July 16, 2025 08:13
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 16, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building clang,llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/23601

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM :: ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll' FAILED ********************
Exit Code: 2

Command Output (stderr):
--
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli -jit-kind=orc-lazy -compile-threads=2 -thread-entry hello /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll # RUN: at line 1
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli -jit-kind=orc-lazy -compile-threads=2 -thread-entry hello /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
 #0 0x00000001013a3bec llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100effbec)
 #1 0x00000001013a199c llvm::sys::RunSignalHandlers() (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100efd99c)
 #2 0x00000001013a46ec SignalHandler(int, __siginfo*, void*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100f006ec)
 #3 0x000000019d937584 (/usr/lib/system/libsystem_platform.dylib+0x18047b584)
 #4 0x000000019d90621c (/usr/lib/system/libsystem_pthread.dylib+0x18044a21c)
 #5 0x000000019d82cad0 (/usr/lib/libc++.1.dylib+0x180370ad0)
 #6 0x0000000100f31388 void llvm::detail::UniqueFunctionBase<void, llvm::Expected<llvm::DenseMap<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr, void>, llvm::detail::DenseMapPair<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef>>>>::CallImpl<llvm::orc::Platform::lookupInitSymbols(llvm::orc::ExecutionSession&, llvm::DenseMap<llvm::orc::JITDylib*, llvm::orc::SymbolLookupSet, llvm::DenseMapInfo<llvm::orc::JITDylib*, void>, llvm::detail::DenseMapPair<llvm::orc::JITDylib*, llvm::orc::SymbolLookupSet>> const&)::$_45>(void*, llvm::Expected<llvm::DenseMap<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef, llvm::DenseMapInfo<llvm::orc::SymbolStringPtr, void>, llvm::detail::DenseMapPair<llvm::orc::SymbolStringPtr, llvm::orc::ExecutorSymbolDef>>>&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100a8d388)
 #7 0x0000000100f2cfbc llvm::orc::AsynchronousSymbolQuery::handleComplete(llvm::orc::ExecutionSession&)::RunQueryCompleteTask::run() (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100a88fbc)
 #8 0x0000000100ff4d7c void* std::__1::__thread_proxy[abi:un170006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, llvm::orc::DynamicThreadPoolTaskDispatcher::dispatch(std::__1::unique_ptr<llvm::orc::Task, std::__1::default_delete<llvm::orc::Task>>)::$_0>>(void*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/lli+0x100b50d7c)
 #9 0x000000019d906f94 (/usr/lib/system/libsystem_pthread.dylib+0x18044af94)
#10 0x000000019d901d34 (/usr/lib/system/libsystem_pthread.dylib+0x180445d34)
FileCheck error: '<stdin>' is empty.
FileCheck command line:  /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/ExecutionEngine/OrcLazy/multiple-compile-threads-basic.ll

--

********************


@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 16, 2025

LLVM Buildbot has detected a new failure on builder publish-sphinx-docs running on as-worker-4 while building clang,llvm at step 6 "Publish docs-llvm-html".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/45/builds/14393

Here is the relevant piece of the build log for the reference
Step 6 (Publish docs-llvm-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]
Step 7 (Publish docs-clang-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]
Step 8 (Publish docs-clang-tools-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]
Step 9 (Publish docs-lld-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]
Step 10 (Publish docs-lldb-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]
Step 12 (Publish docs-openmp-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]
Step 13 (Publish docs-polly-html) failure: 'rsync -vrl ...' (failure)
kex_exchange_identification: Connection closed by remote host
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(235) [sender=3.1.3]

@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 16, 2025

LLVM Buildbot has detected a new failure on builder premerge-monolithic-linux running on premerge-linux-1 while building clang,llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/153/builds/38299

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
...
PASS: lld :: COFF/entry-inference-mingw.s (98656 of 101604)
PASS: lld :: COFF/guardcf-align.s (98657 of 101604)
PASS: lld :: COFF/giats.s (98658 of 101604)
PASS: lld :: COFF/exportas.test (98659 of 101604)
PASS: lld :: COFF/deploadflag-cfg-x64.s (98660 of 101604)
PASS: lld :: COFF/duplicate-imp-func.s (98661 of 101604)
PASS: lld :: COFF/entry-mangled.test (98662 of 101604)
PASS: lld :: COFF/filealign.test (98663 of 101604)
PASS: lld :: COFF/gfids-fallback.s (98664 of 101604)
TIMEOUT: MLIR :: Examples/standalone/test.toy (98665 of 101604)
******************** TEST 'MLIR :: Examples/standalone/test.toy' FAILED ********************
Exit Code: 1
Timeout: Reached timeout of 60 seconds

Command Output (stdout):
--
# RUN: at line 1
"/etc/cmake/bin/cmake" "/build/buildbot/premerge-monolithic-linux/llvm-project/mlir/examples/standalone" -G "Ninja"  -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_C_COMPILER=/usr/bin/clang  -DLLVM_ENABLE_LIBCXX=OFF -DMLIR_DIR=/build/buildbot/premerge-monolithic-linux/build/lib/cmake/mlir  -DLLVM_USE_LINKER=lld  -DPython3_EXECUTABLE="/usr/bin/python3.10"
# executed command: /etc/cmake/bin/cmake /build/buildbot/premerge-monolithic-linux/llvm-project/mlir/examples/standalone -G Ninja -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DCMAKE_C_COMPILER=/usr/bin/clang -DLLVM_ENABLE_LIBCXX=OFF -DMLIR_DIR=/build/buildbot/premerge-monolithic-linux/build/lib/cmake/mlir -DLLVM_USE_LINKER=lld -DPython3_EXECUTABLE=/usr/bin/python3.10
# .---command stdout------------
# | -- The CXX compiler identification is Clang 16.0.6
# | -- The C compiler identification is Clang 16.0.6
# | -- Detecting CXX compiler ABI info
# | -- Detecting CXX compiler ABI info - done
# | -- Check for working CXX compiler: /usr/bin/clang++ - skipped
# | -- Detecting CXX compile features
# | -- Detecting CXX compile features - done
# | -- Detecting C compiler ABI info
# | -- Detecting C compiler ABI info - done
# | -- Check for working C compiler: /usr/bin/clang - skipped
# | -- Detecting C compile features
# | -- Detecting C compile features - done
# | -- Looking for histedit.h
# | -- Looking for histedit.h - found
# | -- Found LibEdit: /usr/include (found version "2.11") 
# | -- Found ZLIB: /usr/lib/x86_64-linux-gnu/libz.so (found version "1.2.11") 
# | -- Found LibXml2: /usr/lib/x86_64-linux-gnu/libxml2.so (found version "2.9.13") 
# | -- Using MLIRConfig.cmake in: /build/buildbot/premerge-monolithic-linux/build/lib/cmake/mlir
# | -- Using LLVMConfig.cmake in: /build/buildbot/premerge-monolithic-linux/build/lib/cmake/llvm
# | -- Linker detection: unknown
# | -- Performing Test LLVM_LIBSTDCXX_MIN
# | -- Performing Test LLVM_LIBSTDCXX_MIN - Success
# | -- Performing Test LLVM_LIBSTDCXX_SOFT_ERROR
# | -- Performing Test LLVM_LIBSTDCXX_SOFT_ERROR - Success
# | -- Performing Test CXX_SUPPORTS_CUSTOM_LINKER
# | -- Performing Test CXX_SUPPORTS_CUSTOM_LINKER - Success
# | -- Performing Test C_SUPPORTS_FPIC
# | -- Performing Test C_SUPPORTS_FPIC - Success
# | -- Performing Test CXX_SUPPORTS_FPIC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V backend:X86 clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category llvm:ir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants