public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v2 1/2] RISC-V: Support _Float16 type.
@ 2022-08-10 15:44 Kito Cheng
  2022-08-10 15:44 ` [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension Kito Cheng
  2022-12-05 13:05 ` [PATCH v2 1/2] RISC-V: Support _Float16 type Maciej W. Rozycki
  0 siblings, 2 replies; 5+ messages in thread
From: Kito Cheng @ 2022-08-10 15:44 UTC (permalink / raw)
  To: gcc-patches, kito.cheng, jim.wilson.gcc, palmer, andrew,
	juzhe.zhong, joseph
  Cc: Kito Cheng

RISC-V decide use _Float16 as primary IEEE half precision type, and this
already become part of psABI, this patch has added folloing support for
_Float16:

- Soft-float support for _Float16.
- Make sure _Float16 available on C++ mode.
- Name mangling for _Float16 on C++ mode.

gcc/ChangeLog

	* config/riscv/riscv-builtins.cc: include stringpool.h
	(riscv_float16_type_node): New.
	(riscv_init_builtin_types): Ditto.
	(riscv_init_builtins): Call riscv_init_builtin_types.
	* config/riscv/riscv-modes.def (HF): New.
	* gcc/config/riscv/riscv.cc (riscv_output_move): Handle HFmode.
	(riscv_mangle_type): New.
	(riscv_scalar_mode_supported_p): Ditto.
	(riscv_libgcc_floating_mode_supported_p): Ditto.
	(riscv_excess_precision): Ditto.
	(riscv_floatn_mode): Ditto.
	(riscv_init_libfuncs): Ditto.
	(TARGET_MANGLE_TYPE): Ditto.
	(TARGET_SCALAR_MODE_SUPPORTED_P): Ditto.
	(TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P): Ditto.
	(TARGET_INIT_LIBFUNCS): Ditto.
	(TARGET_C_EXCESS_PRECISION): Ditto.
	(TARGET_FLOATN_MODE): Ditto.
	* gcc/config/riscv/riscv.md (mode): Add HF.
	(softload): Add HF.
	(softstore): Ditto.
	(fmt): Ditto.
	(UNITMODE): Ditto.
	(movhf): New.
	(*movhf_softfloat): New.

libgcc/ChangeLog:

	* config/riscv/sfp-machine.h (_FP_NANFRAC_H): New.
	(_FP_NANFRAC_H): Ditto.
	(_FP_NANSIGN_H): Ditto.
	* config/riscv/t-softfp32 (softfp_extensions): Add HF related
	routines.
	(softfp_truncations): Ditto.
	(softfp_extras): Ditto.
	* config/riscv/t-softfp64 (softfp_extras): Add HF related routines.

gcc/testsuite/ChangeLog:

	* gcc/testsuite/g++.target/riscv/_Float16.C: New.
	* gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c: Ditto.
	* gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c: Ditto.
	* gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c: Ditto.
	* gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c: Ditto.
	* gcc/testsuite/gcc.target/riscv/_Float16.c: Ditto.
---
 gcc/config/riscv/riscv-builtins.cc            |  24 +++
 gcc/config/riscv/riscv-modes.def              |   1 +
 gcc/config/riscv/riscv.cc                     | 171 ++++++++++++++++--
 gcc/config/riscv/riscv.md                     |  30 ++-
 gcc/testsuite/g++.target/riscv/_Float16.C     |  18 ++
 .../gcc.target/riscv/_Float16-soft-1.c        |   9 +
 .../gcc.target/riscv/_Float16-soft-2.c        |  13 ++
 .../gcc.target/riscv/_Float16-soft-3.c        |  12 ++
 .../gcc.target/riscv/_Float16-soft-4.c        |  12 ++
 gcc/testsuite/gcc.target/riscv/_Float16.c     |  19 ++
 libgcc/config/riscv/sfp-machine.h             |   3 +
 libgcc/config/riscv/t-softfp32                |   5 +
 libgcc/config/riscv/t-softfp64                |   1 +
 13 files changed, 300 insertions(+), 18 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/riscv/_Float16.C
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16.c

diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 1218fdfc67d..3009311604d 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "recog.h"
 #include "diagnostic-core.h"
 #include "stor-layout.h"
+#include "stringpool.h"
 #include "expr.h"
 #include "langhooks.h"
 
@@ -160,6 +161,8 @@ static GTY(()) int riscv_builtin_decl_index[NUM_INSN_CODES];
 #define GET_BUILTIN_DECL(CODE) \
   riscv_builtin_decls[riscv_builtin_decl_index[(CODE)]]
 
+tree riscv_float16_type_node = NULL_TREE;
+
 /* Return the function type associated with function prototype TYPE.  */
 
 static tree
@@ -185,11 +188,32 @@ riscv_build_function_type (enum riscv_function_type type)
   return types[(int) type];
 }
 
