From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id 05D573858426; Tue, 10 Jan 2023 18:08:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 05D573858426 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1673374085; bh=mPakWRGdctzJmrkkbQy3t+I05+eyxrkcKDicsR9HKFw=; h=From:To:Subject:Date:From; b=Xf6WbhhB/EGaEk03MBW9q823FQpVzkhv4+qcHfgVQzNvJYmm2jZz9BGiIk4EOjizp kMR1xztZRo2qOnZoIc3S3FI36pIqP0iXceq6jufmhe/y6wY4CU5a81Sp8Bcj5qa7Pf QeJmCg82H6r7kUQKBpO0aQzulg4huE52pztNaa7c= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Michael Meissner To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/meissner/heads/work104)] Revert patches X-Act-Checkin: gcc X-Git-Author: Michael Meissner X-Git-Refname: refs/users/meissner/heads/work104 X-Git-Oldrev: f2a38b7bb46edabf3e659cf15f90482e1b4a7fc6 X-Git-Newrev: 8f9fd3afd7a1bf5f9b4b4e9f85c7aab79c091ac1 Message-Id: <20230110180805.05D573858426@sourceware.org> Date: Tue, 10 Jan 2023 18:08:04 +0000 (GMT) List-Id: https://gcc.gnu.org/g:8f9fd3afd7a1bf5f9b4b4e9f85c7aab79c091ac1 commit 8f9fd3afd7a1bf5f9b4b4e9f85c7aab79c091ac1 Author: Michael Meissner Date: Tue Jan 10 13:07:59 2023 -0500 Revert patches Diff: --- gcc/config/rs6000/rs6000-modes.def | 50 ++++---- gcc/config/rs6000/rs6000-modes.h | 36 ++++++ gcc/config/rs6000/rs6000.cc | 124 +++++++++---------- gcc/config/rs6000/rs6000.h | 5 + gcc/config/rs6000/rs6000.md | 177 ++++++++++++++++++++-------- gcc/config/rs6000/rs6000.opt | 8 -- gcc/config/rs6000/t-rs6000 | 1 + gcc/expr.cc | 6 +- gcc/genmodes.cc | 106 +++-------------- gcc/machmode.def | 13 +- gcc/machmode.h | 2 +- gcc/testsuite/gcc.target/powerpc/divic3-1.c | 18 --- gcc/testsuite/gcc.target/powerpc/divic3-2.c | 17 --- gcc/testsuite/gcc.target/powerpc/mulic3-1.c | 18 --- gcc/testsuite/gcc.target/powerpc/mulic3-2.c | 17 --- gcc/tree.cc | 9 ++ 16 files changed, 286 insertions(+), 321 deletions(-) diff --git a/gcc/config/rs6000/rs6000-modes.def b/gcc/config/rs6000/rs6000-modes.def index c3c2905525e..8ef910869c5 100644 --- a/gcc/config/rs6000/rs6000-modes.def +++ b/gcc/config/rs6000/rs6000-modes.def @@ -18,39 +18,39 @@ along with GCC; see the file COPYING3. If not see . */ -/* We mark IFmode and KFmode as being types that are not in the mode_wider and - mode_2xwider tables. Thus these types will never automatically be widened - to when the compiler can't perform an operation in a smaller mode. Also, - the float_mode_for_size function will only return TFmode if the size is 128 - bits. */ - -/* Fortran needs to have precisions of 126..128 to differentiate between IEEE - and IBM 128-bit floating point. The values used here are what GCC 12 used - for the precisions. */ -#define UNIQUE_PRECISION_IFmode 128 -#define UNIQUE_PRECISION_TFmode 127 -#define UNIQUE_PRECISION_KFmode 126 +/* We order the 3 128-bit floating point types so that IFmode (IBM 128-bit + floating point) is the 128-bit floating point type with the highest + precision (128 bits). This so that machine independent parts of the + compiler do not try to widen IFmode to TFmode on ISA 3.0 (power9) that has + hardware support for IEEE 128-bit. We set TFmode (long double mode) in + between, and KFmode (explicit __float128) below it. + + Previously, IFmode and KFmode were defined to be fractional modes and TFmode + was the standard mode. Since IFmode does not define the normal arithmetic + insns (other than neg/abs), on a ISA 3.0 system, the machine independent + parts of the compiler would see that TFmode has the necessary hardware + support, and widen the operation from IFmode to TFmode. However, IEEE + 128-bit is not strictly a super-set of IBM extended double and the + conversion to/from IEEE 128-bit was a function call. + + We now make IFmode the highest fractional mode, which means its values are + not considered for widening. Since we don't define insns for IFmode, the + IEEE 128-bit modes would not widen to IFmode. */ + +#ifndef RS6000_MODES_H +#include "config/rs6000/rs6000-modes.h" +#endif /* IBM 128-bit floating point. */ -FRACTIONAL_FLOAT_MODE_NO_WIDEN (IF, 128, 16, ibm_extended_format); -ADJUST_PRECISION (IF, - UNIQUE_FLOAT128_PRECISION ? UNIQUE_PRECISION_IFmode : 128); +FRACTIONAL_FLOAT_MODE (IF, FLOAT_PRECISION_IFmode, 16, ibm_extended_format); /* Explicit IEEE 128-bit floating point. */ -FRACTIONAL_FLOAT_MODE_NO_WIDEN (KF, 128, 16, ieee_quad_format); -ADJUST_PRECISION (KF, - UNIQUE_FLOAT128_PRECISION ? UNIQUE_PRECISION_KFmode : 128); +FRACTIONAL_FLOAT_MODE (KF, FLOAT_PRECISION_KFmode, 16, ieee_quad_format); /* 128-bit floating point, either IBM 128-bit or IEEE 128-bit. This is adjusted in rs6000_option_override_internal to be the appropriate floating point type. */ -FRACTIONAL_FLOAT_MODE (TF, 128, 16, ieee_quad_format); -ADJUST_PRECISION (TF, - UNIQUE_FLOAT128_PRECISION ? UNIQUE_PRECISION_TFmode : 128); - -ADJUST_FLOAT_FORMAT (TF, (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD - ? &ibm_extended_format - : &ieee_quad_format)); +FRACTIONAL_FLOAT_MODE (TF, FLOAT_PRECISION_TFmode, 16, ieee_quad_format); /* Add any extra modes needed to represent the condition code. diff --git a/gcc/config/rs6000/rs6000-modes.h b/gcc/config/rs6000/rs6000-modes.h new file mode 100644 index 00000000000..64abf886db3 --- /dev/null +++ b/gcc/config/rs6000/rs6000-modes.h @@ -0,0 +1,36 @@ +/* Definitions 128-bit floating point precisions used by PowerPC. + Copyright (C) 2018-2022 Free Software Foundation, Inc. + Contributed by Michael Meissner (meissner@linux.ibm.com) + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + . */ + +/* We order the 3 128-bit floating point types so that IFmode (IBM 128-bit + floating point) is the 128-bit floating point type with the highest + precision (128 bits). This so that machine independent parts of the + compiler do not try to widen IFmode to TFmode on ISA 3.0 (power9) that has + hardware support for IEEE 128-bit. We set TFmode (long double mode) in + between, and KFmode (explicit __float128) below it. + + We won't encounter conversion from IEEE 128-bit to IBM 128-bit because we + don't have insns to support the IBM 128-bit aritmetic operations. */ + +#ifndef RS6000_MODES_H +#define RS6000_MODES_H 1 +#define FLOAT_PRECISION_IFmode 128 +#define FLOAT_PRECISION_TFmode 127 +#define FLOAT_PRECISION_KFmode 126 +#endif /* RS6000_MODES_H */ diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 15cefd4e4c1..6ac3adcec6b 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -4115,7 +4115,7 @@ rs6000_option_override_internal (bool global_init_p) 128 into the precision used for TFmode. */ int default_long_double_size = (RS6000_DEFAULT_LONG_DOUBLE_SIZE == 64 ? 64 - : 128); + : FLOAT_PRECISION_TFmode); /* Set long double size before the IEEE 128-bit tests. */ if (!OPTION_SET_P (rs6000_long_double_type_size)) @@ -4127,6 +4127,10 @@ rs6000_option_override_internal (bool global_init_p) else rs6000_long_double_type_size = default_long_double_size; } + else if (rs6000_long_double_type_size == FLOAT_PRECISION_TFmode) + ; /* The option value can be seen when cl_target_option_restore is called. */ + else if (rs6000_long_double_type_size == 128) + rs6000_long_double_type_size = FLOAT_PRECISION_TFmode; /* Set -mabi=ieeelongdouble on some old targets. In the future, power server systems will also set long double to be IEEE 128-bit. AIX and Darwin @@ -4169,10 +4173,6 @@ rs6000_option_override_internal (bool global_init_p) the keyword as well as the type. */ TARGET_FLOAT128_TYPE = TARGET_FLOAT128_ENABLE_TYPE && TARGET_VSX; -/* Fortran needs to have precisions of 126..128 to differentiate between IEEE - and IBM 128-bit floating point. */ - UNIQUE_FLOAT128_PRECISION = lang_GNU_Fortran (); - /* IEEE 128-bit floating point requires VSX support. */ if (TARGET_FLOAT128_KEYWORD) { @@ -4562,6 +4562,9 @@ rs6000_option_override_internal (bool global_init_p) flag_signed_bitfields = 0; #endif + if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD) + REAL_MODE_FORMAT (TFmode) = &ibm_extended_format; + ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1); /* We can only guarantee the availability of DI pseudo-ops when @@ -11142,6 +11145,26 @@ init_float128_ibm (machine_mode mode) } } +/* Create a decl for either complex long double multiply or complex long double + divide when long double is IEEE 128-bit floating point. We can't use + __multc3 and __divtc3 because the original long double using IBM extended + double used those names. The complex multiply/divide functions are encoded + as builtin functions with a complex result and 4 scalar inputs. */ + +static void +create_complex_muldiv (const char *name, built_in_function fncode, tree fntype) +{ + tree fndecl = add_builtin_function (name, fntype, fncode, BUILT_IN_NORMAL, + name, NULL_TREE); + + set_builtin_decl (fncode, fndecl, true); + + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "create complex %s, fncode: %d\n", name, (int) fncode); + + return; +} + /* Set up IEEE 128-bit floating point routines. Use different names if the arguments can be passed in a vector register. The historical PowerPC implementation of IEEE 128-bit floating point used _q_ for the names, so @@ -11153,6 +11176,32 @@ init_float128_ieee (machine_mode mode) { if (FLOAT128_VECTOR_P (mode)) { + static bool complex_muldiv_init_p = false; + + /* Set up to call __mulkc3 and __divkc3 under -mabi=ieeelongdouble. If + we have clone or target attributes, this will be called a second + time. We want to create the built-in function only once. */ + if (mode == TFmode && TARGET_IEEEQUAD && !complex_muldiv_init_p) + { + complex_muldiv_init_p = true; + built_in_function fncode_mul = + (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + TCmode + - MIN_MODE_COMPLEX_FLOAT); + built_in_function fncode_div = + (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + TCmode + - MIN_MODE_COMPLEX_FLOAT); + + tree fntype = build_function_type_list (complex_long_double_type_node, + long_double_type_node, + long_double_type_node, + long_double_type_node, + long_double_type_node, + NULL_TREE); + + create_complex_muldiv ("__mulkc3", fncode_mul, fntype); + create_complex_muldiv ("__divkc3", fncode_div, fntype); + } + set_optab_libfunc (add_optab, mode, "__addkf3"); set_optab_libfunc (sub_optab, mode, "__subkf3"); set_optab_libfunc (neg_optab, mode, "__negkf2"); @@ -11179,7 +11228,7 @@ init_float128_ieee (machine_mode mode) if (mode != TFmode && FLOAT128_IBM_P (TFmode)) set_conv_libfunc (sext_optab, mode, TFmode, "__trunctfkf2"); - set_conv_libfunc (sext_optab, IFmode, mode, "__extendkftf2"); + set_conv_libfunc (trunc_optab, IFmode, mode, "__extendkftf2"); if (mode != TFmode && FLOAT128_IBM_P (TFmode)) set_conv_libfunc (trunc_optab, TFmode, mode, "__extendkftf2"); @@ -28170,25 +28219,6 @@ rs6000_starting_frame_offset (void) return RS6000_STARTING_FRAME_OFFSET; } -/* Internal function to return the built-in function id for the complex - multiply operation for a given mode. */ - -static inline built_in_function -complex_multiply_builtin_code (machine_mode mode) -{ - return (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + mode - - MIN_MODE_COMPLEX_FLOAT); -} - -/* Internal function to return the built-in function id for the complex divide - operation for a given mode. */ - -static inline built_in_function -complex_divide_builtin_code (machine_mode mode) -{ - return (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + mode - - MIN_MODE_COMPLEX_FLOAT); -} /* On 64-bit Linux and Freebsd systems, possibly switch the long double library function names from l to f128 if the default long double type is @@ -28207,53 +28237,11 @@ complex_divide_builtin_code (machine_mode mode) only do this transformation if the __float128 type is enabled. This prevents us from doing the transformation on older 32-bit ports that might have enabled using IEEE 128-bit floating point as the default long double - type. - - We also use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change the - function names used for complex multiply and divide to the appropriate - names. */ + type. */ static tree rs6000_mangle_decl_assembler_name (tree decl, tree id) { - /* Handle complex multiply/divide. For IEEE 128-bit, use __mulkc3 or - __divkc3 and for IBM 128-bit use __multc3 and __divtc3. */ - if (TARGET_FLOAT128_TYPE - && TREE_CODE (decl) == FUNCTION_DECL - && DECL_IS_UNDECLARED_BUILTIN (decl) - && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL) - { - built_in_function id = DECL_FUNCTION_CODE (decl); - const char *newname = NULL; - - if (id == complex_multiply_builtin_code (KCmode)) - newname = "__mulkc3"; - - else if (id == complex_multiply_builtin_code (ICmode)) - newname = "__multc3"; - - else if (id == complex_multiply_builtin_code (TCmode)) - newname = (TARGET_IEEEQUAD) ? "__mulkc3" : "__multc3"; - - else if (id == complex_divide_builtin_code (KCmode)) - newname = "__divkc3"; - - else if (id == complex_divide_builtin_code (ICmode)) - newname = "__divtc3"; - - else if (id == complex_divide_builtin_code (TCmode)) - newname = (TARGET_IEEEQUAD) ? "__divkc3" : "__divtc3"; - - if (newname) - { - if (TARGET_DEBUG_BUILTIN) - fprintf (stderr, "Map complex mul/div => %s\n", newname); - - return get_identifier (newname); - } - } - - /* Map long double built-in functions if long double is IEEE 128-bit. */ if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 && TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_UNDECLARED_BUILTIN (decl) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 440ab55a067..b4df22b6030 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -30,6 +30,11 @@ #include "config/rs6000/rs6000-opts.h" #endif +/* 128-bit floating point precision values. */ +#ifndef RS6000_MODES_H +#include "config/rs6000/rs6000-modes.h" +#endif + /* Definitions for the object file format. These are set at compile-time. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 203d0ba6a7f..3cae64a264a 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -543,6 +543,12 @@ ; Iterator for 128-bit VSX types for pack/unpack (define_mode_iterator FMOVE128_VSX [V1TI KF]) +; Iterators for converting to/from TFmode +(define_mode_iterator IFKF [IF KF]) + +; Constraints for moving IF/KFmode. +(define_mode_attr IFKF_reg [(IF "d") (KF "wa")]) + ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") (DF "") @@ -9155,65 +9161,106 @@ "xxlor %x0,%x1,%x2" [(set_attr "type" "veclogical")]) -;; Float128 conversion functions. We only define the 'conversions' between two -;; formats that use the same representation. We call the library function to -;; convert between IEEE 128-bit and IBM 128-bit. We can't do these moves by -;; using a SUBREG before register allocation. We set up the moves to prefer -;; the output register being the same as the input register, which would enable -;; the move to be deleted completely. -(define_insn_and_split "extendkftf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "=wa,wa") - (float_extend:TF (match_operand:KF 1 "gpc_reg_operand" "0,wa")))] - "TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (TFmode)" - "#" - "&& reload_completed" - [(set (match_dup 0) - (match_dup 2))] +;; Float128 conversion functions. These expand to library function calls. +;; We use expand to convert from IBM double double to IEEE 128-bit +;; and trunc for the opposite. +(define_expand "extendiftf2" + [(set (match_operand:TF 0 "gpc_reg_operand") + (float_extend:TF (match_operand:IF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" { - operands[2] = gen_lowpart (TFmode, operands[1]); -} - [(set_attr "type" "veclogical")]) + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) -(define_insn_and_split "trunctfkf2" - [(set (match_operand:KF 0 "gpc_reg_operand" "=wa,wa") - (float_truncate:KF (match_operand:TF 1 "gpc_reg_operand" "0,wa")))] - "TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (TFmode)" - "#" - "&& reload_completed" - [(set (match_dup 0) - (match_dup 2))] +(define_expand "extendifkf2" + [(set (match_operand:KF 0 "gpc_reg_operand") + (float_extend:KF (match_operand:IF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" { - operands[2] = gen_lowpart (KFmode, operands[1]); -} - [(set_attr "type" "veclogical")]) + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "extendtfkf2" + [(set (match_operand:KF 0 "gpc_reg_operand") + (float_extend:KF (match_operand:TF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "extendtfif2" + [(set (match_operand:IF 0 "gpc_reg_operand") + (float_extend:IF (match_operand:TF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "trunciftf2" + [(set (match_operand:TF 0 "gpc_reg_operand") + (float_truncate:TF (match_operand:IF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "truncifkf2" + [(set (match_operand:KF 0 "gpc_reg_operand") + (float_truncate:KF (match_operand:IF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "trunckftf2" + [(set (match_operand:TF 0 "gpc_reg_operand") + (float_truncate:TF (match_operand:KF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "trunctfif2" + [(set (match_operand:IF 0 "gpc_reg_operand") + (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand")))] + "TARGET_FLOAT128_TYPE" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) -(define_insn_and_split "extendtfif2" - [(set (match_operand:IF 0 "gpc_reg_operand" "=wa,wa,r,r") - (float_extend:IF (match_operand:TF 1 "gpc_reg_operand" "0,wa,0,r")))] - "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)" +(define_insn_and_split "*extendtf2_internal" + [(set (match_operand:TF 0 "gpc_reg_operand" "=") + (float_extend:TF + (match_operand:IFKF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128_TYPE + && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (mode)" "#" "&& reload_completed" - [(set (match_dup 0) - (match_dup 2))] + [(set (match_dup 0) (match_dup 2))] { - operands[2] = gen_lowpart (IFmode, operands[1]); -} - [(set_attr "num_insns" "2") - (set_attr "length" "8")]) + operands[2] = gen_rtx_REG (TFmode, REGNO (operands[1])); +}) -(define_insn_and_split "extendiftf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "=wa,wa,r,r") - (float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "0,wa,0,r")))] - "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)" +(define_insn_and_split "*extendtf2_internal" + [(set (match_operand:IFKF 0 "gpc_reg_operand" "=") + (float_extend:IFKF + (match_operand:TF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128_TYPE + && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (mode)" "#" "&& reload_completed" - [(set (match_dup 0) - (match_dup 2))] + [(set (match_dup 0) (match_dup 2))] { - operands[2] = gen_lowpart (TFmode, operands[1]); -} - [(set_attr "num_insns" "2") - (set_attr "length" "8")]) + operands[2] = gen_rtx_REG (mode, REGNO (operands[1])); +}) ;; Reload helper functions used by rs6000_secondary_reload. The patterns all @@ -14936,6 +14983,40 @@ [(set_attr "type" "vecfloat") (set_attr "size" "128")]) +;; Conversion between KFmode and TFmode if TFmode is ieee 128-bit floating +;; point is a simple copy. +(define_insn_and_split "extendkftf2" + [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa") + (float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))] + "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD" + "@ + # + xxlor %x0,%x1,%x1" + "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])" + [(const_int 0)] +{ + emit_note (NOTE_INSN_DELETED); + DONE; +} + [(set_attr "type" "*,veclogical") + (set_attr "length" "0,4")]) + +(define_insn_and_split "trunctfkf2" + [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa") + (float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))] + "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD" + "@ + # + xxlor %x0,%x1,%x1" + "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])" + [(const_int 0)] +{ + emit_note (NOTE_INSN_DELETED); + DONE; +} + [(set_attr "type" "*,veclogical") + (set_attr "length" "0,4")]) + (define_insn "truncdf2_hw" [(set (match_operand:DF 0 "altivec_register_operand" "=v") (float_truncate:DF diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index cab848c9836..b63a5d443af 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -108,14 +108,6 @@ unsigned char x_TARGET_FLOAT128_TYPE Variable unsigned char TARGET_FLOAT128_TYPE -;; Whether each of the 3 128-bit floating point modes (IFmode, KFmode, and -;; TFmode) have a unique precision number, or whether they all use 128. C -;; and C++ prefer the precision to be 128, but fortran prefers to have -;; separate precisions to differentiate between IBM and IEEE 128-bit floating -;; point. -TargetVariable -bool UNIQUE_FLOAT128_PRECISION - ;; This option existed in the past, but now is always on. mpowerpc Target RejectNegative Undocumented Ignore diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000 index 72bf66dddf2..597cea423ec 100644 --- a/gcc/config/rs6000/t-rs6000 +++ b/gcc/config/rs6000/t-rs6000 @@ -19,6 +19,7 @@ # . TM_H += $(srcdir)/config/rs6000/rs6000-cpus.def +TM_H += $(srcdir)/config/rs6000/rs6000-modes.h PASSES_EXTRA += $(srcdir)/config/rs6000/rs6000-passes.def EXTRA_GTYPE_DEPS += rs6000-builtins.h diff --git a/gcc/expr.cc b/gcc/expr.cc index c1c1e9729e8..15be1c8db99 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -345,8 +345,10 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp) != GET_MODE_PRECISION (to_mode)) || (DECIMAL_FLOAT_MODE_P (from_mode) != DECIMAL_FLOAT_MODE_P (to_mode)) - || (REAL_MODE_FORMAT (from_mode) - != REAL_MODE_FORMAT (to_mode))); + || (REAL_MODE_FORMAT (from_mode) == &arm_bfloat_half_format + && REAL_MODE_FORMAT (to_mode) == &ieee_half_format) + || (REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format + && REAL_MODE_FORMAT (from_mode) == &ieee_half_format)); if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode)) /* Conversion between decimal float and binary float, same size. */ diff --git a/gcc/genmodes.cc b/gcc/genmodes.cc index 8b18e907d85..2d418f09aab 100644 --- a/gcc/genmodes.cc +++ b/gcc/genmodes.cc @@ -79,10 +79,6 @@ struct mode_data adjustment */ unsigned int int_n; /* If nonzero, then __int will be defined */ bool boolean; - bool normal_widen; /* Whether the type should be listed in the - mode_wider and mode_2xwider tables. */ - bool need_precision_adj; /* true if this mode needs dynamic precision - adjustment */ }; static struct mode_data *modes[MAX_MODE_CLASS]; @@ -94,7 +90,7 @@ static const struct mode_data blank_mode = { 0, -1U, -1U, -1U, -1U, 0, 0, 0, 0, 0, 0, "", 0, 0, 0, 0, false, false, 0, - false, true, false + false }; static htab_t modes_by_name; @@ -118,7 +114,6 @@ static struct mode_adjust *adj_alignment; static struct mode_adjust *adj_format; static struct mode_adjust *adj_ibit; static struct mode_adjust *adj_fbit; -static struct mode_adjust *adj_precision; /* Mode class operations. */ static enum mode_class @@ -663,22 +658,18 @@ make_fixed_point_mode (enum mode_class cl, #define FLOAT_MODE(N, Y, F) FRACTIONAL_FLOAT_MODE (N, -1U, Y, F) #define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \ - make_float_mode (#N, B, Y, #F, __FILE__, __LINE__, true) -#define FRACTIONAL_FLOAT_MODE_NO_WIDEN(N, B, Y, F) \ - make_float_mode (#N, B, Y, #F, __FILE__, __LINE__, false) + make_float_mode (#N, B, Y, #F, __FILE__, __LINE__) static void make_float_mode (const char *name, unsigned int precision, unsigned int bytesize, const char *format, - const char *file, unsigned int line, - bool normal_widen) + const char *file, unsigned int line) { struct mode_data *m = new_mode (MODE_FLOAT, name, file, line); m->bytesize = bytesize; m->precision = precision; m->format = format; - m->normal_widen = normal_widen; } #define DECIMAL_FLOAT_MODE(N, Y, F) \ @@ -831,7 +822,6 @@ make_vector_mode (enum mode_class bclass, #define ADJUST_FLOAT_FORMAT(M, X) _ADD_ADJUST (format, M, X, FLOAT, FLOAT) #define ADJUST_IBIT(M, X) _ADD_ADJUST (ibit, M, X, ACCUM, UACCUM) #define ADJUST_FBIT(M, X) _ADD_ADJUST (fbit, M, X, FRACT, UACCUM) -#define ADJUST_PRECISION(M, X) _ADD_ADJUST (precision, M, X, FLOAT, FLOAT) static int bits_per_unit; static int max_bitsize_mode_any_int; @@ -881,13 +871,7 @@ create_modes (void) they have the same bytesize; this is the right thing because the precision must always be smaller than the bytesize * BITS_PER_UNIT. We don't have to do anything special to get this done -- an unset - precision shows up as (unsigned int)-1, i.e. UINT_MAX. - - If a mode is listed as no widen, sort it after the modes that are allowed as - widening types. This is for machine dependent floating point types that we - don't want to promotion. In particular on the PowerPC there are 2 different - 128-bit floating point types (IBM and IEEE) and there are values in each - type that can't be represented in the other type. */ + precision shows up as (unsigned int)-1, i.e. UINT_MAX. */ static int cmp_modes (const void *a, const void *b) { @@ -909,11 +893,6 @@ cmp_modes (const void *a, const void *b) else if (m->precision < n->precision) return -1; - if (!m->normal_widen && n->normal_widen) - return 1; - else if (m->normal_widen && !n->normal_widen) - return -1; - if (!m->component && !n->component) { if (m->counter < n->counter) @@ -1233,8 +1212,7 @@ extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\ unsigned short\n\ mode_unit_precision_inline (machine_mode mode)\n\ {\n\ - extern CONST_MODE_PRECISION unsigned short \n\ - mode_unit_precision[NUM_MACHINE_MODES];\n\ + extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];\n\ gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\ switch (mode)\n\ {"); @@ -1382,8 +1360,7 @@ enum machine_mode\n{"); /* I can't think of a better idea, can you? */ printf ("#define CONST_MODE_NUNITS%s\n", adj_nunits ? "" : " const"); - printf ("#define CONST_MODE_PRECISION%s\n", - adj_precision || adj_nunits ? "" : " const"); + printf ("#define CONST_MODE_PRECISION%s\n", adj_nunits ? "" : " const"); printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize || adj_nunits ? "" : " const"); printf ("#define CONST_MODE_UNIT_SIZE%s\n", adj_bytesize ? "" : " const"); @@ -1502,7 +1479,7 @@ emit_mode_precision (void) struct mode_data *m; print_maybe_const_decl ("%spoly_uint16_pod", "mode_precision", - "NUM_MACHINE_MODES", adj_precision || adj_nunits); + "NUM_MACHINE_MODES", adj_nunits); for_all_modes (c, m) if (m->precision != (unsigned int)-1) @@ -1564,20 +1541,17 @@ emit_mode_wider (void) { struct mode_data *m2 = 0; - if (m->normal_widen - && (m->cl == MODE_INT - || m->cl == MODE_PARTIAL_INT - || m->cl == MODE_FLOAT - || m->cl == MODE_DECIMAL_FLOAT - || m->cl == MODE_COMPLEX_FLOAT - || m->cl == MODE_FRACT - || m->cl == MODE_UFRACT - || m->cl == MODE_ACCUM - || m->cl == MODE_UACCUM)) + if (m->cl == MODE_INT + || m->cl == MODE_PARTIAL_INT + || m->cl == MODE_FLOAT + || m->cl == MODE_DECIMAL_FLOAT + || m->cl == MODE_COMPLEX_FLOAT + || m->cl == MODE_FRACT + || m->cl == MODE_UFRACT + || m->cl == MODE_ACCUM + || m->cl == MODE_UACCUM) for (m2 = m->wider; m2 && m2 != void_mode; m2 = m2->wider) { - if (!m2->normal_widen) - continue; if (m2->bytesize == m->bytesize && m2->precision == m->precision) continue; @@ -1602,8 +1576,6 @@ emit_mode_wider (void) m2 && m2 != void_mode; m2 = m2->wider) { - if (!m2->normal_widen) - continue; if (m2->bytesize < 2 * m->bytesize) continue; if (m->precision != (unsigned int) -1) @@ -1727,8 +1699,7 @@ emit_mode_unit_precision (void) int c; struct mode_data *m; - print_maybe_const_decl ("%sunsigned short", "mode_unit_precision", - "NUM_MACHINE_MODES", adj_precision); + print_decl ("unsigned short", "mode_unit_precision", "NUM_MACHINE_MODES"); for_all_modes (c, m) { @@ -1992,49 +1963,6 @@ emit_mode_adjustments (void) printf ("\n /* %s:%d */\n REAL_MODE_FORMAT (E_%smode) = %s;\n", a->file, a->line, a->mode->name, a->adjustment); - - /* Precision adjustments propagate too. */ - for (a = adj_precision; a; a = a->next) - { - printf ("\n /* %s:%d */\n s = %s;\n", - a->file, a->line, a->adjustment); - printf (" mode_precision[E_%smode] = s;\n", a->mode->name); - printf (" mode_unit_precision[E_%smode] = s;\n", a->mode->name); - - for (m = a->mode->contained; m; m = m->next_cont) - { - switch (m->cl) - { - case MODE_COMPLEX_INT: - case MODE_COMPLEX_FLOAT: - printf (" mode_precision[E_%smode] = 2*s;\n", m->name); - printf (" mode_unit_precision[E_%smode] = s;\n", m->name); - break; - - case MODE_VECTOR_BOOL: - /* Changes to BImode should not affect vector booleans. */ - break; - - case MODE_VECTOR_INT: - case MODE_VECTOR_FLOAT: - case MODE_VECTOR_FRACT: - case MODE_VECTOR_UFRACT: - case MODE_VECTOR_ACCUM: - case MODE_VECTOR_UACCUM: - printf (" mode_precision[E_%smode] = s;\n", m->name); - printf (" mode_unit_precision[E_%smode] = %d*s;\n", - m->name, m->ncomponents); - break; - - default: - internal_error ( - "mode %s is neither vector nor complex but contains %s", - m->name, a->mode->name); - /* NOTREACHED */ - } - } - } - puts ("}"); } diff --git a/gcc/machmode.def b/gcc/machmode.def index eb03fd88999..62e2ba10d45 100644 --- a/gcc/machmode.def +++ b/gcc/machmode.def @@ -90,12 +90,6 @@ along with GCC; see the file COPYING3. If not see storage, but with only PRECISION significant bits, using floating point format FORMAT. - FRACTIONAL_FLOAT_MODE_NO_WIDEN (MODE, PRECISION, BYTESIZE, FORMAT); - declares MODE to be of class FLOAT, BYTESIZE bytes wide in - storage, but with only PRECISION significant bits, using - floating point format FORMAT. Unlike FRACTIONAL_FLOAT_MODE, - MODE is not listed in the mode_wider and mode_2xwider tables. - DECIMAL_FLOAT_MODE (MODE, BYTESIZE, FORMAT); declares MODE to be of class DECIMAL_FLOAT and BYTESIZE bytes wide. All of the bits of its representation are significant. @@ -177,10 +171,9 @@ along with GCC; see the file COPYING3. If not see ADJUST_FLOAT_FORMAT (MODE, EXPR); ADJUST_IBIT (MODE, EXPR); ADJUST_FBIT (MODE, EXPR); - ADJUST_PRECISION (MODE, EXPR); - Arrange for the byte size, alignment, floating point format, ibit, fbit - or precision mode of MODE to be adjustable at run time. EXPR will be - executed once after processing all command line options, and should + Arrange for the byte size, alignment, floating point format, ibit, + or fbit of MODE to be adjustable at run time. EXPR will be executed + once after processing all command line options, and should evaluate to the desired byte size, alignment, format, ibit or fbit. Unlike a FORMAT argument, if you are adjusting a float format diff --git a/gcc/machmode.h b/gcc/machmode.h index e4e0caf9abb..f1865c1ef42 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -27,7 +27,7 @@ extern CONST_MODE_PRECISION poly_uint16_pod mode_precision[NUM_MACHINE_MODES]; extern const unsigned char mode_inner[NUM_MACHINE_MODES]; extern CONST_MODE_NUNITS poly_uint16_pod mode_nunits[NUM_MACHINE_MODES]; extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES]; -extern CONST_MODE_PRECISION unsigned short mode_unit_precision[NUM_MACHINE_MODES]; +extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES]; extern const unsigned char mode_next[NUM_MACHINE_MODES]; extern const unsigned char mode_wider[NUM_MACHINE_MODES]; extern const unsigned char mode_2xwider[NUM_MACHINE_MODES]; diff --git a/gcc/testsuite/gcc.target/powerpc/divic3-1.c b/gcc/testsuite/gcc.target/powerpc/divic3-1.c deleted file mode 100644 index 1cc6b1be904..00000000000 --- a/gcc/testsuite/gcc.target/powerpc/divic3-1.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ -/* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-require-effective-target longdouble128 } */ -/* { dg-require-effective-target ppc_float128_sw } */ -/* { dg-options "-O2 -mpower8-vector -mabi=ieeelongdouble -Wno-psabi" } */ - -/* Check that complex divide generates the right call for __ibm128 when long - double is IEEE 128-bit floating point. */ - -typedef _Complex long double c_ibm128_t __attribute__((mode(__IC__))); - -void -divide (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r) -{ - *p = *q / *r; -} - -/* { dg-final { scan-assembler "bl __divtc3" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/divic3-2.c b/gcc/testsuite/gcc.target/powerpc/divic3-2.c deleted file mode 100644 index 8ff342e0116..00000000000 --- a/gcc/testsuite/gcc.target/powerpc/divic3-2.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ -/* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-require-effective-target longdouble128 } */ -/* { dg-options "-O2 -mpower8-vector -mabi=ibmlongdouble -Wno-psabi" } */ - -/* Check that complex divide generates the right call for __ibm128 when long - double is IBM 128-bit floating point. */ - -typedef _Complex long double c_ibm128_t __attribute__((mode(__TC__))); - -void -divide (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r) -{ - *p = *q / *r; -} - -/* { dg-final { scan-assembler "bl __divtc3" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mulic3-1.c b/gcc/testsuite/gcc.target/powerpc/mulic3-1.c deleted file mode 100644 index 4cd773c4b06..00000000000 --- a/gcc/testsuite/gcc.target/powerpc/mulic3-1.c +++ /dev/null @@ -1,18 +0,0 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ -/* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-require-effective-target longdouble128 } */ -/* { dg-require-effective-target ppc_float128_sw } */ -/* { dg-options "-O2 -mpower8-vector -mabi=ieeelongdouble -Wno-psabi" } */ - -/* Check that complex multiply generates the right call for __ibm128 when long - double is IEEE 128-bit floating point. */ - -typedef _Complex long double c_ibm128_t __attribute__((mode(__IC__))); - -void -multiply (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r) -{ - *p = *q * *r; -} - -/* { dg-final { scan-assembler "bl __multc3" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mulic3-2.c b/gcc/testsuite/gcc.target/powerpc/mulic3-2.c deleted file mode 100644 index 36fe8bc3061..00000000000 --- a/gcc/testsuite/gcc.target/powerpc/mulic3-2.c +++ /dev/null @@ -1,17 +0,0 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ -/* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-require-effective-target longdouble128 } */ -/* { dg-options "-O2 -mpower8-vector -mabi=ibmlongdouble -Wno-psabi" } */ - -/* Check that complex multiply generates the right call for __ibm128 when long - double is IBM 128-bit floating point. */ - -typedef _Complex long double c_ibm128_t __attribute__((mode(__TC__))); - -void -multiply (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r) -{ - *p = *q * *r; -} - -/* { dg-final { scan-assembler "bl __multc3" } } */ diff --git a/gcc/tree.cc b/gcc/tree.cc index 46a3a742592..78b64ee98b3 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -9474,6 +9474,15 @@ build_common_tree_nodes (bool signed_char) if (!targetm.floatn_mode (n, extended).exists (&mode)) continue; int precision = GET_MODE_PRECISION (mode); + /* Work around the rs6000 KFmode having precision 113 not + 128. */ + const struct real_format *fmt = REAL_MODE_FORMAT (mode); + gcc_assert (fmt->b == 2 && fmt->emin + fmt->emax == 3); + int min_precision = fmt->p + ceil_log2 (fmt->emax - fmt->emin); + if (!extended) + gcc_assert (min_precision == n); + if (precision < min_precision) + precision = min_precision; FLOATN_NX_TYPE_NODE (i) = make_node (REAL_TYPE); TYPE_PRECISION (FLOATN_NX_TYPE_NODE (i)) = precision; layout_type (FLOATN_NX_TYPE_NODE (i));