From: Lino Hsing-Yu Peng <[email protected]>
Implement Zvfofp8min widening conversions from FP8 to BF16 across the RVV
builtin framework and machine descriptions. This adds the float8 pattern
definitions and wires new shapes, types, and unspecs for these operations.
gcc/ChangeLog:
* config/riscv/riscv-vector-builtins-bases.cc: Add f8 widening
conversions.
* config/riscv/riscv-vector-builtins-functions.def: Add zvfofp8min
builtins.
* config/riscv/riscv-vector-builtins-shapes.cc: Add f8 shapes and
naming.
* config/riscv/riscv-vector-builtins-shapes.h: Declare f8 shapes.
* config/riscv/riscv-vector-builtins.cc: Add f8_to_bf16 operand info.
* config/riscv/riscv-vector-builtins-types.def: Add bf16 ops list.
* config/riscv/riscv.md: Add zvfofp8min unspecs and include
vector-float8.md.
* config/riscv/vector-float8.md: New file.
---
.../riscv/riscv-vector-builtins-bases.cc | 30 ++++++-
.../riscv/riscv-vector-builtins-functions.def | 6 ++
.../riscv/riscv-vector-builtins-shapes.cc | 88 +++++++++++++++++--
.../riscv/riscv-vector-builtins-shapes.h | 3 +
.../riscv/riscv-vector-builtins-types.def | 14 +++
gcc/config/riscv/riscv-vector-builtins.cc | 14 +++
gcc/config/riscv/riscv.md | 6 ++
gcc/config/riscv/vector-float8.md | 63 +++++++++++++
8 files changed, 216 insertions(+), 8 deletions(-)
create mode 100644 gcc/config/riscv/vector-float8.md
diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc
b/gcc/config/riscv/riscv-vector-builtins-bases.cc
index 525a622882a..58ab57db5d4 100644
--- a/gcc/config/riscv/riscv-vector-builtins-bases.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc
@@ -1516,13 +1516,41 @@ public:
}
};
+enum altfmt
+{
+ F8NONE,
+ F8E4M3,
+ F8E5M2
+};
+
+static altfmt
+get_altfmt (const function_expander &e)
+{
+ if (e.shape == shapes::alu_f8e4m3)
+ return F8E4M3;
+ if (e.shape == shapes::alu_f8e5m2)
+ return F8E5M2;
+ return F8NONE;
+}
class vfwcvt_f : public function_base
{
public:
rtx expand (function_expander &e) const override
{
if (e.op_info->op == OP_TYPE_f_v)
- return e.use_exact_insn (code_for_pred_extend (e.vector_mode ()));
+ {
+ switch (get_altfmt (e))
+ {
+ case F8E4M3:
+ return e.use_exact_insn (
+ code_for_pred_extend_to (UNSPEC_F8E4M3, e.vector_mode ()));
+ case F8E5M2:
+ return e.use_exact_insn (
+ code_for_pred_extend_to (UNSPEC_F8E5M2, e.vector_mode ()));
+ default:
+ return e.use_exact_insn (code_for_pred_extend (e.vector_mode ()));
+ }
+ }
if (e.op_info->op == OP_TYPE_x_v)
return e.use_exact_insn (code_for_pred_widen (FLOAT, e.vector_mode ()));
if (e.op_info->op == OP_TYPE_xu_v)
diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def
b/gcc/config/riscv/riscv-vector-builtins-functions.def
index 3ae3de80897..185d811e2b7 100644
--- a/gcc/config/riscv/riscv-vector-builtins-functions.def
+++ b/gcc/config/riscv/riscv-vector-builtins-functions.def
@@ -769,6 +769,12 @@ DEF_RVV_FUNCTION (vfncvtbf16_f_frm, narrow_alu_frm,
full_preds, f32_to_bf16_f_w_
DEF_RVV_FUNCTION (vfwcvtbf16_f, alu, full_preds, bf16_to_f32_f_v_ops)
#undef REQUIRED_EXTENSIONS
+/* Zvfofp8min */
+#define REQUIRED_EXTENSIONS ZVFOFP8MIN_EXT
+DEF_RVV_FUNCTION (vfwcvt_f, alu_f8e4m3, full_preds, f8_to_bf16_f_v_ops)
+DEF_RVV_FUNCTION (vfwcvt_f, alu_f8e5m2, full_preds, f8_to_bf16_f_v_ops)
+#undef REQUIRED_EXTENSIONS
+
/* Zvfbfwma */
#define REQUIRED_EXTENSIONS ZVFBFWMA_EXT
DEF_RVV_FUNCTION (vfwmaccbf16, alu, full_preds, f32_wwvv_ops)
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
index 3bf40c432c2..3533ef01714 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc
@@ -89,15 +89,14 @@ supports_vectype_p (const function_group_info &group,
unsigned int vec_type_idx)
/* Only judge for bf16 vector type */
if (*group.shape == shapes::loadstore
|| *group.shape == shapes::indexed_loadstore
- || *group.shape == shapes::vundefined
- || *group.shape == shapes::misc
- || *group.shape == shapes::vset
- || *group.shape == shapes::vget
- || *group.shape == shapes::vcreate
- || *group.shape == shapes::fault_load
+ || *group.shape == shapes::vundefined || *group.shape == shapes::misc
+ || *group.shape == shapes::vset || *group.shape == shapes::vget
+ || *group.shape == shapes::vcreate || *group.shape == shapes::fault_load
|| *group.shape == shapes::seg_loadstore
|| *group.shape == shapes::seg_indexed_loadstore
- || *group.shape == shapes::seg_fault_load)
+ || *group.shape == shapes::seg_fault_load
+ || *group.shape == shapes::alu_f8e4m3
+ || *group.shape == shapes::alu_f8e5m2)
return true;
return false;
}
@@ -424,6 +423,78 @@ struct alu_def : public build_base
}
};
+static void
+append_f8_suffix (function_builder &b, vector_type_index vti,
+ const char *altfmt)
+{
+ if (vti == VECTOR_TYPE_INVALID)
+ return;
+
+ const char *suffix = type_suffixes[vti].vector;
+ if (!suffix)
+ return;
+
+ if (strncmp (suffix, "_u8", 3) == 0)
+ {
+ b.append_name ("_");
+ b.append_name (altfmt);
+ b.append_name (suffix + 3);
+ }
+ else
+ b.append_name (suffix);
+}
+
+static char *
+build_f8_name (function_builder &b, const function_instance &instance,
+ bool overloaded_p, const char *altfmt)
+{
+ if (overloaded_p && !instance.base->can_be_overloaded_p (instance.pred))
+ return nullptr;
+
+ b.append_base_name (instance.base_name);
+
+ if (overloaded_p)
+ {
+ b.append_name ("_");
+ b.append_name (altfmt);
+ b.append_name ("_bf16");
+ }
+ else
+ {
+ b.append_name (operand_suffixes[instance.op_info->op]);
+ append_f8_suffix (b,
+ instance.op_info->args[0].get_function_type_index (
+ instance.type.index),
+ altfmt);
+ b.append_name (type_suffixes[instance.type.index].vector);
+ }
+
+ if (overloaded_p && instance.pred == PRED_TYPE_m)
+ return b.finish_name ();
+ b.append_name (predication_suffixes[instance.pred]);
+ return b.finish_name ();
+}
+
+/* alu_f8e4m3_def class. */
+struct alu_f8e4m3_def : public alu_def
+{
+ char *get_name (function_builder &b, const function_instance &instance,
+ bool overloaded_p) const override
+ {
+ return build_f8_name (b, instance, overloaded_p, "f8e4m3");
+ }
+};
+
+/* alu_f8e5m2_def class. */
+struct alu_f8e5m2_def : public alu_def
+{
+ char *get_name (function_builder &b, const function_instance &instance,
+ bool overloaded_p) const override
+ {
+ return build_f8_name (b, instance, overloaded_p, "f8e5m2");
+ }
+};
+
/* The base class for frm build. */
struct build_frm_base : public build_base
{
@@ -1431,4 +1502,7 @@ SHAPE (sf_vqmacc, sf_vqmacc)
SHAPE (sf_vfnrclip, sf_vfnrclip)
SHAPE(sf_vcix_se, sf_vcix_se)
SHAPE(sf_vcix, sf_vcix)
+/* Zvfofp8min */
+SHAPE (alu_f8e4m3, alu_f8e4m3)
+SHAPE (alu_f8e5m2, alu_f8e5m2)
} // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.h
b/gcc/config/riscv/riscv-vector-builtins-shapes.h
index d9502d4c5b4..d700d76da30 100644
--- a/gcc/config/riscv/riscv-vector-builtins-shapes.h
+++ b/gcc/config/riscv/riscv-vector-builtins-shapes.h
@@ -64,6 +64,9 @@ extern const function_shape *const sf_vqmacc;
extern const function_shape *const sf_vfnrclip;
extern const function_shape *const sf_vcix_se;
extern const function_shape *const sf_vcix;
+/* Zvfofp8min extension. */
+extern const function_shape *const alu_f8e4m3;
+extern const function_shape *const alu_f8e5m2;
}
} // end namespace riscv_vector
diff --git a/gcc/config/riscv/riscv-vector-builtins-types.def
b/gcc/config/riscv/riscv-vector-builtins-types.def
index 56f55109188..b4c1b693910 100644
--- a/gcc/config/riscv/riscv-vector-builtins-types.def
+++ b/gcc/config/riscv/riscv-vector-builtins-types.def
@@ -42,6 +42,12 @@ along with GCC; see the file COPYING3. If not see
#define DEF_RVV_B_OPS(TYPE, REQUIRE)
#endif
+/* Use "DEF_RVV_BF_OPS" macro include bfloat16 floating-point which will be
+ iterated and registered as intrinsic functions. */
+#ifndef DEF_RVV_BF_OPS
+#define DEF_RVV_BF_OPS(TYPE, REQUIRE)
+#endif
+
/* Use "DEF_RVV_WEXTI_OPS" macro include Double-Widening signed integer which
will be iterated and registered as intrinsic functions. */
#ifndef DEF_RVV_WEXTI_OPS
@@ -477,6 +483,13 @@ DEF_RVV_B_OPS (vbool4_t, 0)
DEF_RVV_B_OPS (vbool2_t, 0)
DEF_RVV_B_OPS (vbool1_t, 0)
+DEF_RVV_BF_OPS (vbfloat16mf4_t, RVV_REQUIRE_ELEN_BF_16 | RVV_REQUIRE_ELEN_64)
+DEF_RVV_BF_OPS (vbfloat16mf2_t, RVV_REQUIRE_ELEN_BF_16)
+DEF_RVV_BF_OPS (vbfloat16m1_t, RVV_REQUIRE_ELEN_BF_16)
+DEF_RVV_BF_OPS (vbfloat16m2_t, RVV_REQUIRE_ELEN_BF_16)
+DEF_RVV_BF_OPS (vbfloat16m4_t, RVV_REQUIRE_ELEN_BF_16)
+DEF_RVV_BF_OPS (vbfloat16m8_t, RVV_REQUIRE_ELEN_BF_16)
+
DEF_RVV_WEXTI_OPS (vint16mf4_t, RVV_REQUIRE_ELEN_64)
DEF_RVV_WEXTI_OPS (vint16mf2_t, 0)
DEF_RVV_WEXTI_OPS (vint16m1_t, 0)
@@ -1546,6 +1559,7 @@ DEF_RVV_F16_OPS (vfloat16m8_t, RVV_REQUIRE_ELEN_FP_16)
#undef DEF_RVV_U_OPS
#undef DEF_RVV_F_OPS
#undef DEF_RVV_B_OPS
+#undef DEF_RVV_BF_OPS
#undef DEF_RVV_WEXTI_OPS
#undef DEF_RVV_QEXTI_OPS
#undef DEF_RVV_OEXTI_OPS
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc
b/gcc/config/riscv/riscv-vector-builtins.cc
index 5892ae5e466..a7ad068b00a 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -277,6 +277,12 @@ static const rvv_type_info b_ops[] = {
#include "riscv-vector-builtins-types.def"
{NUM_VECTOR_TYPES, 0}};
+/* A list of all bfloat will be registered for intrinsic functions. */
+static const rvv_type_info bf_ops[] = {
+#define DEF_RVV_BF_OPS(TYPE, REQUIRE) {VECTOR_TYPE_##TYPE, REQUIRE},
+#include "riscv-vector-builtins-types.def"
+ {NUM_VECTOR_TYPES, 0}};
+
/* A list of all float will be registered for intrinsic functions. */
static const rvv_type_info f_ops[] = {
#define DEF_RVV_F_OPS(TYPE, REQUIRE) {VECTOR_TYPE_##TYPE, REQUIRE},
@@ -2052,6 +2058,14 @@ static CONSTEXPR const rvv_op_info f_to_nf_f_w_ops
rvv_arg_type_info (RVV_BASE_double_trunc_float_vector), /* Return type */
v_args /* Args */};
+/* A static operand information for vector_type func (vector_type)
+ * function registration. */
+static CONSTEXPR const rvv_op_info f8_to_bf16_f_v_ops
+ = {bf_ops, /* Types */
+ OP_TYPE_f_v, /* Suffix */
+ rvv_arg_type_info (RVV_BASE_vector), /* Return type */
+ w_xu_v_args /* Args */};
+
/* A static operand information for vector_type func (vector_type)
* function registration. */
static CONSTEXPR const rvv_op_info f32_to_bf16_f_w_ops
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 3fe0ad0ccdf..a5e5ecae3e7 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -103,6 +103,11 @@
;; Stack Smash Protector
UNSPEC_SSP_SET
UNSPEC_SSP_TEST
+ ;; Zvfofp8min
+ UNSPEC_F8E4M3
+ UNSPEC_F8E5M2
+ UNSPEC_F8E4M3_SAT
+ UNSPEC_F8E5M2_SAT
])
(define_c_enum "unspecv" [
@@ -4971,6 +4976,7 @@
(include "vector.md")
(include "vector-crypto.md")
(include "vector-bfloat16.md")
+(include "vector-float8.md")
(include "zicond.md")
(include "mips-insn.md")
(include "sfb.md")
diff --git a/gcc/config/riscv/vector-float8.md
b/gcc/config/riscv/vector-float8.md
new file mode 100644
index 00000000000..2a3eeeaa1db
--- /dev/null
+++ b/gcc/config/riscv/vector-float8.md
@@ -0,0 +1,63 @@
+;; Machine description for RISC-V Zvfofp8 extension conversions.
+;; Copyright (C) 2026 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_mode_iterator VWEXTF_ZVFOFP8MIN [
+ (RVVM8BF "TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN")
+ (RVVM4BF "TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN")
+ (RVVM2BF "TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN")
+ (RVVM1BF "TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN")
+ (RVVMF2BF "TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN")
+ (RVVMF4BF "TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN && TARGET_MIN_VLEN > 32")
+])
+
+(define_mode_attr VBF_DOUBLE_TRUNC [
+ (RVVM8BF "RVVM4QI")
+ (RVVM4BF "RVVM2QI")
+ (RVVM2BF "RVVM1QI")
+ (RVVM1BF "RVVMF2QI")
+ (RVVMF2BF "RVVMF4QI")
+ (RVVMF4BF "RVVMF8QI")
+])
+
+(define_int_iterator ALTFMT [UNSPEC_F8E4M3 UNSPEC_F8E5M2])
+(define_int_attr altfmt
+ [(UNSPEC_F8E4M3 "f8e4m3")
+ (UNSPEC_F8E5M2 "f8e5m2")])
+
+;; Zvfofp8min extension: FP8 to BF16 widening conversions.
+
+(define_insn "@pred_extend_<altfmt>_to_<mode>"
+ [(set (match_operand:VWEXTF_ZVFOFP8MIN 0 "register_operand" "=&vr,
&vr")
+ (if_then_else:VWEXTF_ZVFOFP8MIN
+ (unspec:<VM>
+ [(match_operand:<VM> 1 "vector_mask_operand" "vmWc1,vmWc1")
+ (match_operand 4 "vector_length_operand" " rK, rK")
+ (match_operand 5 "const_int_operand" " i, i")
+ (match_operand 6 "const_int_operand" " i, i")
+ (match_operand 7 "const_int_operand" " i, i")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ (unspec:VWEXTF_ZVFOFP8MIN
+ [(float_extend:VWEXTF_ZVFOFP8MIN
+ (match_operand:<VBF_DOUBLE_TRUNC> 3 "register_operand" " vr,
vr"))] ALTFMT)
+ (match_operand:VWEXTF_ZVFOFP8MIN 2 "vector_merge_operand" " vu,
0")))]
+ "TARGET_VECTOR && TARGET_ZVFOFP8MIN && TARGET_ZVFBFMIN"
+ "vfwcvtbf16.f.f.v\t%0,%3%p1"
+ [(set_attr "type" "vfwcvtbf16")
+ (set_attr "mode" "<VBF_DOUBLE_TRUNC>")])
--
2.34.1