+static void
+riscv_init_builtin_types (void)
+{
+  /* Provide the _Float16 type and float16_type_node if needed.  */
+  if (!float16_type_node)
+    {
+      riscv_float16_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (riscv_float16_type_node) = 16;
+      SET_TYPE_MODE (riscv_float16_type_node, HFmode);
+      layout_type (riscv_float16_type_node);
+    }
+  else
+    riscv_float16_type_node = float16_type_node;
+
+  if (!maybe_get_identifier ("_Float16"))
+    lang_hooks.types.register_builtin_type (riscv_float16_type_node,
+					    "_Float16");
+}
+
 /* Implement TARGET_INIT_BUILTINS.  */
 
 void
 riscv_init_builtins (void)
 {
+  riscv_init_builtin_types ();
+
   for (size_t i = 0; i < ARRAY_SIZE (riscv_builtins); i++)
     {
       const struct riscv_builtin_description *d = &riscv_builtins[i];
diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def
index 653228409a4..5cf2fc8e9e6 100644
--- a/gcc/config/riscv/riscv-modes.def
+++ b/gcc/config/riscv/riscv-modes.def
@@ -19,4 +19,5 @@ 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/>.  */
 
+FLOAT_MODE (HF, 2, ieee_half_format);
 FLOAT_MODE (TF, 16, ieee_quad_format);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5a0adffb5ce..47e6110767c 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2296,11 +2296,13 @@ riscv_output_move (rtx dest, rtx src)
   enum rtx_code dest_code, src_code;
   machine_mode mode;
   bool dbl_p;
+  unsigned width;
 
   dest_code = GET_CODE (dest);
   src_code = GET_CODE (src);
   mode = GET_MODE (dest);
   dbl_p = (GET_MODE_SIZE (mode) == 8);
+  width = GET_MODE_SIZE (mode);
 
   if (dbl_p && riscv_split_64bit_move_p (dest, src))
     return "#";
@@ -2308,10 +2310,19 @@ riscv_output_move (rtx dest, rtx src)
   if (dest_code == REG && GP_REG_P (REGNO (dest)))
     {
       if (src_code == REG && FP_REG_P (REGNO (src)))
-	return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.w\t%0,%1";
+	switch (width)
+	  {
+	  case 2:
+	    /* Using fmv.x.s + sign-extend to emulate fmv.x.h.  */
+	    return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16";
+	  case 4:
+	    return "fmv.x.s\t%0,%1";
+	  case 8:
+	    return "fmv.x.d\t%0,%1";
+	  }
 
       if (src_code == MEM)
-	switch (GET_MODE_SIZE (mode))
+	switch (width)
 	  {
 	  case 1: return "lbu\t%0,%1";
 	  case 2: return "lhu\t%0,%1";
@@ -2353,18 +2364,24 @@ riscv_output_move (rtx dest, rtx src)
 	    return "mv\t%0,%z1";
 
 	  if (FP_REG_P (REGNO (dest)))
-	    {
-	      if (!dbl_p)
-		return "fmv.w.x\t%0,%z1";
-	      if (TARGET_64BIT)
-		return "fmv.d.x\t%0,%z1";
-	      /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */
-	      gcc_assert (src == CONST0_RTX (mode));
-	      return "fcvt.d.w\t%0,x0";
-	    }
+	    switch (width)
+	      {
+	      case 2:
+		/* High 16 bits should be all-1, otherwise HW will treated
+		   as a n-bit canonical NaN, but isn't matter for softfloat.  */
+		return "fmv.s.x\t%0,%1";
+	      case 4:
+		return "fmv.s.x\t%0,%z1";
+	      case 8:
+		if (TARGET_64BIT)
+		  return "fmv.d.x\t%0,%z1";
+		/* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */
+		gcc_assert (src == CONST0_RTX (mode));
+		return "fcvt.d.w\t%0,x0";
+	      }
 	}
       if (dest_code == MEM)
-	switch (GET_MODE_SIZE (mode))
+	switch (width)
 	  {
 	  case 1: return "sb\t%z1,%0";
 	  case 2: return "sh\t%z1,%0";
@@ -2375,7 +2392,15 @@ riscv_output_move (rtx dest, rtx src)
   if (src_code == REG && FP_REG_P (REGNO (src)))
     {
       if (dest_code == REG && FP_REG_P (REGNO (dest)))
-	return dbl_p ? "fmv.d\t%0,%1" : "fmv.s\t%0,%1";
+	switch (width)
+	  {
+	  case 2:
+	    return "fmv.s\t%0,%1";
+	  case 4:
+	    return "fmv.s\t%0,%1";
+	  case 8:
+	    return "fmv.d\t%0,%1";
+	  }
 
       if (dest_code == MEM)
 	return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0";
@@ -5638,6 +5663,107 @@ riscv_asan_shadow_offset (void)
   return TARGET_64BIT ? (HOST_WIDE_INT_1 << 29) : 0;
 }
 
+/* Implement TARGET_MANGLE_TYPE.  */
+
+static const char *
+riscv_mangle_type (const_tree type)
+{
+  /* Half-precision float, _Float16 is "DF16_".  */
+  if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16)
+    return "DF16_";
+
+  /* Use the default mangling.  */
+  return NULL;
+}
+
+/* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
+
+static bool
+riscv_scalar_mode_supported_p (scalar_mode mode)
+{
+  if (mode == HFmode)
+    return true;
+  else
+    return default_scalar_mode_supported_p (mode);
+}
+
+/* Implement TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P - return TRUE
+   if MODE is HFmode, and punt to the generic implementation otherwise.  */
+
+static bool
+riscv_libgcc_floating_mode_supported_p (scalar_float_mode mode)
+{
+  if (mode == HFmode)
+    return true;
+  else
+    return default_libgcc_floating_mode_supported_p (mode);
+}
+
+/* Set the value of FLT_EVAL_METHOD.
+   ISO/IEC TS 18661-3 defines two values that we'd like to make use of:
+
+    0: evaluate all operations and constants, whose semantic type has at
+       most the range and precision of type float, to the range and
+       precision of float; evaluate all other operations and constants to
+       the range and precision of the semantic type;
+
+    N, where _FloatN is a supported interchange floating type
+       evaluate all operations and constants, whose semantic type has at
+       most the range and precision of _FloatN type, to the range and
+       precision of the _FloatN type; evaluate all other operations and
+       constants to the range and precision of the semantic type;
+
+   If we have the zfh extensions then we support _Float16 in native
+   precision, so we should set this to 16.  */
+static enum flt_eval_method
+riscv_excess_precision (enum excess_precision_type type)
+{
+  switch (type)
+    {
+    case EXCESS_PRECISION_TYPE_FAST:
+    case EXCESS_PRECISION_TYPE_STANDARD:
+      return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+    case EXCESS_PRECISION_TYPE_IMPLICIT:
+      return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
+    default:
+      gcc_unreachable ();
+    }
+  return FLT_EVAL_METHOD_UNPREDICTABLE;
+}
+
+/* Implement TARGET_FLOATN_MODE.  */
+static opt_scalar_float_mode
+riscv_floatn_mode (int n, bool extended)
+{
+  if (!extended && n == 16)
+    return HFmode;
+
+  return default_floatn_mode (n, extended);
+}
+
+static void
+riscv_init_libfuncs (void)
+{
+  /* Half-precision float operations.  The compiler handles all operations
+     with NULL libfuncs by converting to SFmode.  */
+
+  /* Arithmetic.  */
+  set_optab_libfunc (add_optab, HFmode, NULL);
+  set_optab_libfunc (sdiv_optab, HFmode, NULL);
+  set_optab_libfunc (smul_optab, HFmode, NULL);
+  set_optab_libfunc (neg_optab, HFmode, NULL);
+  set_optab_libfunc (sub_optab, HFmode, NULL);
+
+  /* Comparisons.  */
+  set_optab_libfunc (eq_optab, HFmode, NULL);
+  set_optab_libfunc (ne_optab, HFmode, NULL);
+  set_optab_libfunc (lt_optab, HFmode, NULL);
+  set_optab_libfunc (le_optab, HFmode, NULL);
+  set_optab_libfunc (ge_optab, HFmode, NULL);
+  set_optab_libfunc (gt_optab, HFmode, NULL);
+  set_optab_libfunc (unord_optab, HFmode, NULL);
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -5821,6 +5947,25 @@ riscv_asan_shadow_offset (void)
 #undef TARGET_NEW_ADDRESS_PROFITABLE_P
 #define TARGET_NEW_ADDRESS_PROFITABLE_P riscv_new_address_profitable_p
 
+#undef TARGET_MANGLE_TYPE
+#define TARGET_MANGLE_TYPE riscv_mangle_type
+
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P riscv_scalar_mode_supported_p
+
+#undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+#define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P                                \
+  riscv_libgcc_floating_mode_supported_p
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS riscv_init_libfuncs
+
+#undef TARGET_C_EXCESS_PRECISION
+#define TARGET_C_EXCESS_PRECISION riscv_excess_precision
+
+#undef TARGET_FLOATN_MODE
+#define TARGET_FLOATN_MODE riscv_floatn_mode
+
 #undef TARGET_ASAN_SHADOW_OFFSET
 #define TARGET_ASAN_SHADOW_OFFSET riscv_asan_shadow_offset
 
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 0796f91dd30..7af5c90e0f3 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -134,7 +134,7 @@ (define_attr "move_type"
   (const_string "unknown"))
 
 ;; Main data type used by the insn
-(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF"
+(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,HF,SF,DF,TF"
   (const_string "unknown"))
 
 ;; True if the main data type is twice the size of a word.
@@ -324,20 +324,20 @@ (define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "
 (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
 
 ;; Mode attribute for FP loads into integer registers.
-(define_mode_attr softload [(SF "lw") (DF "ld")])
+(define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")])
 
 ;; Instruction names for stores.
 (define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
 
 ;; Instruction names for FP stores from integer registers.
-(define_mode_attr softstore [(SF "sw") (DF "sd")])
+(define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")])
 
 ;; This attribute gives the best constraint to use for registers of
 ;; a given mode.
 (define_mode_attr reg [(SI "d") (DI "d") (CC "d")])
 
 ;; This attribute gives the format suffix for floating-point operations.
-(define_mode_attr fmt [(SF "s") (DF "d")])
+(define_mode_attr fmt [(HF "h") (SF "s") (DF "d")])
 
 ;; This attribute gives the integer suffix for floating-point conversions.
 (define_mode_attr ifmt [(SI "w") (DI "l")])
@@ -347,7 +347,7 @@ (define_mode_attr amo [(SI "w") (DI "d")])
 
 ;; This attribute gives the upper-case mode name for one unit of a
 ;; floating-point mode.
-(define_mode_attr UNITMODE [(SF "SF") (DF "DF")])
+(define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")])
 
 ;; This attribute gives the integer mode that has half the size of
 ;; the controlling mode.
@@ -1450,6 +1450,26 @@ (define_insn "extendsfdf2"
   [(set_attr "type" "fcvt")
    (set_attr "mode" "DF")])
 
+;; 16-bit floating point moves
+(define_expand "movhf"
+  [(set (match_operand:HF 0 "")
+	(match_operand:HF 1 ""))]
+  ""
+{
+  if (riscv_legitimize_move (HFmode, operands[0], operands[1]))
+    DONE;
+})
+
+
+(define_insn "*movhf_softfloat"
+  [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
+	(match_operand:HF 1 "move_operand"         " f,Gr,m,r,*r,*f"))]
+  "(register_operand (operands[0], HFmode)
+    || reg_or_0_operand (operands[1], HFmode))"
+  { return riscv_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
+   (set_attr "mode" "HF")])
+
 ;;
 ;;  ....................
 ;;
diff --git a/gcc/testsuite/g++.target/riscv/_Float16.C b/gcc/testsuite/g++.target/riscv/_Float16.C
new file mode 100644
index 00000000000..b97d1fbcf1c
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/_Float16.C
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+
+_Float16 x;
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    return a + b;
+}
+
+_Float16 foo2 (_Float16 a, _Float16 b)
+{
+    return a * b;
+}
+
+int foo3 (_Float16 a, _Float16 b)
+{
+    return a > b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c
new file mode 100644
index 00000000000..0622588fdb9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if -mabi=lp64f -O" } */
+
+_Float16 test_soft_move (_Float16 a, _Float16 b)
+{
+    return b;
+}
+
+/* { dg-final { scan-assembler-not "fmv.h" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c
new file mode 100644
index 00000000000..3d37823fa4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if -mabi=lp64f -O" } */
+
+_Float16 test_soft_add (_Float16 a, _Float16 b)
+{
+    /* Make sure __addhf3 not invoked here. */
+    /* { dg-final { scan-assembler-times "call\t__extendhfsf2" 2 } } */
+    return a + b;
+    /* { dg-final { scan-assembler-not "call\t__addhf3" } } */
+    /* { dg-final { scan-assembler-times "fadd.s" 1 } } */
+    /* { dg-final { scan-assembler-times "call\t__truncsfhf2" 1 } } */
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c
new file mode 100644
index 00000000000..ecce364e310
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if -mabi=lp64f -O" } */
+
+int test_soft_compare (_Float16 a, _Float16 b)
+{
+    /* Make sure __gthf2 not invoked here. */
+    /* { dg-final { scan-assembler-times "call\t__extendhfsf2" 2 } } */
+    return a > b;
+    /* { dg-final { scan-assembler-not "call\t__gthf2" } } */
+    /* { dg-final { scan-assembler-times "fgt.s" 1 } } */
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c b/gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c
new file mode 100644
index 00000000000..ce4bc7a6a5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-soft-4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i -mabi=lp64 -O" } */
+
+int test_soft_compare (_Float16 a, _Float16 b)
+{
+    /* Make sure __gthf2 not invoked here. */
+    /* { dg-final { scan-assembler-times "call\t__extendhfsf2" 2 } } */
+    return a > b;
+    /* { dg-final { scan-assembler-not "call\t__gthf2" } } */
+    /* { dg-final { scan-assembler-times "call\t__gtsf2" 1 } } */
+}
+
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16.c b/gcc/testsuite/gcc.target/riscv/_Float16.c
new file mode 100644
index 00000000000..cc131fd3e2c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+_Float16 x;
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    return a + b;
+}
+
+_Float16 foo2 (_Float16 a, _Float16 b)
+{
+    return a * b;
+}
+
+int foo3 (_Float16 a, _Float16 b)
+{
+    return a > b;
+}
diff --git a/libgcc/config/riscv/sfp-machine.h b/libgcc/config/riscv/sfp-machine.h
index 27fbe6e84d6..b2901f0b1fd 100644
--- a/libgcc/config/riscv/sfp-machine.h
+++ b/libgcc/config/riscv/sfp-machine.h
@@ -41,6 +41,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_2_udiv(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_4_udiv(Q,R,X,Y)
 
+#define _FP_NANFRAC_H		_FP_QNANBIT_H
 #define _FP_NANFRAC_S		_FP_QNANBIT_S
 #define _FP_NANFRAC_D		_FP_QNANBIT_D, 0
 #define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0, 0, 0
@@ -63,6 +64,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
 #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
 
+#define _FP_NANFRAC_H		_FP_QNANBIT_H
 #define _FP_NANFRAC_S		_FP_QNANBIT_S
 #define _FP_NANFRAC_D		_FP_QNANBIT_D
 #define _FP_NANFRAC_Q		_FP_QNANBIT_Q, 0
@@ -80,6 +82,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
 typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
 #define CMPtype __gcc_CMPtype
 
+#define _FP_NANSIGN_H		0
 #define _FP_NANSIGN_S		0
 #define _FP_NANSIGN_D		0
 #define _FP_NANSIGN_Q		0
diff --git a/libgcc/config/riscv/t-softfp32 b/libgcc/config/riscv/t-softfp32
index 59be1df827e..55261f98383 100644
--- a/libgcc/config/riscv/t-softfp32
+++ b/libgcc/config/riscv/t-softfp32
@@ -41,3 +41,8 @@ else
 softfp_extras := divsf3 divdf3 divtf3
 
 endif
+
+softfp_extensions += hfsf hfdf hftf
+softfp_truncations += tfhf dfhf sfhf
+softfp_extras += fixhfsi fixhfdi fixunshfsi fixunshfdi \
+                 floatsihf floatdihf floatunsihf floatundihf
diff --git a/libgcc/config/riscv/t-softfp64 b/libgcc/config/riscv/t-softfp64
index 75870951202..c87d242d5c3 100644
--- a/libgcc/config/riscv/t-softfp64
+++ b/libgcc/config/riscv/t-softfp64
@@ -1,3 +1,4 @@
 include $(srcdir)/config/riscv/t-softfp32
 
 softfp_int_modes += ti
+softfp_extras += fixhfti fixunshfti floattihf floatuntihf
-- 
2.37.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension
  2022-08-10 15:44 [PATCH v2 1/2] RISC-V: Support _Float16 type Kito Cheng
@ 2022-08-10 15:44 ` Kito Cheng
  2022-08-10 23:19   ` 钟居哲
  2022-12-05 13:05 ` [PATCH v2 1/2] RISC-V: Support _Float16 type Maciej W. Rozycki
  1 sibling, 1 reply; 5+ messages in thread
From: Kito Cheng @ 2022-08-10 15:44 UTC (permalink / raw)
  To: gcc-patches, kito.cheng, jim.wilson.gcc, palmer, andrew,
	juzhe.zhong, joseph
  Cc: Kito Cheng

Zfh and Zfhmin are extensions for IEEE half precision, both are ratified
in Jan. 2022[1]:

- Zfh has full set of operation like F or D for single or double precision.
- Zfhmin has only provide minimal support for half precision operation,
  like conversion, load, store and move instructions.

[1] https://github.com/riscv/riscv-isa-manual/commit/b35a54079e0da11740ce5b1e6db999d1d5172768

gcc/ChangeLog:

	* common/config/riscv/riscv-common.cc (riscv_implied_info): Add
	zfh and zfhmin.
	(riscv_ext_version_table): Ditto.
	(riscv_ext_flag_table): Ditto.
	* config/riscv/riscv-opts.h (MASK_ZFHMIN): New.
	(MASK_ZFH): Ditto.
	(TARGET_ZFHMIN): Ditto.
	(TARGET_ZFH): Ditto.
	* config/riscv/riscv.cc (riscv_output_move): Handle HFmode move
	for zfh and zfhmin.
	(riscv_emit_float_compare): Handle HFmode.
	* config/riscv/riscv.md (ANYF): Add HF.
	(SOFTF): Add HF.
	(load): Ditto.
	(store): Ditto.
	(truncsfhf2): New.
	(truncdfhf2): Ditto.
	(extendhfsf2): Ditto.
	(extendhfdf2): Ditto.
	(*movhf_hardfloat): Ditto.
	(*movhf_softfloat): Make sure not ZFHMIN.
	* config/riscv/riscv.opt (riscv_zf_subext): New.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/_Float16-zfh-1.c: New.
	* gcc.target/riscv/_Float16-zfh-2.c: Ditto.
	* gcc.target/riscv/_Float16-zfh-3.c: Ditto.
	* gcc.target/riscv/_Float16-zfhmin-1.c: Ditto.
	* gcc.target/riscv/_Float16-zfhmin-2.c: Ditto.
	* gcc.target/riscv/_Float16-zfhmin-3.c: Ditto.
	* gcc.target/riscv/arch-16.c: Ditto.
	* gcc.target/riscv/arch-17.c: Ditto.
	* gcc.target/riscv/predef-21.c: Ditto.
	* gcc.target/riscv/predef-22.c: Ditto.
---
 gcc/common/config/riscv/riscv-common.cc       |  8 +++
 gcc/config/riscv/riscv-opts.h                 |  6 ++
 gcc/config/riscv/riscv.cc                     | 33 ++++++++++-
 gcc/config/riscv/riscv.md                     | 59 +++++++++++++++++--
 gcc/config/riscv/riscv.opt                    |  3 +
 .../gcc.target/riscv/_Float16-zfh-1.c         |  8 +++
 .../gcc.target/riscv/_Float16-zfh-2.c         |  8 +++
 .../gcc.target/riscv/_Float16-zfh-3.c         |  8 +++
 .../gcc.target/riscv/_Float16-zfhmin-1.c      |  9 +++
 .../gcc.target/riscv/_Float16-zfhmin-2.c      |  9 +++
 .../gcc.target/riscv/_Float16-zfhmin-3.c      |  9 +++
 gcc/testsuite/gcc.target/riscv/arch-16.c      |  5 ++
 gcc/testsuite/gcc.target/riscv/arch-17.c      |  5 ++
 gcc/testsuite/gcc.target/riscv/predef-21.c    | 59 +++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/predef-22.c    | 59 +++++++++++++++++++
 15 files changed, 279 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-16.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/arch-17.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/predef-21.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/predef-22.c

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 0e5be2ce105..4ee1b3198c5 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -96,6 +96,9 @@ static const riscv_implied_info_t riscv_implied_info[] =
   {"zvl32768b", "zvl16384b"},
   {"zvl65536b", "zvl32768b"},
 
+  {"zfh", "zfhmin"},
+  {"zfhmin", "f"},
+
   {NULL, NULL}
 };
 
@@ -193,6 +196,9 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"zvl32768b", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zvl65536b", ISA_SPEC_CLASS_NONE, 1, 0},
 
+  {"zfh",       ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zfhmin",    ISA_SPEC_CLASS_NONE, 1, 0},
+
   /* Terminate the list.  */
   {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
 };
@@ -1148,6 +1154,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"zvl32768b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32768B},
   {"zvl65536b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL65536B},
 
+  {"zfhmin",    &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN},
+  {"zfh",       &gcc_options::x_riscv_zf_subext, MASK_ZFH},
 
   {NULL, NULL, 0}
 };
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 1e153b3a6e7..85e869e62e3 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -153,6 +153,12 @@ enum stack_protector_guard {
 #define TARGET_ZICBOM ((riscv_zicmo_subext & MASK_ZICBOM) != 0)
 #define TARGET_ZICBOP ((riscv_zicmo_subext & MASK_ZICBOP) != 0)
 
+#define MASK_ZFHMIN   (1 << 0)
+#define MASK_ZFH      (1 << 1)
+
+#define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0)
+#define TARGET_ZFH    ((riscv_zf_subext & MASK_ZFH) != 0)
+
 /* Bit of riscv_zvl_flags will set contintuly, N-1 bit will set if N-bit is
    set, e.g. MASK_ZVL64B has set then MASK_ZVL32B is set, so we can use
    popcount to caclulate the minimal VLEN.  */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 47e6110767c..9d70974c893 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2313,6 +2313,8 @@ riscv_output_move (rtx dest, rtx src)
 	switch (width)
 	  {
 	  case 2:
+	    if (TARGET_ZFHMIN)
+	      return "fmv.x.h\t%0,%1";
 	    /* Using fmv.x.s + sign-extend to emulate fmv.x.h.  */
 	    return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16";
 	  case 4:
@@ -2367,6 +2369,8 @@ riscv_output_move (rtx dest, rtx src)
 	    switch (width)
 	      {
 	      case 2:
+		if (TARGET_ZFHMIN)
+		  return "fmv.h.x\t%0,%z1";
 		/* High 16 bits should be all-1, otherwise HW will treated
 		   as a n-bit canonical NaN, but isn't matter for softfloat.  */
 		return "fmv.s.x\t%0,%1";
@@ -2395,6 +2399,8 @@ riscv_output_move (rtx dest, rtx src)
 	switch (width)
 	  {
 	  case 2:
+	    if (TARGET_ZFH)
+	      return "fmv.h\t%0,%1";
 	    return "fmv.s\t%0,%1";
 	  case 4:
 	    return "fmv.s\t%0,%1";
@@ -2403,12 +2409,28 @@ riscv_output_move (rtx dest, rtx src)
 	  }
 
       if (dest_code == MEM)
-	return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0";
+	switch (width)
+	  {
+	  case 2:
+	    return "fsh\t%1,%0";
+	  case 4:
+	    return "fsw\t%1,%0";
+	  case 8:
+	    return "fsd\t%1,%0";
+	  }
     }
   if (dest_code == REG && FP_REG_P (REGNO (dest)))
     {
       if (src_code == MEM)
-	return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1";
+	switch (width)
+	  {
+	  case 2:
+	    return "flh\t%0,%1";
+	  case 4:
+	    return "flw\t%0,%1";
+	  case 8:
+	    return "fld\t%0,%1";
+	  }
     }
   gcc_unreachable ();
 }
@@ -2685,6 +2707,10 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
 	emit_insn (gen_f##CMP##_quietdfdi4 (*op0, cmp_op0, cmp_op1));	\
       else if (GET_MODE (cmp_op0) == DFmode)				\
 	emit_insn (gen_f##CMP##_quietdfsi4 (*op0, cmp_op0, cmp_op1));	\
+      else if (GET_MODE (cmp_op0) == HFmode && TARGET_64BIT)		\
+	emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1));	\
+      else if (GET_MODE (cmp_op0) == HFmode)				\
+	emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1));	\
       else								\
 	gcc_unreachable ();						\
       *op1 = const0_rtx;						\
@@ -5722,7 +5748,8 @@ riscv_excess_precision (enum excess_precision_type type)
     {
     case EXCESS_PRECISION_TYPE_FAST:
     case EXCESS_PRECISION_TYPE_STANDARD:
-      return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      return (TARGET_ZFH ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+			 : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
     case EXCESS_PRECISION_TYPE_IMPLICIT:
       return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
     default:
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 7af5c90e0f3..493f00cdb80 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -307,17 +307,18 @@ (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
 
 ;; Iterator for hardware-supported floating-point modes.
 (define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
-			    (DF "TARGET_DOUBLE_FLOAT")])
+			    (DF "TARGET_DOUBLE_FLOAT")
+			    (HF "TARGET_ZFH")])
 
 ;; Iterator for floating-point modes that can be loaded into X registers.
-(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
+(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
 
 ;; This attribute gives the length suffix for a sign- or zero-extension
 ;; instruction.
 (define_mode_attr size [(QI "b") (HI "h")])
 
 ;; Mode attributes for loads.
-(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
+(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")])
 
 ;; Instruction names for integer loads that aren't explicitly sign or zero
 ;; extended.  See riscv_output_move and LOAD_EXTEND_OP.
@@ -327,7 +328,7 @@ (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
 (define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")])
 
 ;; Instruction names for stores.
-(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
+(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")])
 
 ;; Instruction names for FP stores from integer registers.
 (define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")])
@@ -1324,6 +1325,24 @@ (define_insn "truncdfsf2"
   [(set_attr "type" "fcvt")
    (set_attr "mode" "SF")])
 
+(define_insn "truncsfhf2"
+  [(set (match_operand:HF     0 "register_operand" "=f")
+       (float_truncate:HF
+           (match_operand:SF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN"
+  "fcvt.h.s\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "HF")])
+
+(define_insn "truncdfhf2"
+  [(set (match_operand:HF     0 "register_operand" "=f")
+       (float_truncate:HF
+           (match_operand:DF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT"
+  "fcvt.h.d\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "HF")])
+
 ;;
 ;;  ....................
 ;;
@@ -1441,6 +1460,15 @@ (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
   [(set_attr "move_type" "shift_shift,load")
    (set_attr "mode" "SI")])
 
+(define_insn "extendhfsf2"
+  [(set (match_operand:SF     0 "register_operand" "=f")
+       (float_extend:SF
+           (match_operand:HF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN"
+  "fcvt.s.h\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "SF")])
+
 (define_insn "extendsfdf2"
   [(set (match_operand:DF     0 "register_operand" "=f")
 	(float_extend:DF
@@ -1450,6 +1478,15 @@ (define_insn "extendsfdf2"
   [(set_attr "type" "fcvt")
    (set_attr "mode" "DF")])
 
+(define_insn "extendhfdf2"
+  [(set (match_operand:DF     0 "register_operand" "=f")
+       (float_extend:DF
+           (match_operand:HF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT"
+  "fcvt.d.h\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "DF")])
+
 ;; 16-bit floating point moves
 (define_expand "movhf"
   [(set (match_operand:HF 0 "")
@@ -1460,12 +1497,22 @@ (define_expand "movhf"
     DONE;
 })
 
+(define_insn "*movhf_hardfloat"
+  [(set (match_operand:HF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  *r,*r,*m")
+	(match_operand:HF 1 "move_operand"         " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
+  "TARGET_ZFHMIN
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  { return riscv_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+   (set_attr "mode" "HF")])
 
 (define_insn "*movhf_softfloat"
   [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
 	(match_operand:HF 1 "move_operand"         " f,Gr,m,r,*r,*f"))]
-  "(register_operand (operands[0], HFmode)
-    || reg_or_0_operand (operands[1], HFmode))"
+  "!TARGET_ZFHMIN
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
   [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
    (set_attr "mode" "HF")])
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 9e9fe6d8ccd..fbca91b956c 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -212,6 +212,9 @@ int riscv_zvl_flags
 TargetVariable
 int riscv_zicmo_subext
 
+TargetVariable
+int riscv_zf_subext
+
 Enum
 Name(isa_spec_class) Type(enum riscv_isa_spec_class)
 Supported ISA specs (for use with the -misa-spec= option):
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c
new file mode 100644
index 00000000000..98908dccbb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-times "fmv.h" 1 } } */
+    return b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c
new file mode 100644
index 00000000000..58bfa6b4198
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-times "fadd.h" 1 } } */
+    return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c
new file mode 100644
index 00000000000..128b4e53f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */
+
+int foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-times "fgt.h" 1 } } */
+    return a > b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c
new file mode 100644
index 00000000000..631a049f52f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-not "fmv.h" } } */
+    /* { dg-final { scan-assembler-times "fmv.s" 1 } } */
+    return b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c
new file mode 100644
index 00000000000..06c85eb797d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-not "fadd.h" } } */
+    /* { dg-final { scan-assembler-times "fadd.s" 1 } } */
+    return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c
new file mode 100644
index 00000000000..28960d60245
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+int foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-not "fgt.h" } } */
+    /* { dg-final { scan-assembler-times "fgt.s" 1 } } */
+    return a > b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-16.c b/gcc/testsuite/gcc.target/riscv/arch-16.c
new file mode 100644
index 00000000000..14b40ae9a5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-16.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gcv_zfh -mabi=ilp32 -mcmodel=medlow" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-17.c b/gcc/testsuite/gcc.target/riscv/arch-17.c
new file mode 100644
index 00000000000..3d3275e44a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-17.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gcv_zfhmin -mabi=ilp32 -mcmodel=medlow" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-21.c b/gcc/testsuite/gcc.target/riscv/predef-21.c
new file mode 100644
index 00000000000..a171b3b83af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-21.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64i_zfh -mabi=lp64f -mcmodel=medlow -misa-spec=20191213" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 64
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i)
+#error "__riscv_i"
+#endif
+
+#if defined(__riscv_c)
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if defined(__riscv_a)
+#error "__riscv_a"
+#endif
+
+#if defined(__riscv_m)
+#error "__riscv_m"
+#endif
+
+#if !defined(__riscv_f)
+#error "__riscv_f"
+#endif
+
+#if defined(__riscv_d)
+#error "__riscv_d"
+#endif
+
+#if defined(__riscv_v)
+#error "__riscv_v"
+#endif
+
+#if !defined(__riscv_zfh)
+#error "__riscv_zfh"
+#endif
+
+#if !defined(__riscv_zfhmin)
+#error "__riscv_zfhmin"
+#endif
+
+#if !defined(__riscv_zicsr)
+#error "__riscv_zicsr"
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-22.c b/gcc/testsuite/gcc.target/riscv/predef-22.c
new file mode 100644
index 00000000000..ad1896573ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-22.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64i_zfhmin -mabi=lp64f -mcmodel=medlow -misa-spec=20191213" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 64
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i)
+#error "__riscv_i"
+#endif
+
+#if defined(__riscv_c)
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if defined(__riscv_a)
+#error "__riscv_a"
+#endif
+
+#if defined(__riscv_m)
+#error "__riscv_m"
+#endif
+
+#if !defined(__riscv_f)
+#error "__riscv_f"
+#endif
+
+#if defined(__riscv_d)
+#error "__riscv_d"
+#endif
+
+#if defined(__riscv_v)
+#error "__riscv_v"
+#endif
+
+#if defined(__riscv_zfh)
+#error "__riscv_zfh"
+#endif
+
+#if !defined(__riscv_zfhmin)
+#error "__riscv_zfhmin"
+#endif
+
+#if !defined(__riscv_zicsr)
+#error "__riscv_zicsr"
+#endif
+
+  return 0;
+}
-- 
2.37.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension
  2022-08-10 15:44 ` [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension Kito Cheng
@ 2022-08-10 23:19   ` 钟居哲
  0 siblings, 0 replies; 5+ messages in thread
From: 钟居哲 @ 2022-08-10 23:19 UTC (permalink / raw)
  To: kito.cheng; +Cc: gcc-patches

LGTM. 



juzhe.zhong@rivai.ai
 
From: Kito Cheng
Date: 2022-08-10 23:44
To: gcc-patches; kito.cheng; jim.wilson.gcc; palmer; andrew; juzhe.zhong; joseph
CC: Kito Cheng
Subject: [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension
Zfh and Zfhmin are extensions for IEEE half precision, both are ratified
in Jan. 2022[1]:
 
- Zfh has full set of operation like F or D for single or double precision.
- Zfhmin has only provide minimal support for half precision operation,
  like conversion, load, store and move instructions.
 
[1] https://github.com/riscv/riscv-isa-manual/commit/b35a54079e0da11740ce5b1e6db999d1d5172768
 
gcc/ChangeLog:
 
* common/config/riscv/riscv-common.cc (riscv_implied_info): Add
zfh and zfhmin.
(riscv_ext_version_table): Ditto.
(riscv_ext_flag_table): Ditto.
* config/riscv/riscv-opts.h (MASK_ZFHMIN): New.
(MASK_ZFH): Ditto.
(TARGET_ZFHMIN): Ditto.
(TARGET_ZFH): Ditto.
* config/riscv/riscv.cc (riscv_output_move): Handle HFmode move
for zfh and zfhmin.
(riscv_emit_float_compare): Handle HFmode.
* config/riscv/riscv.md (ANYF): Add HF.
(SOFTF): Add HF.
(load): Ditto.
(store): Ditto.
(truncsfhf2): New.
(truncdfhf2): Ditto.
(extendhfsf2): Ditto.
(extendhfdf2): Ditto.
(*movhf_hardfloat): Ditto.
(*movhf_softfloat): Make sure not ZFHMIN.
* config/riscv/riscv.opt (riscv_zf_subext): New.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/_Float16-zfh-1.c: New.
* gcc.target/riscv/_Float16-zfh-2.c: Ditto.
* gcc.target/riscv/_Float16-zfh-3.c: Ditto.
* gcc.target/riscv/_Float16-zfhmin-1.c: Ditto.
* gcc.target/riscv/_Float16-zfhmin-2.c: Ditto.
* gcc.target/riscv/_Float16-zfhmin-3.c: Ditto.
* gcc.target/riscv/arch-16.c: Ditto.
* gcc.target/riscv/arch-17.c: Ditto.
* gcc.target/riscv/predef-21.c: Ditto.
* gcc.target/riscv/predef-22.c: Ditto.
---
gcc/common/config/riscv/riscv-common.cc       |  8 +++
gcc/config/riscv/riscv-opts.h                 |  6 ++
gcc/config/riscv/riscv.cc                     | 33 ++++++++++-
gcc/config/riscv/riscv.md                     | 59 +++++++++++++++++--
gcc/config/riscv/riscv.opt                    |  3 +
.../gcc.target/riscv/_Float16-zfh-1.c         |  8 +++
.../gcc.target/riscv/_Float16-zfh-2.c         |  8 +++
.../gcc.target/riscv/_Float16-zfh-3.c         |  8 +++
.../gcc.target/riscv/_Float16-zfhmin-1.c      |  9 +++
.../gcc.target/riscv/_Float16-zfhmin-2.c      |  9 +++
.../gcc.target/riscv/_Float16-zfhmin-3.c      |  9 +++
gcc/testsuite/gcc.target/riscv/arch-16.c      |  5 ++
gcc/testsuite/gcc.target/riscv/arch-17.c      |  5 ++
gcc/testsuite/gcc.target/riscv/predef-21.c    | 59 +++++++++++++++++++
gcc/testsuite/gcc.target/riscv/predef-22.c    | 59 +++++++++++++++++++
15 files changed, 279 insertions(+), 9 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/arch-16.c
create mode 100644 gcc/testsuite/gcc.target/riscv/arch-17.c
create mode 100644 gcc/testsuite/gcc.target/riscv/predef-21.c
create mode 100644 gcc/testsuite/gcc.target/riscv/predef-22.c
 
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 0e5be2ce105..4ee1b3198c5 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -96,6 +96,9 @@ static const riscv_implied_info_t riscv_implied_info[] =
   {"zvl32768b", "zvl16384b"},
   {"zvl65536b", "zvl32768b"},
+  {"zfh", "zfhmin"},
+  {"zfhmin", "f"},
+
   {NULL, NULL}
};
@@ -193,6 +196,9 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"zvl32768b", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zvl65536b", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zfh",       ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zfhmin",    ISA_SPEC_CLASS_NONE, 1, 0},
+
   /* Terminate the list.  */
   {NULL, ISA_SPEC_CLASS_NONE, 0, 0}
};
@@ -1148,6 +1154,8 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"zvl32768b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL32768B},
   {"zvl65536b", &gcc_options::x_riscv_zvl_flags, MASK_ZVL65536B},
+  {"zfhmin",    &gcc_options::x_riscv_zf_subext, MASK_ZFHMIN},
+  {"zfh",       &gcc_options::x_riscv_zf_subext, MASK_ZFH},
   {NULL, NULL, 0}
};
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 1e153b3a6e7..85e869e62e3 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -153,6 +153,12 @@ enum stack_protector_guard {
#define TARGET_ZICBOM ((riscv_zicmo_subext & MASK_ZICBOM) != 0)
#define TARGET_ZICBOP ((riscv_zicmo_subext & MASK_ZICBOP) != 0)
+#define MASK_ZFHMIN   (1 << 0)
+#define MASK_ZFH      (1 << 1)
+
+#define TARGET_ZFHMIN ((riscv_zf_subext & MASK_ZFHMIN) != 0)
+#define TARGET_ZFH    ((riscv_zf_subext & MASK_ZFH) != 0)
+
/* Bit of riscv_zvl_flags will set contintuly, N-1 bit will set if N-bit is
    set, e.g. MASK_ZVL64B has set then MASK_ZVL32B is set, so we can use
    popcount to caclulate the minimal VLEN.  */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 47e6110767c..9d70974c893 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2313,6 +2313,8 @@ riscv_output_move (rtx dest, rtx src)
switch (width)
  {
  case 2:
+     if (TARGET_ZFHMIN)
+       return "fmv.x.h\t%0,%1";
    /* Using fmv.x.s + sign-extend to emulate fmv.x.h.  */
    return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16";
  case 4:
@@ -2367,6 +2369,8 @@ riscv_output_move (rtx dest, rtx src)
    switch (width)
      {
      case 2:
+ if (TARGET_ZFHMIN)
+   return "fmv.h.x\t%0,%z1";
/* High 16 bits should be all-1, otherwise HW will treated
   as a n-bit canonical NaN, but isn't matter for softfloat.  */
return "fmv.s.x\t%0,%1";
@@ -2395,6 +2399,8 @@ riscv_output_move (rtx dest, rtx src)
switch (width)
  {
  case 2:
+     if (TARGET_ZFH)
+       return "fmv.h\t%0,%1";
    return "fmv.s\t%0,%1";
  case 4:
    return "fmv.s\t%0,%1";
@@ -2403,12 +2409,28 @@ riscv_output_move (rtx dest, rtx src)
  }
       if (dest_code == MEM)
- return dbl_p ? "fsd\t%1,%0" : "fsw\t%1,%0";
+ switch (width)
+   {
+   case 2:
+     return "fsh\t%1,%0";
+   case 4:
+     return "fsw\t%1,%0";
+   case 8:
+     return "fsd\t%1,%0";
+   }
     }
   if (dest_code == REG && FP_REG_P (REGNO (dest)))
     {
       if (src_code == MEM)
- return dbl_p ? "fld\t%0,%1" : "flw\t%0,%1";
+ switch (width)
+   {
+   case 2:
+     return "flh\t%0,%1";
+   case 4:
+     return "flw\t%0,%1";
+   case 8:
+     return "fld\t%0,%1";
+   }
     }
   gcc_unreachable ();
}
@@ -2685,6 +2707,10 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
emit_insn (gen_f##CMP##_quietdfdi4 (*op0, cmp_op0, cmp_op1)); \
       else if (GET_MODE (cmp_op0) == DFmode) \
emit_insn (gen_f##CMP##_quietdfsi4 (*op0, cmp_op0, cmp_op1)); \
+      else if (GET_MODE (cmp_op0) == HFmode && TARGET_64BIT) \
+ emit_insn (gen_f##CMP##_quiethfdi4 (*op0, cmp_op0, cmp_op1)); \
+      else if (GET_MODE (cmp_op0) == HFmode) \
+ emit_insn (gen_f##CMP##_quiethfsi4 (*op0, cmp_op0, cmp_op1)); \
       else \
gcc_unreachable (); \
       *op1 = const0_rtx; \
@@ -5722,7 +5748,8 @@ riscv_excess_precision (enum excess_precision_type type)
     {
     case EXCESS_PRECISION_TYPE_FAST:
     case EXCESS_PRECISION_TYPE_STANDARD:
-      return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT;
+      return (TARGET_ZFH ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16
+ : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT);
     case EXCESS_PRECISION_TYPE_IMPLICIT:
       return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16;
     default:
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 7af5c90e0f3..493f00cdb80 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -307,17 +307,18 @@ (define_mode_iterator ANYI [QI HI SI (DI "TARGET_64BIT")])
;; Iterator for hardware-supported floating-point modes.
(define_mode_iterator ANYF [(SF "TARGET_HARD_FLOAT")
-     (DF "TARGET_DOUBLE_FLOAT")])
+     (DF "TARGET_DOUBLE_FLOAT")
+     (HF "TARGET_ZFH")])
;; Iterator for floating-point modes that can be loaded into X registers.
-(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT")])
+(define_mode_iterator SOFTF [SF (DF "TARGET_64BIT") (HF "TARGET_ZFHMIN")])
;; This attribute gives the length suffix for a sign- or zero-extension
;; instruction.
(define_mode_attr size [(QI "b") (HI "h")])
;; Mode attributes for loads.
-(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (SF "flw") (DF "fld")])
+(define_mode_attr load [(QI "lb") (HI "lh") (SI "lw") (DI "ld") (HF "flh") (SF "flw") (DF "fld")])
;; Instruction names for integer loads that aren't explicitly sign or zero
;; extended.  See riscv_output_move and LOAD_EXTEND_OP.
@@ -327,7 +328,7 @@ (define_mode_attr default_load [(QI "lbu") (HI "lhu") (SI "lw") (DI "ld")])
(define_mode_attr softload [(HF "lh") (SF "lw") (DF "ld")])
;; Instruction names for stores.
-(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (SF "fsw") (DF "fsd")])
+(define_mode_attr store [(QI "sb") (HI "sh") (SI "sw") (DI "sd") (HF "fsh") (SF "fsw") (DF "fsd")])
;; Instruction names for FP stores from integer registers.
(define_mode_attr softstore [(HF "sh") (SF "sw") (DF "sd")])
@@ -1324,6 +1325,24 @@ (define_insn "truncdfsf2"
   [(set_attr "type" "fcvt")
    (set_attr "mode" "SF")])
+(define_insn "truncsfhf2"
+  [(set (match_operand:HF     0 "register_operand" "=f")
+       (float_truncate:HF
+           (match_operand:SF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN"
+  "fcvt.h.s\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "HF")])
+
+(define_insn "truncdfhf2"
+  [(set (match_operand:HF     0 "register_operand" "=f")
+       (float_truncate:HF
+           (match_operand:DF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT"
+  "fcvt.h.d\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "HF")])
+
;;
;;  ....................
;;
@@ -1441,6 +1460,15 @@ (define_insn_and_split "*extend<SHORT:mode><SUPERQI:mode>2"
   [(set_attr "move_type" "shift_shift,load")
    (set_attr "mode" "SI")])
+(define_insn "extendhfsf2"
+  [(set (match_operand:SF     0 "register_operand" "=f")
+       (float_extend:SF
+           (match_operand:HF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN"
+  "fcvt.s.h\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "SF")])
+
(define_insn "extendsfdf2"
   [(set (match_operand:DF     0 "register_operand" "=f")
(float_extend:DF
@@ -1450,6 +1478,15 @@ (define_insn "extendsfdf2"
   [(set_attr "type" "fcvt")
    (set_attr "mode" "DF")])
+(define_insn "extendhfdf2"
+  [(set (match_operand:DF     0 "register_operand" "=f")
+       (float_extend:DF
+           (match_operand:HF 1 "register_operand" " f")))]
+  "TARGET_ZFHMIN && TARGET_DOUBLE_FLOAT"
+  "fcvt.d.h\t%0,%1"
+  [(set_attr "type" "fcvt")
+   (set_attr "mode" "DF")])
+
;; 16-bit floating point moves
(define_expand "movhf"
   [(set (match_operand:HF 0 "")
@@ -1460,12 +1497,22 @@ (define_expand "movhf"
     DONE;
})
+(define_insn "*movhf_hardfloat"
+  [(set (match_operand:HF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*r,  *r,*r,*m")
+ (match_operand:HF 1 "move_operand"         " f,G,m,f,G,*r,*f,*G*r,*m,*r"))]
+  "TARGET_ZFHMIN
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
+  { return riscv_output_move (operands[0], operands[1]); }
+  [(set_attr "move_type" "fmove,mtc,fpload,fpstore,store,mtc,mfc,move,load,store")
+   (set_attr "mode" "HF")])
(define_insn "*movhf_softfloat"
   [(set (match_operand:HF 0 "nonimmediate_operand" "=f, r,r,m,*f,*r")
(match_operand:HF 1 "move_operand"         " f,Gr,m,r,*r,*f"))]
-  "(register_operand (operands[0], HFmode)
-    || reg_or_0_operand (operands[1], HFmode))"
+  "!TARGET_ZFHMIN
+   && (register_operand (operands[0], HFmode)
+       || reg_or_0_operand (operands[1], HFmode))"
   { return riscv_output_move (operands[0], operands[1]); }
   [(set_attr "move_type" "fmove,move,load,store,mtc,mfc")
    (set_attr "mode" "HF")])
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 9e9fe6d8ccd..fbca91b956c 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -212,6 +212,9 @@ int riscv_zvl_flags
TargetVariable
int riscv_zicmo_subext
+TargetVariable
+int riscv_zf_subext
+
Enum
Name(isa_spec_class) Type(enum riscv_isa_spec_class)
Supported ISA specs (for use with the -misa-spec= option):
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c
new file mode 100644
index 00000000000..98908dccbb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-times "fmv.h" 1 } } */
+    return b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c
new file mode 100644
index 00000000000..58bfa6b4198
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-2.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-times "fadd.h" 1 } } */
+    return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c
new file mode 100644
index 00000000000..128b4e53f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfh-3.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfh -mabi=lp64f -O" } */
+
+int foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-times "fgt.h" 1 } } */
+    return a > b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c
new file mode 100644
index 00000000000..631a049f52f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-not "fmv.h" } } */
+    /* { dg-final { scan-assembler-times "fmv.s" 1 } } */
+    return b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c
new file mode 100644
index 00000000000..06c85eb797d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-2.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+_Float16 foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-not "fadd.h" } } */
+    /* { dg-final { scan-assembler-times "fadd.s" 1 } } */
+    return a + b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c
new file mode 100644
index 00000000000..28960d60245
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/_Float16-zfhmin-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64if_zfhmin -mabi=lp64f -O" } */
+
+int foo1 (_Float16 a, _Float16 b)
+{
+    /* { dg-final { scan-assembler-not "fgt.h" } } */
+    /* { dg-final { scan-assembler-times "fgt.s" 1 } } */
+    return a > b;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-16.c b/gcc/testsuite/gcc.target/riscv/arch-16.c
new file mode 100644
index 00000000000..14b40ae9a5a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-16.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gcv_zfh -mabi=ilp32 -mcmodel=medlow" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-17.c b/gcc/testsuite/gcc.target/riscv/arch-17.c
new file mode 100644
index 00000000000..3d3275e44a5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-17.c
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv32gcv_zfhmin -mabi=ilp32 -mcmodel=medlow" } */
+int foo()
+{
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-21.c b/gcc/testsuite/gcc.target/riscv/predef-21.c
new file mode 100644
index 00000000000..a171b3b83af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-21.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64i_zfh -mabi=lp64f -mcmodel=medlow -misa-spec=20191213" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 64
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i)
+#error "__riscv_i"
+#endif
+
+#if defined(__riscv_c)
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if defined(__riscv_a)
+#error "__riscv_a"
+#endif
+
+#if defined(__riscv_m)
+#error "__riscv_m"
+#endif
+
+#if !defined(__riscv_f)
+#error "__riscv_f"
+#endif
+
+#if defined(__riscv_d)
+#error "__riscv_d"
+#endif
+
+#if defined(__riscv_v)
+#error "__riscv_v"
+#endif
+
+#if !defined(__riscv_zfh)
+#error "__riscv_zfh"
+#endif
+
+#if !defined(__riscv_zfhmin)
+#error "__riscv_zfhmin"
+#endif
+
+#if !defined(__riscv_zicsr)
+#error "__riscv_zicsr"
+#endif
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/predef-22.c b/gcc/testsuite/gcc.target/riscv/predef-22.c
new file mode 100644
index 00000000000..ad1896573ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/predef-22.c
@@ -0,0 +1,59 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64i_zfhmin -mabi=lp64f -mcmodel=medlow -misa-spec=20191213" } */
+
+int main () {
+
+#ifndef __riscv_arch_test
+#error "__riscv_arch_test"
+#endif
+
+#if __riscv_xlen != 64
+#error "__riscv_xlen"
+#endif
+
+#if !defined(__riscv_i)
+#error "__riscv_i"
+#endif
+
+#if defined(__riscv_c)
+#error "__riscv_c"
+#endif
+
+#if defined(__riscv_e)
+#error "__riscv_e"
+#endif
+
+#if defined(__riscv_a)
+#error "__riscv_a"
+#endif
+
+#if defined(__riscv_m)
+#error "__riscv_m"
+#endif
+
+#if !defined(__riscv_f)
+#error "__riscv_f"
+#endif
+
+#if defined(__riscv_d)
+#error "__riscv_d"
+#endif
+
+#if defined(__riscv_v)
+#error "__riscv_v"
+#endif
+
+#if defined(__riscv_zfh)
+#error "__riscv_zfh"
+#endif
+
+#if !defined(__riscv_zfhmin)
+#error "__riscv_zfhmin"
+#endif
+
+#if !defined(__riscv_zicsr)
+#error "__riscv_zicsr"
+#endif
+
+  return 0;
+}
-- 
2.37.1
 
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] RISC-V: Support _Float16 type.
  2022-08-10 15:44 [PATCH v2 1/2] RISC-V: Support _Float16 type Kito Cheng
  2022-08-10 15:44 ` [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension Kito Cheng
@ 2022-12-05 13:05 ` Maciej W. Rozycki
  2022-12-07 14:15   ` Kito Cheng
  1 sibling, 1 reply; 5+ messages in thread
From: Maciej W. Rozycki @ 2022-12-05 13:05 UTC (permalink / raw)
  To: Kito Cheng
  Cc: gcc-patches, kito.cheng, Jim Wilson, Palmer Dabbelt, andrew,
	juzhe.zhong, joseph

Hi Kito,

 I came across this issue while inspecting code and I have been wondering 
what the reason was to downgrade current FMV.X.W and FMW.W.X instructions 
to their older FMV.S.W and FMV.W.S variants here:

On Wed, 10 Aug 2022, Kito Cheng wrote:

> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 5a0adffb5ce..47e6110767c 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -2308,10 +2310,19 @@ riscv_output_move (rtx dest, rtx src)
>    if (dest_code == REG && GP_REG_P (REGNO (dest)))
>      {
>        if (src_code == REG && FP_REG_P (REGNO (src)))
> -	return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.w\t%0,%1";
> +	switch (width)
> +	  {
> +	  case 2:
> +	    /* Using fmv.x.s + sign-extend to emulate fmv.x.h.  */
> +	    return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16";
> +	  case 4:
> +	    return "fmv.x.s\t%0,%1";
> +	  case 8:
> +	    return "fmv.x.d\t%0,%1";
> +	  }

and here:

> @@ -2353,18 +2364,24 @@ riscv_output_move (rtx dest, rtx src)
>  	    return "mv\t%0,%z1";
>  
>  	  if (FP_REG_P (REGNO (dest)))
> -	    {
> -	      if (!dbl_p)
> -		return "fmv.w.x\t%0,%z1";
> -	      if (TARGET_64BIT)
> -		return "fmv.d.x\t%0,%z1";
> -	      /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */
> -	      gcc_assert (src == CONST0_RTX (mode));
> -	      return "fcvt.d.w\t%0,x0";
> -	    }
> +	    switch (width)
> +	      {
> +	      case 2:
> +		/* High 16 bits should be all-1, otherwise HW will treated
> +		   as a n-bit canonical NaN, but isn't matter for softfloat.  */
> +		return "fmv.s.x\t%0,%1";
> +	      case 4:
> +		return "fmv.s.x\t%0,%z1";
> +	      case 8:
> +		if (TARGET_64BIT)
> +		  return "fmv.d.x\t%0,%z1";
> +		/* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */

(Incorrect comment formatting here as well.)

> +		gcc_assert (src == CONST0_RTX (mode));
> +		return "fcvt.d.w\t%0,x0";
> +	      }

Was it intentional or just an oversight in review?  If intentional, I'd 
expect such a change to happen on its own rather than sneaked in with a 
large functional update.

  Maciej

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] RISC-V: Support _Float16 type.
  2022-12-05 13:05 ` [PATCH v2 1/2] RISC-V: Support _Float16 type Maciej W. Rozycki
@ 2022-12-07 14:15   ` Kito Cheng
  0 siblings, 0 replies; 5+ messages in thread
From: Kito Cheng @ 2022-12-07 14:15 UTC (permalink / raw)
  To: Maciej W. Rozycki
  Cc: Jim Wilson, Kito Cheng, Palmer Dabbelt, andrew, gcc-patches,
	joseph, juzhe.zhong

[-- Attachment #1: Type: text/plain, Size: 2763 bytes --]

Hi Maciej:

It’s not intentionally, I suspect that is because I port from our internal
old gcc branch, will send patch to fix that later, thanks for catching this!

Maciej W. Rozycki <macro@embecosm.com>於 2022年12月5日 週一,21:05寫道:

> Hi Kito,
>
>  I came across this issue while inspecting code and I have been wondering
> what the reason was to downgrade current FMV.X.W and FMW.W.X instructions
> to their older FMV.S.W and FMV.W.S variants here:
>
> On Wed, 10 Aug 2022, Kito Cheng wrote:
>
> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> > index 5a0adffb5ce..47e6110767c 100644
> > --- a/gcc/config/riscv/riscv.cc
> > +++ b/gcc/config/riscv/riscv.cc
> > @@ -2308,10 +2310,19 @@ riscv_output_move (rtx dest, rtx src)
> >    if (dest_code == REG && GP_REG_P (REGNO (dest)))
> >      {
> >        if (src_code == REG && FP_REG_P (REGNO (src)))
> > -     return dbl_p ? "fmv.x.d\t%0,%1" : "fmv.x.w\t%0,%1";
> > +     switch (width)
> > +       {
> > +       case 2:
> > +         /* Using fmv.x.s + sign-extend to emulate fmv.x.h.  */
> > +         return "fmv.x.s\t%0,%1;slli\t%0,%0,16;srai\t%0,%0,16";
> > +       case 4:
> > +         return "fmv.x.s\t%0,%1";
> > +       case 8:
> > +         return "fmv.x.d\t%0,%1";
> > +       }
>
> and here:
>
> > @@ -2353,18 +2364,24 @@ riscv_output_move (rtx dest, rtx src)
> >           return "mv\t%0,%z1";
> >
> >         if (FP_REG_P (REGNO (dest)))
> > -         {
> > -           if (!dbl_p)
> > -             return "fmv.w.x\t%0,%z1";
> > -           if (TARGET_64BIT)
> > -             return "fmv.d.x\t%0,%z1";
> > -           /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */
> > -           gcc_assert (src == CONST0_RTX (mode));
> > -           return "fcvt.d.w\t%0,x0";
> > -         }
> > +         switch (width)
> > +           {
> > +           case 2:
> > +             /* High 16 bits should be all-1, otherwise HW will treated
> > +                as a n-bit canonical NaN, but isn't matter for
> softfloat.  */
> > +             return "fmv.s.x\t%0,%1";
> > +           case 4:
> > +             return "fmv.s.x\t%0,%z1";
> > +           case 8:
> > +             if (TARGET_64BIT)
> > +               return "fmv.d.x\t%0,%z1";
> > +             /* in RV32, we can emulate fmv.d.x %0, x0 using fcvt.d.w */
>
> (Incorrect comment formatting here as well.)
>
> > +             gcc_assert (src == CONST0_RTX (mode));
> > +             return "fcvt.d.w\t%0,x0";
> > +           }
>
> Was it intentional or just an oversight in review?  If intentional, I'd
> expect such a change to happen on its own rather than sneaked in with a
> large functional update.
>
>   Maciej
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-12-07 14:15 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-10 15:44 [PATCH v2 1/2] RISC-V: Support _Float16 type Kito Cheng
2022-08-10 15:44 ` [PATCH v2 2/2] RISC-V: Support zfh and zfhmin extension Kito Cheng
2022-08-10 23:19   ` 钟居哲
2022-12-05 13:05 ` [PATCH v2 1/2] RISC-V: Support _Float16 type Maciej W. Rozycki
2022-12-07 14:15   ` Kito Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).