public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3]  LoongArch:Implement 128-bit floating point functions in gcc.
@ 2023-08-15 10:39 chenxiaolong
  2023-08-15 10:48 ` Xi Ruoyao
  2023-08-15 20:03 ` Joseph Myers
  0 siblings, 2 replies; 13+ messages in thread
From: chenxiaolong @ 2023-08-15 10:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: xry111, i, xuchenghua, chenglulu, chenxiaolong

	In the implementation process, the "q" suffix function is
        Re-register and associate the "__float128" type with the
        "long double" type so that the compiler can handle the
        corresponding function correctly. The functions implemented
        include __builtin_{huge_valq infq, fabsq, copysignq, nanq,nansq}.
        On the LoongArch architecture, __builtin_{fabsq,copysignq} can
        be implemented with the instruction "bstrins.d", so that its
        optimization effect reaches the optimal value.

gcc/ChangeLog:

	* config/loongarch/loongarch-builtins.cc (DEF_LARCH_FTYPE):
	(enum loongarch_builtin_type):Increases the type of the function.
	(FLOAT_BUILTIN_HIQ):__builtin_{huge_valq,infq}.
	(FLOAT_BUILTIN_FCQ):__builtin_{fabsq,copysignq}.
	(FLOAT_BUILTIN_NNQ):__builtin_{nanq,nansq}.
	(loongarch_init_builtins):
	(loongarch_fold_builtin):
	(loongarch_expand_builtin):
	* config/loongarch/loongarch-protos.h (loongarch_fold_builtin):
	(loongarch_c_mode_for_suffix):Add the declaration of the function.
	* config/loongarch/loongarch.cc (loongarch_c_mode_for_suffix):Add
        the definition of the function.
	(TARGET_FOLD_BUILTIN):
	(TARGET_C_MODE_FOR_SUFFIX):
	* config/loongarch/loongarch.md (infq):Add an instruction template
        to the machine description file to generate information such as
        the icode used by the function and the constructor.
	(<mathq_pattern>):
	(fabsq):
	(copysignq):

libgcc/ChangeLog:

	* config/loongarch/t-softfp-tf:
	* config/loongarch/tf-signs.c: New file.
---
 gcc/config/loongarch/loongarch-builtins.cc | 168 ++++++++++++++++++++-
 gcc/config/loongarch/loongarch-protos.h    |   2 +
 gcc/config/loongarch/loongarch.cc          |  14 ++
 gcc/config/loongarch/loongarch.md          |  69 +++++++++
 libgcc/config/loongarch/t-softfp-tf        |   3 +
 libgcc/config/loongarch/tf-signs.c         |  59 ++++++++
 6 files changed, 313 insertions(+), 2 deletions(-)
 create mode 100644 libgcc/config/loongarch/tf-signs.c

diff --git a/gcc/config/loongarch/loongarch-builtins.cc b/gcc/config/loongarch/loongarch-builtins.cc
index b929f224dfa..2fb0fde0e3f 100644
--- a/gcc/config/loongarch/loongarch-builtins.cc
+++ b/gcc/config/loongarch/loongarch-builtins.cc
@@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "expr.h"
 #include "langhooks.h"
+#include "calls.h"
+#include "explow.h"
 
 /* Macros to create an enumeration identifier for a function prototype.  */
 #define LARCH_FTYPE_NAME1(A, B) LARCH_##A##_FTYPE_##B
@@ -48,9 +50,18 @@ enum loongarch_function_type
 #define DEF_LARCH_FTYPE(NARGS, LIST) LARCH_FTYPE_NAME##NARGS LIST,
 #include "config/loongarch/loongarch-ftypes.def"
 #undef DEF_LARCH_FTYPE
+  LARCH_BUILTIN_HUGE_VALQ,
+  LARCH_BUILTIN_INFQ,
+  LARCH_BUILTIN_FABSQ,
+  LARCH_BUILTIN_COPYSIGNQ,
+  LARCH_BUILTIN_NANQ,
+  LARCH_BUILTIN_NANSQ,
   LARCH_MAX_FTYPE_MAX
 };
 
+/* Count the number of functions with "q" as the suffix.  */
+const int MATHQ_NUMS =	(int)LARCH_MAX_FTYPE_MAX - (int)LARCH_BUILTIN_HUGE_VALQ;
+
 /* Specifies how a built-in function should be converted into rtl.  */
 enum loongarch_builtin_type
 {
@@ -63,6 +74,15 @@ enum loongarch_builtin_type
      value and the arguments are mapped to operands 0 and above.  */
   LARCH_BUILTIN_DIRECT_NO_TARGET,
 
+ /* The function corresponds to  __builtin_{huge_valq,infq}.  */
+  LARCH_BUILTIN_HIQ_DIRECT,
+
+ /* The function corresponds to  __builtin_{fabsq,copysignq}.  */
+  LARCH_BUILTIN_FCQ_DIRECT,
+
+  /* Define the type of the __builtin_{nanq,nansq} function.  */
+  LARCH_BUILTIN_NNQ_DIRECT
+
 };
 
 /* Declare an availability predicate for built-in functions that require
@@ -136,6 +156,24 @@ AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI)
   LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT_NO_TARGET, \
 		 FUNCTION_TYPE, AVAIL)
 
+/* Define an float to do funciton {huge_valq,infq}.  */
+#define FLOAT_BUILTIN_HIQ (INSN, FUNCTION_TYPE)	  \
+    { CODE_FOR_ ## INSN,			  \
+    "__builtin_" #INSN,  LARCH_BUILTIN_HIQ_DIRECT,    \
+    FUNCTION_TYPE, loongarch_builtin_avail_default }
+
+/* Define an float to do funciton {fabsq,copysignq}.  */
+#define FLOAT_BUILTIN_FCQ (INSN, FUNCTION_TYPE)	  \
+    { CODE_FOR_ ## INSN,			  \
+    "__builtin_" #INSN,  LARCH_BUILTIN_FCQ_DIRECT,    \
+    FUNCTION_TYPE, loongarch_builtin_avail_default }
+
+/* Define an float to do funciton {nanq,nansq}.  */
+#define FLOAT_BUILTIN_NNQ (INSN, FUNCTION_TYPE)      \
+    { CODE_FOR_ ## INSN,				\
+    "__builtin_" #INSN,  LARCH_BUILTIN_NNQ_DIRECT,	  \
+    FUNCTION_TYPE, loongarch_builtin_avail_default }
+
 static const struct loongarch_builtin_description loongarch_builtins[] = {
 #define LARCH_MOVFCSR2GR 0
   DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float),
@@ -183,6 +221,14 @@ static const struct loongarch_builtin_description loongarch_builtins[] = {
   DIRECT_NO_TARGET_BUILTIN (asrtgt_d, LARCH_VOID_FTYPE_DI_DI, default),
   DIRECT_NO_TARGET_BUILTIN (syscall, LARCH_VOID_FTYPE_USI, default),
   DIRECT_NO_TARGET_BUILTIN (break, LARCH_VOID_FTYPE_USI, default),
+
+  FLOAT_BUILTIN_HIQ (huge_valq, LARCH_BUILTIN_HUGE_VALQ),
+  FLOAT_BUILTIN_HIQ (infq, LARCH_BUILTIN_INFQ),
+  FLOAT_BUILTIN_FCQ (fabsq, LARCH_BUILTIN_FABSQ),
+  FLOAT_BUILTIN_FCQ (copysignq, LARCH_BUILTIN_COPYSIGNQ),
+  FLOAT_BUILTIN_NNQ (nanq, LARCH_BUILTIN_NANQ),
+  FLOAT_BUILTIN_NNQ (nansq, LARCH_BUILTIN_NANSQ),
+
 };
 
 /* Index I is the function declaration for loongarch_builtins[I], or null if
@@ -255,10 +301,13 @@ loongarch_init_builtins (void)
   const struct loongarch_builtin_description *d;
   unsigned int i;
   tree type;
+  tree const_string_type
+     =build_pointer_type (build_qualified_type (char_type_node,
+						TYPE_QUAL_CONST));
 
   /* Iterate through all of the bdesc arrays, initializing all of the
      builtin functions.  */
-  for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++)
+  for (i = 0; i < ARRAY_SIZE (loongarch_builtins)-MATHQ_NUMS; i++)
     {
       d = &loongarch_builtins[i];
       if (d->avail ())
@@ -270,6 +319,63 @@ loongarch_init_builtins (void)
 	  loongarch_get_builtin_decl_index[d->icode] = i;
 	}
     }
+   /* Register the type long_double_type_node as a built-in type and
+     give it an alias "__float128".  */
+  (*lang_hooks.types.register_builtin_type) (long_double_type_node,
+					    "__float128");
+
+      type = build_function_type_list (long_double_type_node, NULL_TREE);
+      d = &loongarch_builtins[i];
+      loongarch_builtin_decls[i]
+	=add_builtin_function ("__builtin_huge_valq", type,
+			     i,	BUILT_IN_MD, NULL, NULL_TREE);
+      loongarch_get_builtin_decl_index[d->icode]=i++;
+
+      type = build_function_type_list (long_double_type_node, NULL_TREE);
+      d = &loongarch_builtins[i];
+      loongarch_builtin_decls[i]
+	=add_builtin_function ("__builtin_infq",  type,
+				i,  BUILT_IN_MD,  NULL,	NULL_TREE);
+      loongarch_get_builtin_decl_index[d->icode]=i++;
+
+      type = build_function_type_list (long_double_type_node,
+				       long_double_type_node,
+				       NULL_TREE);
+      d = &loongarch_builtins[i];
+      loongarch_builtin_decls[i]
+	=add_builtin_function ("__builtin_fabsq", type,
+			       i,  BUILT_IN_MD,  NULL,  NULL_TREE);
+      TREE_READONLY (loongarch_builtin_decls[i]) =1;
+      loongarch_get_builtin_decl_index[d->icode]=i++;
+
+      type = build_function_type_list (long_double_type_node,
+				       long_double_type_node,
+				       long_double_type_node,
+				       NULL_TREE);
+      d = &loongarch_builtins[i];
+      loongarch_builtin_decls[i]
+	=add_builtin_function ("__builtin_copysignq", type,
+			       i,  BUILT_IN_MD,  NULL,  NULL_TREE);
+      TREE_READONLY (loongarch_builtin_decls[i]) =1;
+      loongarch_get_builtin_decl_index[d->icode]=i++;
+
+      type=build_function_type_list (long_double_type_node,
+				     const_string_type,
+				     NULL_TREE);
+      d = &loongarch_builtins[i];
+      loongarch_builtin_decls[i]
+	=add_builtin_function ("__builtin_nanq", type,
+			       i, BUILT_IN_MD,  "__nanq", NULL_TREE);
+      TREE_READONLY (loongarch_builtin_decls[i]) =1;
+      loongarch_get_builtin_decl_index[d->icode]=i++;
+
+      d = &loongarch_builtins[i];
+      loongarch_builtin_decls[i]
+	=add_builtin_function ("__builtin_nansq", type,
+			       i, BUILT_IN_MD,  "__nansq",  NULL_TREE);
+      TREE_READONLY (loongarch_builtin_decls[i]) =1;
+      loongarch_get_builtin_decl_index[d->icode]=i;
+
 }
 
 /* Implement TARGET_BUILTIN_DECL.  */
@@ -282,6 +388,42 @@ loongarch_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
   return loongarch_builtin_decls[code];
 }
 
+tree
+loongarch_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
+			tree *args, bool ignore ATTRIBUTE_UNUSED)
+{
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
+    {
+      enum loongarch_function_type fn_code
+	 = (enum loongarch_function_type) DECL_MD_FUNCTION_CODE (fndecl);
+      switch (fn_code)
+	{
+	  case LARCH_BUILTIN_NANQ:
+	  case LARCH_BUILTIN_NANSQ:
+	    {
+	      tree type = TREE_TYPE (TREE_TYPE (fndecl));
+	      const char *str = c_getstr (*args);
+	      int quiet = fn_code == LARCH_BUILTIN_NANQ;
+	      REAL_VALUE_TYPE real;
+
+	      if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
+		return build_real (type, real);
+	      return NULL_TREE;
+	    }
+
+	  default:
+	    break;
+	}
+      }
+
+#ifdef SUBTARGET_FOLD_BUILTIN
+  return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore);
+#endif
+
+  return NULL_TREE;
+}
+
+
 /* Take argument ARGNO from EXP's argument list and convert it into
    an expand operand.  Store the operand in *OP.  */
 
