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 <xry...@xry111.site> School of Aerospace Science and Technology, Xidian University