@@ -362,11 +504,33 @@ loongarch_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
   switch (d->builtin_type)
     {
     case LARCH_BUILTIN_DIRECT:
+    case LARCH_BUILTIN_FCQ_DIRECT:
       return loongarch_expand_builtin_direct (d->icode, target, exp, true);
 
     case LARCH_BUILTIN_DIRECT_NO_TARGET:
       return loongarch_expand_builtin_direct (d->icode, target, exp, false);
-    }
+
+    case LARCH_BUILTIN_NNQ_DIRECT:
+      return expand_call ( exp ,target , ignore);
+
+    case LARCH_BUILTIN_HIQ_DIRECT:
+      {
+	machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
+	REAL_VALUE_TYPE inf;
+	rtx tmp;
+
+	real_inf (&inf);
+	tmp = const_double_from_real_value (inf, target_mode);
+
+	tmp=validize_mem (force_const_mem (target_mode,tmp));
+
+	if (target ==0)
+	    target =gen_reg_rtx (target_mode);
+	emit_move_insn (target,tmp);
+
+	return target;
+      }
+  }
   gcc_unreachable ();
 }
 
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
index b71b188507a..35fc2ad7def 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -175,11 +175,13 @@ extern void loongarch_register_frame_header_opt (void);
 /* Routines implemented in loongarch-c.c.  */
 void loongarch_cpu_cpp_builtins (cpp_reader *);
 
+extern tree loongarch_fold_builtin (tree, int, tree*, bool);
 extern void loongarch_init_builtins (void);
 extern void loongarch_atomic_assign_expand_fenv (tree *, tree *, tree *);
 extern tree loongarch_builtin_decl (unsigned int, bool);
 extern rtx loongarch_expand_builtin (tree, rtx, rtx subtarget ATTRIBUTE_UNUSED,
 				     machine_mode, int);
 extern tree loongarch_build_builtin_va_list (void);
+extern machine_mode loongarch_c_mode_for_suffix (char suffix);
 
 #endif /* ! GCC_LOONGARCH_PROTOS_H */
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 86d58784113..7a8358c9630 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -6790,6 +6790,16 @@ loongarch_set_handled_components (sbitmap components)
 	cfun->machine->reg_is_wrapped_separately[regno] = true;
 }
 
+/* Target hook for c_mode_for_suffix.  */
+machine_mode
+loongarch_c_mode_for_suffix (char suffix)
+{
+  if (suffix == 'q')
+    return TFmode;
+
+  return VOIDmode;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -6901,6 +6911,10 @@ loongarch_set_handled_components (sbitmap components)
 #define TARGET_BUILTIN_DECL loongarch_builtin_decl
 #undef TARGET_EXPAND_BUILTIN
 #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin
+#undef TARGET_FOLD_BUILTIN
+#define TARGET_FOLD_BUILTIN loongarch_fold_builtin
+#undef TARGET_C_MODE_FOR_SUFFIX
+#define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix
 
 /* The generic ELF target does not always have TLS support.  */
 #ifdef HAVE_AS_TLS
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index b37e070660f..9fe3faf8b92 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -44,6 +44,13 @@ (define_c_enum "unspec" [
   UNSPEC_FSCALEB
   UNSPEC_FLOGB
 
+  UNSPEC_INFQ
+  UNSPEC_HUGE_VALQ
+  UNSPEC_FABSQ
+  UNSPEC_COPYSIGNQ
+  UNSPEC_NANQ
+  UNSPEC_NANSQ
+
   ;; Override return address for exception handling.
   UNSPEC_EH_RETURN
 
@@ -563,6 +570,15 @@ (define_int_attr bytepick_imm [(8 "1")
 				 (48 "6")
 				 (56 "7")])
 
+;; mathq function
+(define_int_iterator MATHQ[UNSPEC_INFQ	 UNSPEC_HUGE_VALQ
+			    UNSPEC_NANQ UNSPEC_NANSQ])
+(define_int_attr mathq_pattern[(UNSPEC_INFQ "infq")
+				(UNSPEC_HUGE_VALQ "huge_valq")
+				(UNSPEC_NANQ "nanq")
+				(UNSPEC_NANSQ "nansq")]
+)
+
 ;;
 ;;  ....................
 ;;
@@ -2008,6 +2024,59 @@ (define_insn "movfcc"
   ""
   "movgr2cf\t%0,$r0")
 
+;; Implements functions with a "q" suffix
+
+(define_insn "<mathq_pattern>"
+  [(unspec:SI[(const_int 0)] MATHQ)]
+  ""
+  "")
+
+;;Implement __builtin_fabsq function.
+
+(define_insn_and_split   "fabsq"
+  [(set (match_operand:TF  0 "register_operand" "=r")
+	(unspec:TF[(match_operand:TF 1 "register_operand" "rG")]
+		    UNSPEC_FABSQ))]
+  ""
+  "#"
+  "reload_completed"
+[(set (zero_extract:DI (match_operand:DI 0 "register_operand")
+			(match_operand:SI 3 "const_int_operand")
+			(match_operand:SI 4 "const_int_operand"))
+      (match_operand:DI 2 "const_int_operand"))]
+{
+	operands[0] = gen_rtx_REG (Pmode, REGNO (operands[0])+1);
+	operands[2] = GEN_INT (0);
+	operands[3] = GEN_INT (1);
+	operands[4] = GEN_INT (63);
+}
+)
+
+;;Implement __builtin_copysignq function.
+
+(define_insn_and_split  "copysignq"
+  [(set (match_operand:TF  0 "register_operand" "=r")
+	(unspec:TF[(match_operand:TF 1 "register_operand" "rG")
+		    (match_operand:TF 2 "register_operand" "rG")]
+		      UNSPEC_COPYSIGNQ))]
+ ""
+ "#"
+ "reload_completed"
+  [(set (match_operand:DI 2 "register_operand")
+	(lshiftrt :DI (match_operand:DI 2 "register_operand")
+	(match_operand:SI 4 "arith_operand")))
+   (set (zero_extract:DI (match_operand:DI 0 "register_operand")
+			  (match_operand:SI 3 "const_int_operand")
+			  (match_operand:SI 4 "const_int_operand"))
+	(match_operand:DI 2 "register_operand"))]
+{
+   operands[0] = gen_rtx_REG (Pmode,REGNO (operands[0])+1);
+   operands[2] = gen_rtx_REG (Pmode,REGNO (operands[2])+1);
+   operands[3] = GEN_INT (1);
+   operands[4] = GEN_INT (63);
+}
+)
+
 ;; Conditional move instructions.
 
 (define_insn "*sel<code><GPR:mode>_using_<GPR2:mode>"
diff --git a/libgcc/config/loongarch/t-softfp-tf b/libgcc/config/loongarch/t-softfp-tf
index 306677b1255..0e7c2b4cabe 100644
--- a/libgcc/config/loongarch/t-softfp-tf
+++ b/libgcc/config/loongarch/t-softfp-tf
@@ -1,3 +1,6 @@
 softfp_float_modes += tf
 softfp_extensions += sftf dftf
 softfp_truncations += tfsf tfdf
+#Used to implement a special 128-bit function with a q suffix
+LIB2ADD += $(srcdir)/config/loongarch/tf-signs.c
+
diff --git a/libgcc/config/loongarch/tf-signs.c b/libgcc/config/loongarch/tf-signs.c
new file mode 100644
index 00000000000..68db1729372
--- /dev/null
+++ b/libgcc/config/loongarch/tf-signs.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2008-2023 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+union _FP_UNION_Q
+{
+   __float128 flt;
+   struct
+   {
+      unsigned long frac0 : 64;
+      unsigned long frac1 : 48;
+      unsigned exp : 15;
+      unsigned sign : 1;
+   } bits __attribute__((packed));
+};
+
+__float128 __nanq (const char *str);
+__float128 __nansq (const char *str);
+
+__float128 __nanq (const char * str)
+{
+  union _FP_UNION_Q nan;
+  nan.bits.frac0 = 0;
+  nan.bits.frac1 = 0;
+  nan.bits.exp = 0x7FFF;
+  nan.bits.sign = 0;
+
+  return nan.flt;
+}
+__float128 __nansq (const char *str)
+{
+  union _FP_UNION_Q nan;
+  nan.bits.frac0 = 0xFFFFFFFFFFFFFFFFUL;
+  nan.bits.frac1 = 0x0000FFFFFFFFFFFFUL;
+  nan.bits.exp = 0x7FFF;
+  nan.bits.sign = 0;
+
+  return nan.flt;
+}
+
-- 
2.20.1


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

* Re: [PATCH v3]  LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-15 10:39 [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc chenxiaolong
@ 2023-08-15 10:48 ` Xi Ruoyao
  2023-08-17  6:56   ` chenxiaolong
  2023-08-15 20:03 ` Joseph Myers
  1 sibling, 1 reply; 13+ messages in thread
From: Xi Ruoyao @ 2023-08-15 10:48 UTC (permalink / raw)
  To: chenxiaolong, gcc-patches; +Cc: i, xuchenghua, chenglulu

Please fix code style (this is the third time I say it and I'm really
frustrated now).  GCC is a project, it's not a student homework so style
matters.  And it's not so difficult to fix the style: for a new file you
can use "clang-format --style GNU -i filename.c" to do the work
automatically.

On Tue, 2023-08-15 at 18:39 +0800, chenxiaolong wrote:
>         In the implementation process, the "q" suffix function is
>         Re-register and associate the "__float128" type with the
>         "long double" type so that the compiler can handle the
>         corresponding function correctly. The functions implemented
>         include __builtin_{huge_valq infq, fabsq, copysignq, nanq,nansq}.
>         On the LoongArch architecture, __builtin_{fabsq,copysignq} can
>         be implemented with the instruction "bstrins.d", so that its
>         optimization effect reaches the optimal value.
> 
> gcc/ChangeLog:
> 
>         * config/loongarch/loongarch-builtins.cc (DEF_LARCH_FTYPE):
>         (enum loongarch_builtin_type):Increases the type of the function.
>         (FLOAT_BUILTIN_HIQ):__builtin_{huge_valq,infq}.
>         (FLOAT_BUILTIN_FCQ):__builtin_{fabsq,copysignq}.
>         (FLOAT_BUILTIN_NNQ):__builtin_{nanq,nansq}.
>         (loongarch_init_builtins):
>         (loongarch_fold_builtin):
>         (loongarch_expand_builtin):
>         * config/loongarch/loongarch-protos.h (loongarch_fold_builtin):
>         (loongarch_c_mode_for_suffix):Add the declaration of the function.
>         * config/loongarch/loongarch.cc (loongarch_c_mode_for_suffix):Add
>         the definition of the function.
>         (TARGET_FOLD_BUILTIN):
>         (TARGET_C_MODE_FOR_SUFFIX):
>         * config/loongarch/loongarch.md (infq):Add an instruction template
>         to the machine description file to generate information such as
>         the icode used by the function and the constructor.
>         (<mathq_pattern>):
>         (fabsq):
>         (copysignq):
> 
> libgcc/ChangeLog:
> 
>         * config/loongarch/t-softfp-tf:
>         * config/loongarch/tf-signs.c: New file.
> ---
>  gcc/config/loongarch/loongarch-builtins.cc | 168 ++++++++++++++++++++-
>  gcc/config/loongarch/loongarch-protos.h    |   2 +
>  gcc/config/loongarch/loongarch.cc          |  14 ++
>  gcc/config/loongarch/loongarch.md          |  69 +++++++++
>  libgcc/config/loongarch/t-softfp-tf        |   3 +
>  libgcc/config/loongarch/tf-signs.c         |  59 ++++++++
>  6 files changed, 313 insertions(+), 2 deletions(-)
>  create mode 100644 libgcc/config/loongarch/tf-signs.c
> 
> diff --git a/gcc/config/loongarch/loongarch-builtins.cc b/gcc/config/loongarch/loongarch-builtins.cc
> index b929f224dfa..2fb0fde0e3f 100644
> --- a/gcc/config/loongarch/loongarch-builtins.cc
> +++ b/gcc/config/loongarch/loongarch-builtins.cc
> @@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.  If not see
>  #include "fold-const.h"
>  #include "expr.h"
>  #include "langhooks.h"
> +#include "calls.h"
> +#include "explow.h"
>  
>  /* Macros to create an enumeration identifier for a function prototype.  */
>  #define LARCH_FTYPE_NAME1(A, B) LARCH_##A##_FTYPE_##B
> @@ -48,9 +50,18 @@ enum loongarch_function_type
>  #define DEF_LARCH_FTYPE(NARGS, LIST) LARCH_FTYPE_NAME##NARGS LIST,
>  #include "config/loongarch/loongarch-ftypes.def"
>  #undef DEF_LARCH_FTYPE
> +  LARCH_BUILTIN_HUGE_VALQ,
> +  LARCH_BUILTIN_INFQ,
> +  LARCH_BUILTIN_FABSQ,
> +  LARCH_BUILTIN_COPYSIGNQ,
> +  LARCH_BUILTIN_NANQ,
> +  LARCH_BUILTIN_NANSQ,
>    LARCH_MAX_FTYPE_MAX
>  };
>  
> +/* Count the number of functions with "q" as the suffix.  */
> +const int MATHQ_NUMS = (int)LARCH_MAX_FTYPE_MAX - (int)LARCH_BUILTIN_HUGE_VALQ;
> +
>  /* Specifies how a built-in function should be converted into rtl.  */
>  enum loongarch_builtin_type
>  {
> @@ -63,6 +74,15 @@ enum loongarch_builtin_type
>       value and the arguments are mapped to operands 0 and above.  */
>    LARCH_BUILTIN_DIRECT_NO_TARGET,
>  
> + /* The function corresponds to  __builtin_{huge_valq,infq}.  */
> +  LARCH_BUILTIN_HIQ_DIRECT,
> +
> + /* The function corresponds to  __builtin_{fabsq,copysignq}.  */
> +  LARCH_BUILTIN_FCQ_DIRECT,
> +
> +  /* Define the type of the __builtin_{nanq,nansq} function.  */
> +  LARCH_BUILTIN_NNQ_DIRECT
> +
>  };
>  
>  /* Declare an availability predicate for built-in functions that require
> @@ -136,6 +156,24 @@ AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI)
>    LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT_NO_TARGET, \
>                  FUNCTION_TYPE, AVAIL)
>  
> +/* Define an float to do funciton {huge_valq,infq}.  */
> +#define FLOAT_BUILTIN_HIQ (INSN, FUNCTION_TYPE)          \
> +    { CODE_FOR_ ## INSN,                         \
> +    "__builtin_" #INSN,  LARCH_BUILTIN_HIQ_DIRECT,    \
> +    FUNCTION_TYPE, loongarch_builtin_avail_default }
> +
> +/* Define an float to do funciton {fabsq,copysignq}.  */
> +#define FLOAT_BUILTIN_FCQ (INSN, FUNCTION_TYPE)          \
> +    { CODE_FOR_ ## INSN,                         \
> +    "__builtin_" #INSN,  LARCH_BUILTIN_FCQ_DIRECT,    \
> +    FUNCTION_TYPE, loongarch_builtin_avail_default }
> +
> +/* Define an float to do funciton {nanq,nansq}.  */
> +#define FLOAT_BUILTIN_NNQ (INSN, FUNCTION_TYPE)      \
> +    { CODE_FOR_ ## INSN,                               \
> +    "__builtin_" #INSN,  LARCH_BUILTIN_NNQ_DIRECT,       \
> +    FUNCTION_TYPE, loongarch_builtin_avail_default }
> +
>  static const struct loongarch_builtin_description loongarch_builtins[] = {
>  #define LARCH_MOVFCSR2GR 0
>    DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float),
> @@ -183,6 +221,14 @@ static const struct loongarch_builtin_description loongarch_builtins[] = {
>    DIRECT_NO_TARGET_BUILTIN (asrtgt_d, LARCH_VOID_FTYPE_DI_DI, default),
>    DIRECT_NO_TARGET_BUILTIN (syscall, LARCH_VOID_FTYPE_USI, default),
>    DIRECT_NO_TARGET_BUILTIN (break, LARCH_VOID_FTYPE_USI, default),
> +
> +  FLOAT_BUILTIN_HIQ (huge_valq, LARCH_BUILTIN_HUGE_VALQ),
> +  FLOAT_BUILTIN_HIQ (infq, LARCH_BUILTIN_INFQ),
> +  FLOAT_BUILTIN_FCQ (fabsq, LARCH_BUILTIN_FABSQ),
> +  FLOAT_BUILTIN_FCQ (copysignq, LARCH_BUILTIN_COPYSIGNQ),
> +  FLOAT_BUILTIN_NNQ (nanq, LARCH_BUILTIN_NANQ),
> +  FLOAT_BUILTIN_NNQ (nansq, LARCH_BUILTIN_NANSQ),
> +
>  };
>  
>  /* Index I is the function declaration for loongarch_builtins[I], or null if
> @@ -255,10 +301,13 @@ loongarch_init_builtins (void)
>    const struct loongarch_builtin_description *d;
>    unsigned int i;
>    tree type;
> +  tree const_string_type
> +     =build_pointer_type (build_qualified_type (char_type_node,
> +                                               TYPE_QUAL_CONST));
>  
>    /* Iterate through all of the bdesc arrays, initializing all of the
>       builtin functions.  */
> -  for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++)
> +  for (i = 0; i < ARRAY_SIZE (loongarch_builtins)-MATHQ_NUMS; i++)
>      {
>        d = &loongarch_builtins[i];
>        if (d->avail ())
> @@ -270,6 +319,63 @@ loongarch_init_builtins (void)
>           loongarch_get_builtin_decl_index[d->icode] = i;
>         }
>      }
> +   /* Register the type long_double_type_node as a built-in type and
> +     give it an alias "__float128".  */
> +  (*lang_hooks.types.register_builtin_type) (long_double_type_node,
> +                                           "__float128");
> +
> +      type = build_function_type_list (long_double_type_node, NULL_TREE);
> +      d = &loongarch_builtins[i];
> +      loongarch_builtin_decls[i]
> +       =add_builtin_function ("__builtin_huge_valq", type,
> +                            i, BUILT_IN_MD, NULL, NULL_TREE);
> +      loongarch_get_builtin_decl_index[d->icode]=i++;
> +
> +      type = build_function_type_list (long_double_type_node, NULL_TREE);
> +      d = &loongarch_builtins[i];
> +      loongarch_builtin_decls[i]
> +       =add_builtin_function ("__builtin_infq",  type,
> +                               i,  BUILT_IN_MD,  NULL, NULL_TREE);
> +      loongarch_get_builtin_decl_index[d->icode]=i++;
> +
> +      type = build_function_type_list (long_double_type_node,
> +                                      long_double_type_node,
> +                                      NULL_TREE);
> +      d = &loongarch_builtins[i];
> +      loongarch_builtin_decls[i]
> +       =add_builtin_function ("__builtin_fabsq", type,
> +                              i,  BUILT_IN_MD,  NULL,  NULL_TREE);
> +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> +      loongarch_get_builtin_decl_index[d->icode]=i++;
> +
> +      type = build_function_type_list (long_double_type_node,
> +                                      long_double_type_node,
> +                                      long_double_type_node,
> +                                      NULL_TREE);
> +      d = &loongarch_builtins[i];
> +      loongarch_builtin_decls[i]
> +       =add_builtin_function ("__builtin_copysignq", type,
> +                              i,  BUILT_IN_MD,  NULL,  NULL_TREE);
> +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> +      loongarch_get_builtin_decl_index[d->icode]=i++;
> +
> +      type=build_function_type_list (long_double_type_node,
> +                                    const_string_type,
> +                                    NULL_TREE);
> +      d = &loongarch_builtins[i];
> +      loongarch_builtin_decls[i]
> +       =add_builtin_function ("__builtin_nanq", type,
> +                              i, BUILT_IN_MD,  "__nanq", NULL_TREE);
> +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> +      loongarch_get_builtin_decl_index[d->icode]=i++;
> +
> +      d = &loongarch_builtins[i];
> +      loongarch_builtin_decls[i]
> +       =add_builtin_function ("__builtin_nansq", type,
> +                              i, BUILT_IN_MD,  "__nansq",  NULL_TREE);
> +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> +      loongarch_get_builtin_decl_index[d->icode]=i;
> +
>  }
>  
>  /* Implement TARGET_BUILTIN_DECL.  */
> @@ -282,6 +388,42 @@ loongarch_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
>    return loongarch_builtin_decls[code];
>  }
>  
> +tree
> +loongarch_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
> +                       tree *args, bool ignore ATTRIBUTE_UNUSED)
> +{
> +  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
> +    {
> +      enum loongarch_function_type fn_code
> +        = (enum loongarch_function_type) DECL_MD_FUNCTION_CODE (fndecl);
> +      switch (fn_code)
> +       {
> +         case LARCH_BUILTIN_NANQ:
> +         case LARCH_BUILTIN_NANSQ:
> +           {
> +             tree type = TREE_TYPE (TREE_TYPE (fndecl));
> +             const char *str = c_getstr (*args);
> +             int quiet = fn_code == LARCH_BUILTIN_NANQ;
> +             REAL_VALUE_TYPE real;
> +
> +             if (str && real_nan (&real, str, quiet, TYPE_MODE (type)))
> +               return build_real (type, real);
> +             return NULL_TREE;
> +           }
> +
> +         default:
> +           break;
> +       }
> +      }
> +
> +#ifdef SUBTARGET_FOLD_BUILTIN
> +  return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore);
> +#endif
> +
> +  return NULL_TREE;
> +}
> +
> +
>  /* Take argument ARGNO from EXP's argument list and convert it into
>     an expand operand.  Store the operand in *OP.  */
>  
> @@ -362,11 +504,33 @@ loongarch_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
>    switch (d->builtin_type)
>      {
>      case LARCH_BUILTIN_DIRECT:
> +    case LARCH_BUILTIN_FCQ_DIRECT:
>        return loongarch_expand_builtin_direct (d->icode, target, exp, true);
>  
>      case LARCH_BUILTIN_DIRECT_NO_TARGET:
>        return loongarch_expand_builtin_direct (d->icode, target, exp, false);
> -    }
> +
> +    case LARCH_BUILTIN_NNQ_DIRECT:
> +      return expand_call ( exp ,target , ignore);
> +
> +    case LARCH_BUILTIN_HIQ_DIRECT:
> +      {
> +       machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
> +       REAL_VALUE_TYPE inf;
> +       rtx tmp;
> +
> +       real_inf (&inf);
> +       tmp = const_double_from_real_value (inf, target_mode);
> +
> +       tmp=validize_mem (force_const_mem (target_mode,tmp));
> +
> +       if (target ==0)
> +           target =gen_reg_rtx (target_mode);
> +       emit_move_insn (target,tmp);
> +
> +       return target;
> +      }
> +  }
>    gcc_unreachable ();
>  }
>  
> diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
> index b71b188507a..35fc2ad7def 100644
> --- a/gcc/config/loongarch/loongarch-protos.h
> +++ b/gcc/config/loongarch/loongarch-protos.h
> @@ -175,11 +175,13 @@ extern void loongarch_register_frame_header_opt (void);
>  /* Routines implemented in loongarch-c.c.  */
>  void loongarch_cpu_cpp_builtins (cpp_reader *);
>  
> +extern tree loongarch_fold_builtin (tree, int, tree*, bool);
>  extern void loongarch_init_builtins (void);
>  extern void loongarch_atomic_assign_expand_fenv (tree *, tree *, tree *);
>  extern tree loongarch_builtin_decl (unsigned int, bool);
>  extern rtx loongarch_expand_builtin (tree, rtx, rtx subtarget ATTRIBUTE_UNUSED,
>                                      machine_mode, int);
>  extern tree loongarch_build_builtin_va_list (void);
> +extern machine_mode loongarch_c_mode_for_suffix (char suffix);
>  
>  #endif /* ! GCC_LOONGARCH_PROTOS_H */
> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> index 86d58784113..7a8358c9630 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -6790,6 +6790,16 @@ loongarch_set_handled_components (sbitmap components)
>         cfun->machine->reg_is_wrapped_separately[regno] = true;
>  }
>  
> +/* Target hook for c_mode_for_suffix.  */
> +machine_mode
> +loongarch_c_mode_for_suffix (char suffix)
> +{
> +  if (suffix == 'q')
> +    return TFmode;
> +
> +  return VOIDmode;
> +}
> +
>  /* Initialize the GCC target structure.  */
>  #undef TARGET_ASM_ALIGNED_HI_OP
>  #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
> @@ -6901,6 +6911,10 @@ loongarch_set_handled_components (sbitmap components)
>  #define TARGET_BUILTIN_DECL loongarch_builtin_decl
>  #undef TARGET_EXPAND_BUILTIN
>  #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin
> +#undef TARGET_FOLD_BUILTIN
> +#define TARGET_FOLD_BUILTIN loongarch_fold_builtin
> +#undef TARGET_C_MODE_FOR_SUFFIX
> +#define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix
>  
>  /* The generic ELF target does not always have TLS support.  */
>  #ifdef HAVE_AS_TLS
> diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
> index b37e070660f..9fe3faf8b92 100644
> --- a/gcc/config/loongarch/loongarch.md
> +++ b/gcc/config/loongarch/loongarch.md
> @@ -44,6 +44,13 @@ (define_c_enum "unspec" [
>    UNSPEC_FSCALEB
>    UNSPEC_FLOGB
>  
> +  UNSPEC_INFQ
> +  UNSPEC_HUGE_VALQ
> +  UNSPEC_FABSQ
> +  UNSPEC_COPYSIGNQ
> +  UNSPEC_NANQ
> +  UNSPEC_NANSQ
> +
>    ;; Override return address for exception handling.
>    UNSPEC_EH_RETURN
>  
> @@ -563,6 +570,15 @@ (define_int_attr bytepick_imm [(8 "1")
>                                  (48 "6")
>                                  (56 "7")])
>  
> +;; mathq function
> +(define_int_iterator MATHQ[UNSPEC_INFQ  UNSPEC_HUGE_VALQ
> +                           UNSPEC_NANQ UNSPEC_NANSQ])
> +(define_int_attr mathq_pattern[(UNSPEC_INFQ "infq")
> +                               (UNSPEC_HUGE_VALQ "huge_valq")
> +                               (UNSPEC_NANQ "nanq")
> +                               (UNSPEC_NANSQ "nansq")]
> +)
> +
>  ;;
>  ;;  ....................
>  ;;
> @@ -2008,6 +2024,59 @@ (define_insn "movfcc"
>    ""
>    "movgr2cf\t%0,$r0")
>  
> +;; Implements functions with a "q" suffix
> +
> +(define_insn "<mathq_pattern>"
> +  [(unspec:SI[(const_int 0)] MATHQ)]
> +  ""
> +  "")
> +
> +;;Implement __builtin_fabsq function.
> +
> +(define_insn_and_split   "fabsq"
> +  [(set (match_operand:TF  0 "register_operand" "=r")
> +       (unspec:TF[(match_operand:TF 1 "register_operand" "rG")]
> +                   UNSPEC_FABSQ))]
> +  ""
> +  "#"
> +  "reload_completed"
> +[(set (zero_extract:DI (match_operand:DI 0 "register_operand")
> +                       (match_operand:SI 3 "const_int_operand")
> +                       (match_operand:SI 4 "const_int_operand"))
> +      (match_operand:DI 2 "const_int_operand"))]
> +{
> +       operands[0] = gen_rtx_REG (Pmode, REGNO (operands[0])+1);
> +       operands[2] = GEN_INT (0);
> +       operands[3] = GEN_INT (1);
> +       operands[4] = GEN_INT (63);
> +}
> +)
> +
> +;;Implement __builtin_copysignq function.
> +
> +(define_insn_and_split  "copysignq"
> +  [(set (match_operand:TF  0 "register_operand" "=r")
> +       (unspec:TF[(match_operand:TF 1 "register_operand" "rG")
> +                   (match_operand:TF 2 "register_operand" "rG")]
> +                     UNSPEC_COPYSIGNQ))]
> + ""
> + "#"
> + "reload_completed"
> +  [(set (match_operand:DI 2 "register_operand")
> +       (lshiftrt :DI (match_operand:DI 2 "register_operand")
> +       (match_operand:SI 4 "arith_operand")))
> +   (set (zero_extract:DI (match_operand:DI 0 "register_operand")
> +                         (match_operand:SI 3 "const_int_operand")
> +                         (match_operand:SI 4 "const_int_operand"))
> +       (match_operand:DI 2 "register_operand"))]
> +{
> +   operands[0] = gen_rtx_REG (Pmode,REGNO (operands[0])+1);
> +   operands[2] = gen_rtx_REG (Pmode,REGNO (operands[2])+1);
> +   operands[3] = GEN_INT (1);
> +   operands[4] = GEN_INT (63);
> +}
> +)
> +
>  ;; Conditional move instructions.
>  
>  (define_insn "*sel<code><GPR:mode>_using_<GPR2:mode>"
> diff --git a/libgcc/config/loongarch/t-softfp-tf b/libgcc/config/loongarch/t-softfp-tf
> index 306677b1255..0e7c2b4cabe 100644
> --- a/libgcc/config/loongarch/t-softfp-tf
> +++ b/libgcc/config/loongarch/t-softfp-tf
> @@ -1,3 +1,6 @@
>  softfp_float_modes += tf
>  softfp_extensions += sftf dftf
>  softfp_truncations += tfsf tfdf
> +#Used to implement a special 128-bit function with a q suffix
> +LIB2ADD += $(srcdir)/config/loongarch/tf-signs.c
> +
> diff --git a/libgcc/config/loongarch/tf-signs.c b/libgcc/config/loongarch/tf-signs.c
> new file mode 100644
> index 00000000000..68db1729372
> --- /dev/null
> +++ b/libgcc/config/loongarch/tf-signs.c
> @@ -0,0 +1,59 @@
> +/* Copyright (C) 2008-2023 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.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +<http://www.gnu.org/licenses/>.  */
> +
> +union _FP_UNION_Q
> +{
> +   __float128 flt;
> +   struct
> +   {
> +      unsigned long frac0 : 64;
> +      unsigned long frac1 : 48;
> +      unsigned exp : 15;
> +      unsigned sign : 1;
> +   } bits __attribute__((packed));
> +};
> +
> +__float128 __nanq (const char *str);
> +__float128 __nansq (const char *str);
> +
> +__float128 __nanq (const char * str)
> +{
> +  union _FP_UNION_Q nan;
> +  nan.bits.frac0 = 0;
> +  nan.bits.frac1 = 0;
> +  nan.bits.exp = 0x7FFF;
> +  nan.bits.sign = 0;
> +
> +  return nan.flt;
> +}
> +__float128 __nansq (const char *str)
> +{
> +  union _FP_UNION_Q nan;
> +  nan.bits.frac0 = 0xFFFFFFFFFFFFFFFFUL;
> +  nan.bits.frac1 = 0x0000FFFFFFFFFFFFUL;
> +  nan.bits.exp = 0x7FFF;
> +  nan.bits.sign = 0;
> +
> +  return nan.flt;
> +}
> +

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-15 10:39 [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc chenxiaolong
  2023-08-15 10:48 ` Xi Ruoyao
@ 2023-08-15 20:03 ` Joseph Myers
  2023-08-16 10:08   ` chenxiaolong
  2023-08-17  3:44   ` Xi Ruoyao
  1 sibling, 2 replies; 13+ messages in thread
From: Joseph Myers @ 2023-08-15 20:03 UTC (permalink / raw)
  To: chenxiaolong; +Cc: gcc-patches, xry111, i, xuchenghua, chenglulu

On Tue, 15 Aug 2023, chenxiaolong wrote:

> 	In the implementation process, the "q" suffix function is
>         Re-register and associate the "__float128" type with the
>         "long double" type so that the compiler can handle the
>         corresponding function correctly. The functions implemented
>         include __builtin_{huge_valq infq, fabsq, copysignq, nanq,nansq}.
>         On the LoongArch architecture, __builtin_{fabsq,copysignq} can
>         be implemented with the instruction "bstrins.d", so that its
>         optimization effect reaches the optimal value.

Why?  If long double has binary128 format, you shouldn't need any of these 
functions at all; if it doesn't, just the C23 _Float128 type name and f128 
constant suffix, and associated built-in functions defined in 
builtins.def, should suffice (and since we now have _FloatN support for 
C++, C++ no longer provides a reason for adding __float128 either).  
__float128 is a legacy type name and feature and shouldn't be needed on 
any new architectures, which can just use the standard type name from the 
start.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-15 20:03 ` Joseph Myers
@ 2023-08-16 10:08   ` chenxiaolong
  2023-08-16 13:16     ` Joseph Myers
  2023-08-17  3:44   ` Xi Ruoyao
  1 sibling, 1 reply; 13+ messages in thread
From: chenxiaolong @ 2023-08-16 10:08 UTC (permalink / raw)
  To: Joseph Myers; +Cc: gcc-patches, xry111, i, xuchenghua, chenglulu

Thanks for the tip! Similar functions (e.g. __builtin_fabsf128
(_Float128 a) are already supported by the compiler and can be handled
correctly, but functions that can be implemented on the LoongArch
architecture directly using the "bstrins" directive (e.g. fabsq,
copysignq, etc.) are better optimized because they generate fewer
assembly instructions. copysignq, etc.) on the LoongArch architecture
are better optimized because they generate fewer assembly instructions.

Translated with www.DeepL.com/Translator (free version)

在 2023-08-15二的 20:03 +0000,Joseph Myers写道:
> On Tue, 15 Aug 2023, chenxiaolong wrote:
> 
> > 	In the implementation process, the "q" suffix function is
> >         Re-register and associate the "__float128" type with the
> >         "long double" type so that the compiler can handle the
> >         corresponding function correctly. The functions implemented
> >         include __builtin_{huge_valq infq, fabsq, copysignq,
> > nanq,nansq}.
> >         On the LoongArch architecture, __builtin_{fabsq,copysignq}
> > can
> >         be implemented with the instruction "bstrins.d", so that
> > its
> >         optimization effect reaches the optimal value.
> 
> Why?  If long double has binary128 format, you shouldn't need any of
> these 
> functions at all; if it doesn't, just the C23 _Float128 type name and
> f128 
> constant suffix, and associated built-in functions defined in 
> builtins.def, should suffice (and since we now have _FloatN support
> for 
> C++, C++ no longer provides a reason for adding __float128 either).  
> __float128 is a legacy type name and feature and shouldn't be needed
> on 
> any new architectures, which can just use the standard type name from
> the 
> start.
> 


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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-16 10:08   ` chenxiaolong
@ 2023-08-16 13:16     ` Joseph Myers
  0 siblings, 0 replies; 13+ messages in thread
From: Joseph Myers @ 2023-08-16 13:16 UTC (permalink / raw)
  To: chenxiaolong; +Cc: gcc-patches, xry111, i, xuchenghua, chenglulu

On Wed, 16 Aug 2023, chenxiaolong wrote:

> Thanks for the tip! Similar functions (e.g. __builtin_fabsf128
> (_Float128 a) are already supported by the compiler and can be handled
> correctly, but functions that can be implemented on the LoongArch
> architecture directly using the "bstrins" directive (e.g. fabsq,
> copysignq, etc.) are better optimized because they generate fewer
> assembly instructions. copysignq, etc.) on the LoongArch architecture
> are better optimized because they generate fewer assembly instructions.

Then you should make the existing built-in functions for _Float128 or long 
double generate the desired instructions, rather than adding a legacy and 
duplicative API to a new architecture.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-15 20:03 ` Joseph Myers
  2023-08-16 10:08   ` chenxiaolong
@ 2023-08-17  3:44   ` Xi Ruoyao
  2023-08-17 15:08     ` Joseph Myers
  1 sibling, 1 reply; 13+ messages in thread
From: Xi Ruoyao @ 2023-08-17  3:44 UTC (permalink / raw)
  To: Joseph Myers, chenxiaolong; +Cc: gcc-patches, i, xuchenghua, chenglulu

On Tue, 2023-08-15 at 20:03 +0000, Joseph Myers wrote:
> On Tue, 15 Aug 2023, chenxiaolong wrote:
> 
> >         In the implementation process, the "q" suffix function is
> >         Re-register and associate the "__float128" type with the
> >         "long double" type so that the compiler can handle the
> >         corresponding function correctly. The functions implemented
> >         include __builtin_{huge_valq infq, fabsq, copysignq, nanq,nansq}.
> >         On the LoongArch architecture, __builtin_{fabsq,copysignq} can
> >         be implemented with the instruction "bstrins.d", so that its
> >         optimization effect reaches the optimal value.
> 
> Why?  If long double has binary128 format, you shouldn't need any of these 
> functions at all; if it doesn't, just the C23 _Float128 type name and f128 
> constant suffix, and associated built-in functions defined in 
> builtins.def, should suffice (and since we now have _FloatN support for 
> C++, C++ no longer provides a reason for adding __float128 either).  
> __float128 is a legacy type name and feature and shouldn't be needed on 
> any new architectures, which can just use the standard type name from the 
> start.

For _Float128 GCC already does the correct thing:

_Float128 g(_Float128 x) { return __builtin_fabsf128(x); }

compiled to (with -O2):

g:
.LFB3 = .
        .cfi_startproc
        bstrpick.d      $r5,$r5,62,0
        jr      $r1
        .cfi_endproc

So I guess we just need

builtin_define ("__builtin_fabsq=__builtin_fabsf128");
builtin_define ("__builtin_nanq=__builtin_nanf128");

etc. to map the "q" builtins to "f128" builtins if we really need the
"q" builtins.

Joseph: the problem here is many customers of LoongArch CPUs wish to
compile their old code with minimal change.  Is it acceptable to add
these builtin_define's like rs6000-c.cc?  Note "a new architecture" does
not mean we'll only compile post-C2x-era programs onto it.
-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH v3]  LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-15 10:48 ` Xi Ruoyao
@ 2023-08-17  6:56   ` chenxiaolong
  0 siblings, 0 replies; 13+ messages in thread
From: chenxiaolong @ 2023-08-17  6:56 UTC (permalink / raw)
  To: Xi Ruoyao, gcc-patches; +Cc: i, xuchenghua, chenglulu

Okay, thanks for the heads up! I'll try to format the code according to
the GNU Coding Standards. I'll double-check every line of the submitted
patch to make sure that I don't have such a low-level formatting
problem in every future patch, so that I can comply with the code
specification.

在 2023-08-15二的 18:48 +0800,Xi Ruoyao写道:
> Please fix code style (this is the third time I say it and I'm really
> frustrated now).  GCC is a project, it's not a student homework so
> style
> matters.  And it's not so difficult to fix the style: for a new file
> you
> can use "clang-format --style GNU -i filename.c" to do the work
> automatically.
> 
> On Tue, 2023-08-15 at 18:39 +0800, chenxiaolong wrote:
> >         In the implementation process, the "q" suffix function is
> >         Re-register and associate the "__float128" type with the
> >         "long double" type so that the compiler can handle the
> >         corresponding function correctly. The functions implemented
> >         include __builtin_{huge_valq infq, fabsq, copysignq,
> > nanq,nansq}.
> >         On the LoongArch architecture, __builtin_{fabsq,copysignq}
> > can
> >         be implemented with the instruction "bstrins.d", so that
> > its
> >         optimization effect reaches the optimal value.
> > 
> > gcc/ChangeLog:
> > 
> >         * config/loongarch/loongarch-builtins.cc (DEF_LARCH_FTYPE):
> >         (enum loongarch_builtin_type):Increases the type of the
> > function.
> >         (FLOAT_BUILTIN_HIQ):__builtin_{huge_valq,infq}.
> >         (FLOAT_BUILTIN_FCQ):__builtin_{fabsq,copysignq}.
> >         (FLOAT_BUILTIN_NNQ):__builtin_{nanq,nansq}.
> >         (loongarch_init_builtins):
> >         (loongarch_fold_builtin):
> >         (loongarch_expand_builtin):
> >         * config/loongarch/loongarch-protos.h
> > (loongarch_fold_builtin):
> >         (loongarch_c_mode_for_suffix):Add the declaration of the
> > function.
> >         * config/loongarch/loongarch.cc
> > (loongarch_c_mode_for_suffix):Add
> >         the definition of the function.
> >         (TARGET_FOLD_BUILTIN):
> >         (TARGET_C_MODE_FOR_SUFFIX):
> >         * config/loongarch/loongarch.md (infq):Add an instruction
> > template
> >         to the machine description file to generate information
> > such as
> >         the icode used by the function and the constructor.
> >         (<mathq_pattern>):
> >         (fabsq):
> >         (copysignq):
> > 
> > libgcc/ChangeLog:
> > 
> >         * config/loongarch/t-softfp-tf:
> >         * config/loongarch/tf-signs.c: New file.
> > ---
> >  gcc/config/loongarch/loongarch-builtins.cc | 168
> > ++++++++++++++++++++-
> >  gcc/config/loongarch/loongarch-protos.h    |   2 +
> >  gcc/config/loongarch/loongarch.cc          |  14 ++
> >  gcc/config/loongarch/loongarch.md          |  69 +++++++++
> >  libgcc/config/loongarch/t-softfp-tf        |   3 +
> >  libgcc/config/loongarch/tf-signs.c         |  59 ++++++++
> >  6 files changed, 313 insertions(+), 2 deletions(-)
> >  create mode 100644 libgcc/config/loongarch/tf-signs.c
> > 
> > diff --git a/gcc/config/loongarch/loongarch-builtins.cc
> > b/gcc/config/loongarch/loongarch-builtins.cc
> > index b929f224dfa..2fb0fde0e3f 100644
> > --- a/gcc/config/loongarch/loongarch-builtins.cc
> > +++ b/gcc/config/loongarch/loongarch-builtins.cc
> > @@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.  If not
> > see
> >  #include "fold-const.h"
> >  #include "expr.h"
> >  #include "langhooks.h"
> > +#include "calls.h"
> > +#include "explow.h"
> >  
> >  /* Macros to create an enumeration identifier for a function
> > prototype.  */
> >  #define LARCH_FTYPE_NAME1(A, B) LARCH_##A##_FTYPE_##B
> > @@ -48,9 +50,18 @@ enum loongarch_function_type
> >  #define DEF_LARCH_FTYPE(NARGS, LIST) LARCH_FTYPE_NAME##NARGS LIST,
> >  #include "config/loongarch/loongarch-ftypes.def"
> >  #undef DEF_LARCH_FTYPE
> > +  LARCH_BUILTIN_HUGE_VALQ,
> > +  LARCH_BUILTIN_INFQ,
> > +  LARCH_BUILTIN_FABSQ,
> > +  LARCH_BUILTIN_COPYSIGNQ,
> > +  LARCH_BUILTIN_NANQ,
> > +  LARCH_BUILTIN_NANSQ,
> >    LARCH_MAX_FTYPE_MAX
> >  };
> >  
> > +/* Count the number of functions with "q" as the suffix.  */
> > +const int MATHQ_NUMS = (int)LARCH_MAX_FTYPE_MAX -
> > (int)LARCH_BUILTIN_HUGE_VALQ;
> > +
> >  /* Specifies how a built-in function should be converted into
> > rtl.  */
> >  enum loongarch_builtin_type
> >  {
> > @@ -63,6 +74,15 @@ enum loongarch_builtin_type
> >       value and the arguments are mapped to operands 0 and above. 
> > */
> >    LARCH_BUILTIN_DIRECT_NO_TARGET,
> >  
> > + /* The function corresponds to  __builtin_{huge_valq,infq}.  */
> > +  LARCH_BUILTIN_HIQ_DIRECT,
> > +
> > + /* The function corresponds to  __builtin_{fabsq,copysignq}.  */
> > +  LARCH_BUILTIN_FCQ_DIRECT,
> > +
> > +  /* Define the type of the __builtin_{nanq,nansq} function.  */
> > +  LARCH_BUILTIN_NNQ_DIRECT
> > +
> >  };
> >  
> >  /* Declare an availability predicate for built-in functions that
> > require
> > @@ -136,6 +156,24 @@ AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI)
> >    LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT_NO_TARGET, \
> >                  FUNCTION_TYPE, AVAIL)
> >  
> > +/* Define an float to do funciton {huge_valq,infq}.  */
> > +#define FLOAT_BUILTIN_HIQ (INSN, FUNCTION_TYPE)          \
> > +    { CODE_FOR_ ## INSN,                         \
> > +    "__builtin_" #INSN,  LARCH_BUILTIN_HIQ_DIRECT,    \
> > +    FUNCTION_TYPE, loongarch_builtin_avail_default }
> > +
> > +/* Define an float to do funciton {fabsq,copysignq}.  */
> > +#define FLOAT_BUILTIN_FCQ (INSN, FUNCTION_TYPE)          \
> > +    { CODE_FOR_ ## INSN,                         \
> > +    "__builtin_" #INSN,  LARCH_BUILTIN_FCQ_DIRECT,    \
> > +    FUNCTION_TYPE, loongarch_builtin_avail_default }
> > +
> > +/* Define an float to do funciton {nanq,nansq}.  */
> > +#define FLOAT_BUILTIN_NNQ (INSN, FUNCTION_TYPE)      \
> > +    { CODE_FOR_ ## INSN,                               \
> > +    "__builtin_" #INSN,  LARCH_BUILTIN_NNQ_DIRECT,       \
> > +    FUNCTION_TYPE, loongarch_builtin_avail_default }
> > +
> >  static const struct loongarch_builtin_description
> > loongarch_builtins[] = {
> >  #define LARCH_MOVFCSR2GR 0
> >    DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float),
> > @@ -183,6 +221,14 @@ static const struct
> > loongarch_builtin_description loongarch_builtins[] = {
> >    DIRECT_NO_TARGET_BUILTIN (asrtgt_d, LARCH_VOID_FTYPE_DI_DI,
> > default),
> >    DIRECT_NO_TARGET_BUILTIN (syscall, LARCH_VOID_FTYPE_USI,
> > default),
> >    DIRECT_NO_TARGET_BUILTIN (break, LARCH_VOID_FTYPE_USI, default),
> > +
> > +  FLOAT_BUILTIN_HIQ (huge_valq, LARCH_BUILTIN_HUGE_VALQ),
> > +  FLOAT_BUILTIN_HIQ (infq, LARCH_BUILTIN_INFQ),
> > +  FLOAT_BUILTIN_FCQ (fabsq, LARCH_BUILTIN_FABSQ),
> > +  FLOAT_BUILTIN_FCQ (copysignq, LARCH_BUILTIN_COPYSIGNQ),
> > +  FLOAT_BUILTIN_NNQ (nanq, LARCH_BUILTIN_NANQ),
> > +  FLOAT_BUILTIN_NNQ (nansq, LARCH_BUILTIN_NANSQ),
> > +
> >  };
> >  
> >  /* Index I is the function declaration for loongarch_builtins[I],
> > or null if
> > @@ -255,10 +301,13 @@ loongarch_init_builtins (void)
> >    const struct loongarch_builtin_description *d;
> >    unsigned int i;
> >    tree type;
> > +  tree const_string_type
> > +     =build_pointer_type (build_qualified_type (char_type_node,
> > +                                               TYPE_QUAL_CONST));
> >  
> >    /* Iterate through all of the bdesc arrays, initializing all of
> > the
> >       builtin functions.  */
> > -  for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++)
> > +  for (i = 0; i < ARRAY_SIZE (loongarch_builtins)-MATHQ_NUMS; i++)
> >      {
> >        d = &loongarch_builtins[i];
> >        if (d->avail ())
> > @@ -270,6 +319,63 @@ loongarch_init_builtins (void)
> >           loongarch_get_builtin_decl_index[d->icode] = i;
> >         }
> >      }
> > +   /* Register the type long_double_type_node as a built-in type
> > and
> > +     give it an alias "__float128".  */
> > +  (*lang_hooks.types.register_builtin_type)
> > (long_double_type_node,
> > +                                           "__float128");
> > +
> > +      type = build_function_type_list (long_double_type_node,
> > NULL_TREE);
> > +      d = &loongarch_builtins[i];
> > +      loongarch_builtin_decls[i]
> > +       =add_builtin_function ("__builtin_huge_valq", type,
> > +                            i, BUILT_IN_MD, NULL, NULL_TREE);
> > +      loongarch_get_builtin_decl_index[d->icode]=i++;
> > +
> > +      type = build_function_type_list (long_double_type_node,
> > NULL_TREE);
> > +      d = &loongarch_builtins[i];
> > +      loongarch_builtin_decls[i]
> > +       =add_builtin_function ("__builtin_infq",  type,
> > +                               i,  BUILT_IN_MD,  NULL, NULL_TREE);
> > +      loongarch_get_builtin_decl_index[d->icode]=i++;
> > +
> > +      type = build_function_type_list (long_double_type_node,
> > +                                      long_double_type_node,
> > +                                      NULL_TREE);
> > +      d = &loongarch_builtins[i];
> > +      loongarch_builtin_decls[i]
> > +       =add_builtin_function ("__builtin_fabsq", type,
> > +                              i,  BUILT_IN_MD,  NULL,  NULL_TREE);
> > +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> > +      loongarch_get_builtin_decl_index[d->icode]=i++;
> > +
> > +      type = build_function_type_list (long_double_type_node,
> > +                                      long_double_type_node,
> > +                                      long_double_type_node,
> > +                                      NULL_TREE);
> > +      d = &loongarch_builtins[i];
> > +      loongarch_builtin_decls[i]
> > +       =add_builtin_function ("__builtin_copysignq", type,
> > +                              i,  BUILT_IN_MD,  NULL,  NULL_TREE);
> > +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> > +      loongarch_get_builtin_decl_index[d->icode]=i++;
> > +
> > +      type=build_function_type_list (long_double_type_node,
> > +                                    const_string_type,
> > +                                    NULL_TREE);
> > +      d = &loongarch_builtins[i];
> > +      loongarch_builtin_decls[i]
> > +       =add_builtin_function ("__builtin_nanq", type,
> > +                              i, BUILT_IN_MD,  "__nanq",
> > NULL_TREE);
> > +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> > +      loongarch_get_builtin_decl_index[d->icode]=i++;
> > +
> > +      d = &loongarch_builtins[i];
> > +      loongarch_builtin_decls[i]
> > +       =add_builtin_function ("__builtin_nansq", type,
> > +                              i, BUILT_IN_MD,  "__nansq", 
> > NULL_TREE);
> > +      TREE_READONLY (loongarch_builtin_decls[i]) =1;
> > +      loongarch_get_builtin_decl_index[d->icode]=i;
> > +
> >  }
> >  
> >  /* Implement TARGET_BUILTIN_DECL.  */
> > @@ -282,6 +388,42 @@ loongarch_builtin_decl (unsigned int code,
> > bool initialize_p ATTRIBUTE_UNUSED)
> >    return loongarch_builtin_decls[code];
> >  }
> >  
> > +tree
> > +loongarch_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
> > +                       tree *args, bool ignore ATTRIBUTE_UNUSED)
> > +{
> > +  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
> > +    {
> > +      enum loongarch_function_type fn_code
> > +        = (enum loongarch_function_type) DECL_MD_FUNCTION_CODE
> > (fndecl);
> > +      switch (fn_code)
> > +       {
> > +         case LARCH_BUILTIN_NANQ:
> > +         case LARCH_BUILTIN_NANSQ:
> > +           {
> > +             tree type = TREE_TYPE (TREE_TYPE (fndecl));
> > +             const char *str = c_getstr (*args);
> > +             int quiet = fn_code == LARCH_BUILTIN_NANQ;
> > +             REAL_VALUE_TYPE real;
> > +
> > +             if (str && real_nan (&real, str, quiet, TYPE_MODE
> > (type)))
> > +               return build_real (type, real);
> > +             return NULL_TREE;
> > +           }
> > +
> > +         default:
> > +           break;
> > +       }
> > +      }
> > +
> > +#ifdef SUBTARGET_FOLD_BUILTIN
> > +  return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore);
> > +#endif
> > +
> > +  return NULL_TREE;
> > +}
> > +
> > +
> >  /* Take argument ARGNO from EXP's argument list and convert it
> > into
> >     an expand operand.  Store the operand in *OP.  */
> >  
> > @@ -362,11 +504,33 @@ loongarch_expand_builtin (tree exp, rtx
> > target, rtx subtarget ATTRIBUTE_UNUSED,
> >    switch (d->builtin_type)
> >      {
> >      case LARCH_BUILTIN_DIRECT:
> > +    case LARCH_BUILTIN_FCQ_DIRECT:
> >        return loongarch_expand_builtin_direct (d->icode, target,
> > exp, true);
> >  
> >      case LARCH_BUILTIN_DIRECT_NO_TARGET:
> >        return loongarch_expand_builtin_direct (d->icode, target,
> > exp, false);
> > -    }
> > +
> > +    case LARCH_BUILTIN_NNQ_DIRECT:
> > +      return expand_call ( exp ,target , ignore);
> > +
> > +    case LARCH_BUILTIN_HIQ_DIRECT:
> > +      {
> > +       machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp));
> > +       REAL_VALUE_TYPE inf;
> > +       rtx tmp;
> > +
> > +       real_inf (&inf);
> > +       tmp = const_double_from_real_value (inf, target_mode);
> > +
> > +       tmp=validize_mem (force_const_mem (target_mode,tmp));
> > +
> > +       if (target ==0)
> > +           target =gen_reg_rtx (target_mode);
> > +       emit_move_insn (target,tmp);
> > +
> > +       return target;
> > +      }
> > +  }
> >    gcc_unreachable ();
> >  }
> >  
> > diff --git a/gcc/config/loongarch/loongarch-protos.h
> > b/gcc/config/loongarch/loongarch-protos.h
> > index b71b188507a..35fc2ad7def 100644
> > --- a/gcc/config/loongarch/loongarch-protos.h
> > +++ b/gcc/config/loongarch/loongarch-protos.h
> > @@ -175,11 +175,13 @@ extern void
> > loongarch_register_frame_header_opt (void);
> >  /* Routines implemented in loongarch-c.c.  */
> >  void loongarch_cpu_cpp_builtins (cpp_reader *);
> >  
> > +extern tree loongarch_fold_builtin (tree, int, tree*, bool);
> >  extern void loongarch_init_builtins (void);
> >  extern void loongarch_atomic_assign_expand_fenv (tree *, tree *,
> > tree *);
> >  extern tree loongarch_builtin_decl (unsigned int, bool);
> >  extern rtx loongarch_expand_builtin (tree, rtx, rtx subtarget
> > ATTRIBUTE_UNUSED,
> >                                      machine_mode, int);
> >  extern tree loongarch_build_builtin_va_list (void);
> > +extern machine_mode loongarch_c_mode_for_suffix (char suffix);
> >  
> >  #endif /* ! GCC_LOONGARCH_PROTOS_H */
> > diff --git a/gcc/config/loongarch/loongarch.cc
> > b/gcc/config/loongarch/loongarch.cc
> > index 86d58784113..7a8358c9630 100644
> > --- a/gcc/config/loongarch/loongarch.cc
> > +++ b/gcc/config/loongarch/loongarch.cc
> > @@ -6790,6 +6790,16 @@ loongarch_set_handled_components (sbitmap
> > components)
> >         cfun->machine->reg_is_wrapped_separately[regno] = true;
> >  }
> >  
> > +/* Target hook for c_mode_for_suffix.  */
> > +machine_mode
> > +loongarch_c_mode_for_suffix (char suffix)
> > +{
> > +  if (suffix == 'q')
> > +    return TFmode;
> > +
> > +  return VOIDmode;
> > +}
> > +
> >  /* Initialize the GCC target structure.  */
> >  #undef TARGET_ASM_ALIGNED_HI_OP
> >  #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
> > @@ -6901,6 +6911,10 @@ loongarch_set_handled_components (sbitmap
> > components)
> >  #define TARGET_BUILTIN_DECL loongarch_builtin_decl
> >  #undef TARGET_EXPAND_BUILTIN
> >  #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin
> > +#undef TARGET_FOLD_BUILTIN
> > +#define TARGET_FOLD_BUILTIN loongarch_fold_builtin
> > +#undef TARGET_C_MODE_FOR_SUFFIX
> > +#define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix
> >  
> >  /* The generic ELF target does not always have TLS support.  */
> >  #ifdef HAVE_AS_TLS
> > diff --git a/gcc/config/loongarch/loongarch.md
> > b/gcc/config/loongarch/loongarch.md
> > index b37e070660f..9fe3faf8b92 100644
> > --- a/gcc/config/loongarch/loongarch.md
> > +++ b/gcc/config/loongarch/loongarch.md
> > @@ -44,6 +44,13 @@ (define_c_enum "unspec" [
> >    UNSPEC_FSCALEB
> >    UNSPEC_FLOGB
> >  
> > +  UNSPEC_INFQ
> > +  UNSPEC_HUGE_VALQ
> > +  UNSPEC_FABSQ
> > +  UNSPEC_COPYSIGNQ
> > +  UNSPEC_NANQ
> > +  UNSPEC_NANSQ
> > +
> >    ;; Override return address for exception handling.
> >    UNSPEC_EH_RETURN
> >  
> > @@ -563,6 +570,15 @@ (define_int_attr bytepick_imm [(8 "1")
> >                                  (48 "6")
> >                                  (56 "7")])
> >  
> > +;; mathq function
> > +(define_int_iterator MATHQ[UNSPEC_INFQ  UNSPEC_HUGE_VALQ
> > +                           UNSPEC_NANQ UNSPEC_NANSQ])
> > +(define_int_attr mathq_pattern[(UNSPEC_INFQ "infq")
> > +                               (UNSPEC_HUGE_VALQ "huge_valq")
> > +                               (UNSPEC_NANQ "nanq")
> > +                               (UNSPEC_NANSQ "nansq")]
> > +)
> > +
> >  ;;
> >  ;;  ....................
> >  ;;
> > @@ -2008,6 +2024,59 @@ (define_insn "movfcc"
> >    ""
> >    "movgr2cf\t%0,$r0")
> >  
> > +;; Implements functions with a "q" suffix
> > +
> > +(define_insn "<mathq_pattern>"
> > +  [(unspec:SI[(const_int 0)] MATHQ)]
> > +  ""
> > +  "")
> > +
> > +;;Implement __builtin_fabsq function.
> > +
> > +(define_insn_and_split   "fabsq"
> > +  [(set (match_operand:TF  0 "register_operand" "=r")
> > +       (unspec:TF[(match_operand:TF 1 "register_operand" "rG")]
> > +                   UNSPEC_FABSQ))]
> > +  ""
> > +  "#"
> > +  "reload_completed"
> > +[(set (zero_extract:DI (match_operand:DI 0 "register_operand")
> > +                       (match_operand:SI 3 "const_int_operand")
> > +                       (match_operand:SI 4 "const_int_operand"))
> > +      (match_operand:DI 2 "const_int_operand"))]
> > +{
> > +       operands[0] = gen_rtx_REG (Pmode, REGNO (operands[0])+1);
> > +       operands[2] = GEN_INT (0);
> > +       operands[3] = GEN_INT (1);
> > +       operands[4] = GEN_INT (63);
> > +}
> > +)
> > +
> > +;;Implement __builtin_copysignq function.
> > +
> > +(define_insn_and_split  "copysignq"
> > +  [(set (match_operand:TF  0 "register_operand" "=r")
> > +       (unspec:TF[(match_operand:TF 1 "register_operand" "rG")
> > +                   (match_operand:TF 2 "register_operand" "rG")]
> > +                     UNSPEC_COPYSIGNQ))]
> > + ""
> > + "#"
> > + "reload_completed"
> > +  [(set (match_operand:DI 2 "register_operand")
> > +       (lshiftrt :DI (match_operand:DI 2 "register_operand")
> > +       (match_operand:SI 4 "arith_operand")))
> > +   (set (zero_extract:DI (match_operand:DI 0 "register_operand")
> > +                         (match_operand:SI 3 "const_int_operand")
> > +                         (match_operand:SI 4 "const_int_operand"))
> > +       (match_operand:DI 2 "register_operand"))]
> > +{
> > +   operands[0] = gen_rtx_REG (Pmode,REGNO (operands[0])+1);
> > +   operands[2] = gen_rtx_REG (Pmode,REGNO (operands[2])+1);
> > +   operands[3] = GEN_INT (1);
> > +   operands[4] = GEN_INT (63);
> > +}
> > +)
> > +
> >  ;; Conditional move instructions.
> >  
> >  (define_insn "*sel<code><GPR:mode>_using_<GPR2:mode>"
> > diff --git a/libgcc/config/loongarch/t-softfp-tf
> > b/libgcc/config/loongarch/t-softfp-tf
> > index 306677b1255..0e7c2b4cabe 100644
> > --- a/libgcc/config/loongarch/t-softfp-tf
> > +++ b/libgcc/config/loongarch/t-softfp-tf
> > @@ -1,3 +1,6 @@
> >  softfp_float_modes += tf
> >  softfp_extensions += sftf dftf
> >  softfp_truncations += tfsf tfdf
> > +#Used to implement a special 128-bit function with a q suffix
> > +LIB2ADD += $(srcdir)/config/loongarch/tf-signs.c
> > +
> > diff --git a/libgcc/config/loongarch/tf-signs.c
> > b/libgcc/config/loongarch/tf-signs.c
> > new file mode 100644
> > index 00000000000..68db1729372
> > --- /dev/null
> > +++ b/libgcc/config/loongarch/tf-signs.c
> > @@ -0,0 +1,59 @@
> > +/* Copyright (C) 2008-2023 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.
> > +
> > +Under Section 7 of GPL version 3, you are granted additional
> > +permissions described in the GCC Runtime Library Exception,
> > version
> > +3.1, as published by the Free Software Foundation.
> > +
> > +You should have received a copy of the GNU General Public License
> > and
> > +a copy of the GCC Runtime Library Exception along with this
> > program;
> > +see the files COPYING3 and COPYING.RUNTIME respectively.  If not,
> > see
> > +<http://www.gnu.org/licenses/>;.  */
> > +
> > +union _FP_UNION_Q
> > +{
> > +   __float128 flt;
> > +   struct
> > +   {
> > +      unsigned long frac0 : 64;
> > +      unsigned long frac1 : 48;
> > +      unsigned exp : 15;
> > +      unsigned sign : 1;
> > +   } bits __attribute__((packed));
> > +};
> > +
> > +__float128 __nanq (const char *str);
> > +__float128 __nansq (const char *str);
> > +
> > +__float128 __nanq (const char * str)
> > +{
> > +  union _FP_UNION_Q nan;
> > +  nan.bits.frac0 = 0;
> > +  nan.bits.frac1 = 0;
> > +  nan.bits.exp = 0x7FFF;
> > +  nan.bits.sign = 0;
> > +
> > +  return nan.flt;
> > +}
> > +__float128 __nansq (const char *str)
> > +{
> > +  union _FP_UNION_Q nan;
> > +  nan.bits.frac0 = 0xFFFFFFFFFFFFFFFFUL;
> > +  nan.bits.frac1 = 0x0000FFFFFFFFFFFFUL;
> > +  nan.bits.exp = 0x7FFF;
> > +  nan.bits.sign = 0;
> > +
> > +  return nan.flt;
> > +}
> > +


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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-17  3:44   ` Xi Ruoyao
@ 2023-08-17 15:08     ` Joseph Myers
  2023-08-18  6:39       ` chenxiaolong
  0 siblings, 1 reply; 13+ messages in thread
From: Joseph Myers @ 2023-08-17 15:08 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: chenxiaolong, gcc-patches, i, xuchenghua, chenglulu

On Thu, 17 Aug 2023, Xi Ruoyao via Gcc-patches wrote:

> So I guess we just need
> 
> builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> builtin_define ("__builtin_nanq=__builtin_nanf128");
> 
> etc. to map the "q" builtins to "f128" builtins if we really need the
> "q" builtins.
> 
> Joseph: the problem here is many customers of LoongArch CPUs wish to
> compile their old code with minimal change.  Is it acceptable to add
> these builtin_define's like rs6000-c.cc?  Note "a new architecture" does
> not mean we'll only compile post-C2x-era programs onto it.

The powerpc support for __float128 started in GCC 6, predating the support 
for _FloatN type names, built-in functions etc. in GCC 7 - that's why 
there's such backwards compatibility support there.  That name only exists 
on a few architectures.

If people really want to compile code using the old __float128 names for 
LoongArch I suppose you could have such #defines, but it would be better 
for people to make their code use the standard names (as supported from 
GCC 7 onwards, though only from GCC 13 in C++) and then put backwards 
compatibility in their code for using the __float128 names if they want to 
support the type with older GCC (GCC 6 or before for C; GCC 12 or before 
for C++) on x86_64 / i386 / powerpc / ia64.  Such backwards compatibility 
in user code is more likely to be relevant for C++ than for C, given how 
the C++ support was added to GCC much more recently.  (Note: I haven't 
checked when other compilers added support for the _Float128 name or 
associated built-in functions, whether for C or for C++, which might also 
affect when user code wants such compatibility.)

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-17 15:08     ` Joseph Myers
@ 2023-08-18  6:39       ` chenxiaolong
  2023-08-18  6:58         ` Xi Ruoyao
  0 siblings, 1 reply; 13+ messages in thread
From: chenxiaolong @ 2023-08-18  6:39 UTC (permalink / raw)
  To: Joseph Myers, Xi Ruoyao; +Cc: gcc-patches, i, xuchenghua, chenglulu

在 2023-08-17四的 15:08 +0000,Joseph Myers写道:
> On Thu, 17 Aug 2023, Xi Ruoyao via Gcc-patches wrote:
> 
> > So I guess we just need
> > 
> > builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > builtin_define ("__builtin_nanq=__builtin_nanf128");
> > 
> > etc. to map the "q" builtins to "f128" builtins if we really need
> > the
> > "q" builtins.
> > 
> > Joseph: the problem here is many customers of LoongArch CPUs wish
> > to
> > compile their old code with minimal change.  Is it acceptable to
> > add
> > these builtin_define's like rs6000-c.cc?  Note "a new architecture"
> > does
> > not mean we'll only compile post-C2x-era programs onto it.
> 
> The powerpc support for __float128 started in GCC 6, predating the
> support 
> for _FloatN type names, built-in functions etc. in GCC 7 - that's
> why 
> there's such backwards compatibility support there.  That name only
> exists 
> on a few architectures.
> 
> If people really want to compile code using the old __float128 names
> for 
> LoongArch I suppose you could have such #defines, but it would be
> better 
> for people to make their code use the standard names (as supported
> from 
> GCC 7 onwards, though only from GCC 13 in C++) and then put
> backwards 
> compatibility in their code for using the __float128 names if they
> want to 
> support the type with older GCC (GCC 6 or before for C; GCC 12 or
> before 
> for C++) on x86_64 / i386 / powerpc / ia64.  Such backwards
> compatibility 
> in user code is more likely to be relevant for C++ than for C, given
> how 
> the C++ support was added to GCC much more recently.  (Note: I
> haven't 
> checked when other compilers added support for the _Float128 name or 
> associated built-in functions, whether for C or for C++, which might
> also 
> affect when user code wants such compatibility.)
> 
Thank you for your valuable comments. On the LoongArch architecture,
the "__float128" type is associated with float128_type_node and the "q"
suffix function is mapped to the "f128" function. This allows
compatibility with both "__float128" and "_Float128" types in the GCC
compiler. The new code is modified as follows:
  Add the following to the loongarch-builtins.c file:
+lang_hooks.types.register_builtin_type (float128_type_node,
"__float128");
  Add the following to the loongarch-c.c file:
+builtin_define ("__builtin_fabsq=__builtin_fabsf128");
+builtin_define ("__builtin_copysignq=__builtin_copysignf128");
+builtin_define ("__builtin_nanq=__builtin_nanf128");
+builtin_define ("__builtin_nansq=__builtin_nansf128");
+builtin_define ("__builtin_infq=__builtin_inff128");
+builtin_define ("__builtin_huge_valq=__builtin_huge_valf128");

 The regression tests of the six functions were added without problems.
However, the implementation of the __builtin_nansq() function does not
get the result we want. The questions are as follows:
 x86_64:
    _Float128 ret=__builtin_nansf128("NAN");

    compiled to (with gcc test.c -O2 ):
 		.cfi_offset 1, -8
	bl	%plt(__builtin_nansf128)
        ..
 LoongArch:
    _Float128 ret=__builtin_nansf128("NAN");
      compiled to (with gcc test.c -O2 ):
	.cfi_offset 1, -8
	bl	%plt(__builtin_nansf128)
        ..
   Obviously, there may have been legacy issues with the implementation
when "_Float128 __builtin_nansf128()" was first supported.
Architectures including LoongArch, x86_64, arm, etc. are no longer
supported, and some of the remaining architectures are unproven.
   I will continue to follow up the implementation of the builtin
function and complete the function.


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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-18  6:39       ` chenxiaolong
@ 2023-08-18  6:58         ` Xi Ruoyao
  2023-08-18  7:05           ` Xi Ruoyao
  0 siblings, 1 reply; 13+ messages in thread
From: Xi Ruoyao @ 2023-08-18  6:58 UTC (permalink / raw)
  To: chenxiaolong, Joseph Myers; +Cc: gcc-patches, i, xuchenghua, chenglulu

On Fri, 2023-08-18 at 14:39 +0800, chenxiaolong wrote:
> 在 2023-08-17四的 15:08 +0000,Joseph Myers写道:
> > On Thu, 17 Aug 2023, Xi Ruoyao via Gcc-patches wrote:
> > 
> > > So I guess we just need
> > > 
> > > builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > > builtin_define ("__builtin_nanq=__builtin_nanf128");
> > > 
> > > etc. to map the "q" builtins to "f128" builtins if we really need
> > > the
> > > "q" builtins.
> > > 
> > > Joseph: the problem here is many customers of LoongArch CPUs wish
> > > to
> > > compile their old code with minimal change.  Is it acceptable to
> > > add
> > > these builtin_define's like rs6000-c.cc?  Note "a new architecture"
> > > does
> > > not mean we'll only compile post-C2x-era programs onto it.
> > 
> > The powerpc support for __float128 started in GCC 6, predating the
> > support 
> > for _FloatN type names, built-in functions etc. in GCC 7 - that's
> > why 
> > there's such backwards compatibility support there.  That name only
> > exists 
> > on a few architectures.
> > 
> > If people really want to compile code using the old __float128 names
> > for 
> > LoongArch I suppose you could have such #defines, but it would be
> > better 
> > for people to make their code use the standard names (as supported
> > from 
> > GCC 7 onwards, though only from GCC 13 in C++) and then put
> > backwards 
> > compatibility in their code for using the __float128 names if they
> > want to 
> > support the type with older GCC (GCC 6 or before for C; GCC 12 or
> > before 
> > for C++) on x86_64 / i386 / powerpc / ia64.  Such backwards
> > compatibility 
> > in user code is more likely to be relevant for C++ than for C, given
> > how 
> > the C++ support was added to GCC much more recently.  (Note: I
> > haven't 
> > checked when other compilers added support for the _Float128 name or
> > associated built-in functions, whether for C or for C++, which might
> > also 
> > affect when user code wants such compatibility.)
> > 
> Thank you for your valuable comments. On the LoongArch architecture,
> the "__float128" type is associated with float128_type_node and the "q"
> suffix function is mapped to the "f128" function. This allows
> compatibility with both "__float128" and "_Float128" types in the GCC
> compiler. The new code is modified as follows:
>   Add the following to the loongarch-builtins.c file:
> +lang_hooks.types.register_builtin_type (float128_type_node,
> "__float128");
>   Add the following to the loongarch-c.c file:
> +builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> +builtin_define ("__builtin_copysignq=__builtin_copysignf128");
> +builtin_define ("__builtin_nanq=__builtin_nanf128");
> +builtin_define ("__builtin_nansq=__builtin_nansf128");
> +builtin_define ("__builtin_infq=__builtin_inff128");
> +builtin_define ("__builtin_huge_valq=__builtin_huge_valf128");
> 
>  The regression tests of the six functions were added without problems.
> However, the implementation of the __builtin_nansq() function does not
> get the result we want. The questions are as follows:
>  x86_64:
>     _Float128 ret=__builtin_nansf128("NAN");
> 
>     compiled to (with gcc test.c -O2 ):
>                 .cfi_offset 1, -8
>         bl      %plt(__builtin_nansf128)
>         ..
>  LoongArch:
>     _Float128 ret=__builtin_nansf128("NAN");
>       compiled to (with gcc test.c -O2 ):
>         .cfi_offset 1, -8
>         bl      %plt(__builtin_nansf128)

It seems wrong.  It should be "bl %plt(nansf128)" instead, without the
__builtin_ prefix so the implementation in libm (from Glibc) will be
used instead.  AFAIK __builtin_nan and __builtin_nans are rarely called
with a non-empty tagp so it's not worthy to inline the implementation
for non-empty tagp here.

The same issue happens on x86_64:

call    __builtin_nansf128@PLT

__builtin_nanf128 compiles correct:

call    nanf128@PLT

I'll see if there is a ticket in https://gcc.gnu.org/bugzilla.  If not
I'll create one.


-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-18  6:58         ` Xi Ruoyao
@ 2023-08-18  7:05           ` Xi Ruoyao
  2023-08-18  7:19             ` Xi Ruoyao
  0 siblings, 1 reply; 13+ messages in thread
From: Xi Ruoyao @ 2023-08-18  7:05 UTC (permalink / raw)
  To: chenxiaolong, Joseph Myers; +Cc: gcc-patches, i, xuchenghua, chenglulu

On Fri, 2023-08-18 at 14:58 +0800, Xi Ruoyao via Gcc-patches wrote:
> On Fri, 2023-08-18 at 14:39 +0800, chenxiaolong wrote:
> > 在 2023-08-17四的 15:08 +0000,Joseph Myers写道:
> > > On Thu, 17 Aug 2023, Xi Ruoyao via Gcc-patches wrote:
> > > 
> > > > So I guess we just need
> > > > 
> > > > builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > > > builtin_define ("__builtin_nanq=__builtin_nanf128");
> > > > 
> > > > etc. to map the "q" builtins to "f128" builtins if we really need
> > > > the
> > > > "q" builtins.
> > > > 
> > > > Joseph: the problem here is many customers of LoongArch CPUs wish
> > > > to
> > > > compile their old code with minimal change.  Is it acceptable to
> > > > add
> > > > these builtin_define's like rs6000-c.cc?  Note "a new architecture"
> > > > does
> > > > not mean we'll only compile post-C2x-era programs onto it.
> > > 
> > > The powerpc support for __float128 started in GCC 6, predating the
> > > support 
> > > for _FloatN type names, built-in functions etc. in GCC 7 - that's
> > > why 
> > > there's such backwards compatibility support there.  That name only
> > > exists 
> > > on a few architectures.
> > > 
> > > If people really want to compile code using the old __float128 names
> > > for 
> > > LoongArch I suppose you could have such #defines, but it would be
> > > better 
> > > for people to make their code use the standard names (as supported
> > > from 
> > > GCC 7 onwards, though only from GCC 13 in C++) and then put
> > > backwards 
> > > compatibility in their code for using the __float128 names if they
> > > want to 
> > > support the type with older GCC (GCC 6 or before for C; GCC 12 or
> > > before 
> > > for C++) on x86_64 / i386 / powerpc / ia64.  Such backwards
> > > compatibility 
> > > in user code is more likely to be relevant for C++ than for C, given
> > > how 
> > > the C++ support was added to GCC much more recently.  (Note: I
> > > haven't 
> > > checked when other compilers added support for the _Float128 name or
> > > associated built-in functions, whether for C or for C++, which might
> > > also 
> > > affect when user code wants such compatibility.)
> > > 
> > Thank you for your valuable comments. On the LoongArch architecture,
> > the "__float128" type is associated with float128_type_node and the "q"
> > suffix function is mapped to the "f128" function. This allows
> > compatibility with both "__float128" and "_Float128" types in the GCC
> > compiler. The new code is modified as follows:
> >   Add the following to the loongarch-builtins.c file:
> > +lang_hooks.types.register_builtin_type (float128_type_node,
> > "__float128");
> >   Add the following to the loongarch-c.c file:
> > +builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > +builtin_define ("__builtin_copysignq=__builtin_copysignf128");
> > +builtin_define ("__builtin_nanq=__builtin_nanf128");
> > +builtin_define ("__builtin_nansq=__builtin_nansf128");
> > +builtin_define ("__builtin_infq=__builtin_inff128");
> > +builtin_define ("__builtin_huge_valq=__builtin_huge_valf128");
> > 
> >  The regression tests of the six functions were added without problems.
> > However, the implementation of the __builtin_nansq() function does not
> > get the result we want. The questions are as follows:
> >  x86_64:
> >     _Float128 ret=__builtin_nansf128("NAN");
> > 
> >     compiled to (with gcc test.c -O2 ):
> >                 .cfi_offset 1, -8
> >         bl      %plt(__builtin_nansf128)
> >         ..
> >  LoongArch:
> >     _Float128 ret=__builtin_nansf128("NAN");
> >       compiled to (with gcc test.c -O2 ):
> >         .cfi_offset 1, -8
> >         bl      %plt(__builtin_nansf128)
> 
> It seems wrong.  It should be "bl %plt(nansf128)" instead, without the
> __builtin_ prefix so the implementation in libm (from Glibc) will be
> used instead.  AFAIK __builtin_nan and __builtin_nans are rarely called
> with a non-empty tagp so it's not worthy to inline the implementation
> for non-empty tagp here.
> 
> The same issue happens on x86_64:
> 
> call    __builtin_nansf128@PLT
> 
> __builtin_nanf128 compiles correct:
> 
> call    nanf128@PLT
> 
> I'll see if there is a ticket in https://gcc.gnu.org/bugzilla.  If not
> I'll create one.

Alright, Glibc does not have a "nansf128" function yet.  Actually there
is even no "nans" function for the plain double type.  So even a plain
__builtin_nans("114") won't work too.

If we'll fix this, we need to do it in a generic, target-independent way
(i. e. fix it all at once for all targets).

So for now, and for LoongArch specific code, the proper thing to do is
aliasing float128_type_node as __float128 and the six
__builtin_define's.

Please commit them to trunk if regression test passes.  You need to also
add LoongArch as a target supporting __float128 in extend.texi.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-18  7:05           ` Xi Ruoyao
@ 2023-08-18  7:19             ` Xi Ruoyao
  2023-08-18  7:52               ` chenxiaolong
  0 siblings, 1 reply; 13+ messages in thread
From: Xi Ruoyao @ 2023-08-18  7:19 UTC (permalink / raw)
  To: chenxiaolong, Joseph Myers; +Cc: gcc-patches, i, xuchenghua, chenglulu

On Fri, 2023-08-18 at 15:05 +0800, Xi Ruoyao via Gcc-patches wrote:
> On Fri, 2023-08-18 at 14:58 +0800, Xi Ruoyao via Gcc-patches wrote:
> > On Fri, 2023-08-18 at 14:39 +0800, chenxiaolong wrote:
> > > 在 2023-08-17四的 15:08 +0000,Joseph Myers写道:
> > > > On Thu, 17 Aug 2023, Xi Ruoyao via Gcc-patches wrote:
> > > > 
> > > > > So I guess we just need
> > > > > 
> > > > > builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > > > > builtin_define ("__builtin_nanq=__builtin_nanf128");
> > > > > 
> > > > > etc. to map the "q" builtins to "f128" builtins if we really need
> > > > > the
> > > > > "q" builtins.
> > > > > 
> > > > > Joseph: the problem here is many customers of LoongArch CPUs wish
> > > > > to
> > > > > compile their old code with minimal change.  Is it acceptable to
> > > > > add
> > > > > these builtin_define's like rs6000-c.cc?  Note "a new architecture"
> > > > > does
> > > > > not mean we'll only compile post-C2x-era programs onto it.
> > > > 
> > > > The powerpc support for __float128 started in GCC 6, predating the
> > > > support 
> > > > for _FloatN type names, built-in functions etc. in GCC 7 - that's
> > > > why 
> > > > there's such backwards compatibility support there.  That name only
> > > > exists 
> > > > on a few architectures.
> > > > 
> > > > If people really want to compile code using the old __float128 names
> > > > for 
> > > > LoongArch I suppose you could have such #defines, but it would be
> > > > better 
> > > > for people to make their code use the standard names (as supported
> > > > from 
> > > > GCC 7 onwards, though only from GCC 13 in C++) and then put
> > > > backwards 
> > > > compatibility in their code for using the __float128 names if they
> > > > want to 
> > > > support the type with older GCC (GCC 6 or before for C; GCC 12 or
> > > > before 
> > > > for C++) on x86_64 / i386 / powerpc / ia64.  Such backwards
> > > > compatibility 
> > > > in user code is more likely to be relevant for C++ than for C, given
> > > > how 
> > > > the C++ support was added to GCC much more recently.  (Note: I
> > > > haven't 
> > > > checked when other compilers added support for the _Float128 name or
> > > > associated built-in functions, whether for C or for C++, which might
> > > > also 
> > > > affect when user code wants such compatibility.)
> > > > 
> > > Thank you for your valuable comments. On the LoongArch architecture,
> > > the "__float128" type is associated with float128_type_node and the "q"
> > > suffix function is mapped to the "f128" function. This allows
> > > compatibility with both "__float128" and "_Float128" types in the GCC
> > > compiler. The new code is modified as follows:
> > >   Add the following to the loongarch-builtins.c file:
> > > +lang_hooks.types.register_builtin_type (float128_type_node,
> > > "__float128");
> > >   Add the following to the loongarch-c.c file:
> > > +builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > > +builtin_define ("__builtin_copysignq=__builtin_copysignf128");
> > > +builtin_define ("__builtin_nanq=__builtin_nanf128");
> > > +builtin_define ("__builtin_nansq=__builtin_nansf128");
> > > +builtin_define ("__builtin_infq=__builtin_inff128");
> > > +builtin_define ("__builtin_huge_valq=__builtin_huge_valf128");
> > > 
> > >  The regression tests of the six functions were added without problems.
> > > However, the implementation of the __builtin_nansq() function does not
> > > get the result we want. The questions are as follows:
> > >  x86_64:
> > >     _Float128 ret=__builtin_nansf128("NAN");
> > > 
> > >     compiled to (with gcc test.c -O2 ):
> > >                 .cfi_offset 1, -8
> > >         bl      %plt(__builtin_nansf128)
> > >         ..
> > >  LoongArch:
> > >     _Float128 ret=__builtin_nansf128("NAN");
> > >       compiled to (with gcc test.c -O2 ):
> > >         .cfi_offset 1, -8
> > >         bl      %plt(__builtin_nansf128)
> > 
> > It seems wrong.  It should be "bl %plt(nansf128)" instead, without the
> > __builtin_ prefix so the implementation in libm (from Glibc) will be
> > used instead.  AFAIK __builtin_nan and __builtin_nans are rarely called
> > with a non-empty tagp so it's not worthy to inline the implementation
> > for non-empty tagp here.
> > 
> > The same issue happens on x86_64:
> > 
> > call    __builtin_nansf128@PLT
> > 
> > __builtin_nanf128 compiles correct:
> > 
> > call    nanf128@PLT
> > 
> > I'll see if there is a ticket in https://gcc.gnu.org/bugzilla.  If not
> > I'll create one.

https://gcc.gnu.org/PR111058

> Alright, Glibc does not have a "nansf128" function yet.  Actually there
> is even no "nans" function for the plain double type.  So even a plain
> __builtin_nans("114") won't work too.
> 
> If we'll fix this, we need to do it in a generic, target-independent way
> (i. e. fix it all at once for all targets).
> 
> So for now, and for LoongArch specific code, the proper thing to do is
> aliasing float128_type_node as __float128 and the six
> __builtin_define's.
> 
> Please commit them to trunk if regression test passes.  You need to also
> add LoongArch as a target supporting __float128 in extend.texi.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

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

* Re: [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc.
  2023-08-18  7:19             ` Xi Ruoyao
@ 2023-08-18  7:52               ` chenxiaolong
  0 siblings, 0 replies; 13+ messages in thread
From: chenxiaolong @ 2023-08-18  7:52 UTC (permalink / raw)
  To: Xi Ruoyao, Joseph Myers; +Cc: gcc-patches, i, xuchenghua, chenglulu

在 2023-08-18五的 15:19 +0800,Xi Ruoyao写道:
> On Fri, 2023-08-18 at 15:05 +0800, Xi Ruoyao via Gcc-patches wrote:
> > On Fri, 2023-08-18 at 14:58 +0800, Xi Ruoyao via Gcc-patches wrote:
> > > On Fri, 2023-08-18 at 14:39 +0800, chenxiaolong wrote:
> > > > 在 2023-08-17四的 15:08 +0000,Joseph Myers写道:
> > > > > On Thu, 17 Aug 2023, Xi Ruoyao via Gcc-patches wrote:
> > > > > 
> > > > > > So I guess we just need
> > > > > > 
> > > > > > builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > > > > > builtin_define ("__builtin_nanq=__builtin_nanf128");
> > > > > > 
> > > > > > etc. to map the "q" builtins to "f128" builtins if we
> > > > > > really need
> > > > > > the
> > > > > > "q" builtins.
> > > > > > 
> > > > > > Joseph: the problem here is many customers of LoongArch
> > > > > > CPUs wish
> > > > > > to
> > > > > > compile their old code with minimal change.  Is it
> > > > > > acceptable to
> > > > > > add
> > > > > > these builtin_define's like rs6000-c.cc?  Note "a new
> > > > > > architecture"
> > > > > > does
> > > > > > not mean we'll only compile post-C2x-era programs onto it.
> > > > > 
> > > > > The powerpc support for __float128 started in GCC 6,
> > > > > predating the
> > > > > support 
> > > > > for _FloatN type names, built-in functions etc. in GCC 7 -
> > > > > that's
> > > > > why 
> > > > > there's such backwards compatibility support there.  That
> > > > > name only
> > > > > exists 
> > > > > on a few architectures.
> > > > > 
> > > > > If people really want to compile code using the old
> > > > > __float128 names
> > > > > for 
> > > > > LoongArch I suppose you could have such #defines, but it
> > > > > would be
> > > > > better 
> > > > > for people to make their code use the standard names (as
> > > > > supported
> > > > > from 
> > > > > GCC 7 onwards, though only from GCC 13 in C++) and then put
> > > > > backwards 
> > > > > compatibility in their code for using the __float128 names if
> > > > > they
> > > > > want to 
> > > > > support the type with older GCC (GCC 6 or before for C; GCC
> > > > > 12 or
> > > > > before 
> > > > > for C++) on x86_64 / i386 / powerpc / ia64.  Such backwards
> > > > > compatibility 
> > > > > in user code is more likely to be relevant for C++ than for
> > > > > C, given
> > > > > how 
> > > > > the C++ support was added to GCC much more recently.  (Note:
> > > > > I
> > > > > haven't 
> > > > > checked when other compilers added support for the _Float128
> > > > > name or
> > > > > associated built-in functions, whether for C or for C++,
> > > > > which might
> > > > > also 
> > > > > affect when user code wants such compatibility.)
> > > > > 
> > > > Thank you for your valuable comments. On the LoongArch
> > > > architecture,
> > > > the "__float128" type is associated with float128_type_node and
> > > > the "q"
> > > > suffix function is mapped to the "f128" function. This allows
> > > > compatibility with both "__float128" and "_Float128" types in
> > > > the GCC
> > > > compiler. The new code is modified as follows:
> > > >   Add the following to the loongarch-builtins.c file:
> > > > +lang_hooks.types.register_builtin_type (float128_type_node,
> > > > "__float128");
> > > >   Add the following to the loongarch-c.c file:
> > > > +builtin_define ("__builtin_fabsq=__builtin_fabsf128");
> > > > +builtin_define ("__builtin_copysignq=__builtin_copysignf128");
> > > > +builtin_define ("__builtin_nanq=__builtin_nanf128");
> > > > +builtin_define ("__builtin_nansq=__builtin_nansf128");
> > > > +builtin_define ("__builtin_infq=__builtin_inff128");
> > > > +builtin_define ("__builtin_huge_valq=__builtin_huge_valf128");
> > > > 
> > > >  The regression tests of the six functions were added without
> > > > problems.
> > > > However, the implementation of the __builtin_nansq() function
> > > > does not
> > > > get the result we want. The questions are as follows:
> > > >  x86_64:
> > > >     _Float128 ret=__builtin_nansf128("NAN");
> > > > 
> > > >     compiled to (with gcc test.c -O2 ):
> > > >                 .cfi_offset 1, -8
> > > >         bl      %plt(__builtin_nansf128)
> > > >         ..
> > > >  LoongArch:
> > > >     _Float128 ret=__builtin_nansf128("NAN");
> > > >       compiled to (with gcc test.c -O2 ):
> > > >         .cfi_offset 1, -8
> > > >         bl      %plt(__builtin_nansf128)
> > > 
> > > It seems wrong.  It should be "bl %plt(nansf128)" instead,
> > > without the
> > > __builtin_ prefix so the implementation in libm (from Glibc) will
> > > be
> > > used instead.  AFAIK __builtin_nan and __builtin_nans are rarely
> > > called
> > > with a non-empty tagp so it's not worthy to inline the
> > > implementation
> > > for non-empty tagp here.
> > > 
> > > The same issue happens on x86_64:
> > > 
> > > call    __builtin_nansf128@PLT
> > > 
> > > __builtin_nanf128 compiles correct:
> > > 
> > > call    nanf128@PLT
> > > 
> > > I'll see if there is a ticket in https://gcc.gnu.org/bugzilla. 
> > > If not
> > > I'll create one.
> 
> https://gcc.gnu.org/PR111058
> 
> > Alright, Glibc does not have a "nansf128" function yet.  Actually
> > there
> > is even no "nans" function for the plain double type.  So even a
> > plain
> > __builtin_nans("114") won't work too.
> > 
> > If we'll fix this, we need to do it in a generic, target-
> > independent way
> > (i. e. fix it all at once for all targets).
> > 
> > So for now, and for LoongArch specific code, the proper thing to do
> > is
> > aliasing float128_type_node as __float128 and the six
> > __builtin_define's.
> > 
> > Please commit them to trunk if regression test passes.  You need to
> > also
> > add LoongArch as a target supporting __float128 in extend.texi.

Ok, I will properly analyze the implementation of the buildin relatedfunctions and fix this issue as soon as possible.



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

end of thread, other threads:[~2023-08-18  7:52 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-15 10:39 [PATCH v3] LoongArch:Implement 128-bit floating point functions in gcc chenxiaolong
2023-08-15 10:48 ` Xi Ruoyao
2023-08-17  6:56   ` chenxiaolong
2023-08-15 20:03 ` Joseph Myers
2023-08-16 10:08   ` chenxiaolong
2023-08-16 13:16     ` Joseph Myers
2023-08-17  3:44   ` Xi Ruoyao
2023-08-17 15:08     ` Joseph Myers
2023-08-18  6:39       ` chenxiaolong
2023-08-18  6:58         ` Xi Ruoyao
2023-08-18  7:05           ` Xi Ruoyao
2023-08-18  7:19             ` Xi Ruoyao
2023-08-18  7:52               ` chenxiaolong

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).