diff mbox series

[09/52] Replace {FLOAT, {, LONG_}DOUBLE}_TYPE_SIZE with new hook mode_for_floating_type

Message ID f9227ec78e18c99ef94405fe46a8373156869a5f.1717134752.git.linkw@linux.ibm.com
State New
Headers show
Series Replace {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE with new hook | expand

Commit Message

Kewen.Lin June 3, 2024, 3 a.m. UTC
Currently how we determine which mode will be used for a
floating point type is that for a given type precision
(size) call mode_for_size to get the first mode which has
this size in the specified class.  On Powerpc, we have
three modes (TF/KF/IF) having the same mode precision 128
(see[1]), so the processing forces us to have to place TF
at the first place, it would require us to make more
adjustment in some generic code to avoid some unexpected
mode conversions and it would be even worse if we get rid
of TF eventually one day.  And as Joseph pointed out in [2],
"floating types should have their mode, not a poorly
defined precision value", as Joseph and Richi suggested,
this patch is to introduce one hook mode_for_floating_type
which returns the corresponding mode for type float, double
or long double.  The default implementation returns SFmode
for float and DFmode for double or long double.  For ports
which need special treatment, there are some other patches
for their own port specific implementation (referring to
how {,LONG_}DOUBLE_TYPE_SIZE get used there).  For all
generic uses of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE, depending
on the context, some of them are replaced with TYPE_PRECISION
of the according type node, some other are replaced with
GET_MODE_PRECISION on the mode from mode_for_floating_type.
This patch also poisons {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE,
so most defines of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE in port
specific are removed, but there are still some which are
good to be kept for readability then they get renamed with
port specific prefix.

[1] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651017.html
[2] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651209.html

gcc/ChangeLog:

	* coretypes.h (enum tree_index): Forward declaration.
	* defaults.h (FLOAT_TYPE_SIZE): Remove.
	(DOUBLE_TYPE_SIZE): Likewise.
	(LONG_DOUBLE_TYPE_SIZE): Likewise.
	* doc/rtl.texi: Update document by replacing {FLOAT,DOUBLE}_TYPE_SIZE
	with C type {float,double}.
	* doc/tm.texi.in: Document new hook mode_for_floating_type, remove
	document entries for {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE and
	update document for WIDEST_HARDWARE_FP_SIZE.
	* doc/tm.texi: Regenerate.
	* emit-rtl.cc (init_emit_once): Replace DOUBLE_TYPE_SIZE by
	calling targetm.c.mode_for_floating_type with TI_DOUBLE_TYPE.
	* real.h (REAL_VALUE_TO_TARGET_LONG_DOUBLE): Use TYPE_PRECISION of
	long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE.
	* system.h (FLOAT_TYPE_SIZE): Poison.
	(DOUBLE_TYPE_SIZE): Likewise.
	(LONG_DOUBLE_TYPE_SIZE): Likewise.
	* target.def (mode_for_floating_type): New hook.
	* targhooks.cc (default_mode_for_floating_type): New function.
	(default_scalar_mode_supported_p): Update macros
	{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE by calling
	targetm.c.mode_for_floating_type with
	TI_{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE.
	* targhooks.h (default_mode_for_floating_type): New declaration.
	* tree-core.h (enum tree_index): Specify underlying type unsigned
	to sync with forward declaration in coretypes.h.
	(NUM_FLOATN_TYPES): Explicitly convert to int.
	(NUM_FLOATNX_TYPES): Likewise.
	(NUM_FLOATN_NX_TYPES): Likewise.
	* tree.cc (build_common_tree_nodes): Update macros
	{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE by calling
	targetm.c.mode_for_floating_type with
	TI_{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE and set type mode accordingly.
---
 gcc/coretypes.h    |  1 +
 gcc/defaults.h     | 12 ------------
 gcc/doc/rtl.texi   |  2 +-
 gcc/doc/tm.texi    | 33 +++++++++++++--------------------
 gcc/doc/tm.texi.in | 27 +++++++--------------------
 gcc/emit-rtl.cc    |  3 ++-
 gcc/real.h         |  7 ++++---
 gcc/system.h       |  3 ++-
 gcc/target.def     |  9 +++++++++
 gcc/targhooks.cc   | 18 +++++++++++++++---
 gcc/targhooks.h    |  1 +
 gcc/tree-core.h    | 13 +++++++------
 gcc/tree.cc        | 18 +++++++++++++++---
 13 files changed, 77 insertions(+), 70 deletions(-)

Comments

Richard Biener June 3, 2024, 6:49 a.m. UTC | #1
On Mon, Jun 3, 2024 at 5:02 AM Kewen Lin <linkw@linux.ibm.com> wrote:
>
> Currently how we determine which mode will be used for a
> floating point type is that for a given type precision
> (size) call mode_for_size to get the first mode which has
> this size in the specified class.  On Powerpc, we have
> three modes (TF/KF/IF) having the same mode precision 128
> (see[1]), so the processing forces us to have to place TF
> at the first place, it would require us to make more
> adjustment in some generic code to avoid some unexpected
> mode conversions and it would be even worse if we get rid
> of TF eventually one day.  And as Joseph pointed out in [2],
> "floating types should have their mode, not a poorly
> defined precision value", as Joseph and Richi suggested,
> this patch is to introduce one hook mode_for_floating_type
> which returns the corresponding mode for type float, double
> or long double.  The default implementation returns SFmode
> for float and DFmode for double or long double.  For ports
> which need special treatment, there are some other patches
> for their own port specific implementation (referring to
> how {,LONG_}DOUBLE_TYPE_SIZE get used there).  For all
> generic uses of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE, depending
> on the context, some of them are replaced with TYPE_PRECISION
> of the according type node, some other are replaced with
> GET_MODE_PRECISION on the mode from mode_for_floating_type.
> This patch also poisons {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE,
> so most defines of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE in port
> specific are removed, but there are still some which are
> good to be kept for readability then they get renamed with
> port specific prefix.
>
> [1] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651017.html
> [2] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651209.html
>
> gcc/ChangeLog:
>
>         * coretypes.h (enum tree_index): Forward declaration.
>         * defaults.h (FLOAT_TYPE_SIZE): Remove.
>         (DOUBLE_TYPE_SIZE): Likewise.
>         (LONG_DOUBLE_TYPE_SIZE): Likewise.
>         * doc/rtl.texi: Update document by replacing {FLOAT,DOUBLE}_TYPE_SIZE
>         with C type {float,double}.
>         * doc/tm.texi.in: Document new hook mode_for_floating_type, remove
>         document entries for {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE and
>         update document for WIDEST_HARDWARE_FP_SIZE.
>         * doc/tm.texi: Regenerate.
>         * emit-rtl.cc (init_emit_once): Replace DOUBLE_TYPE_SIZE by
>         calling targetm.c.mode_for_floating_type with TI_DOUBLE_TYPE.
>         * real.h (REAL_VALUE_TO_TARGET_LONG_DOUBLE): Use TYPE_PRECISION of
>         long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE.
>         * system.h (FLOAT_TYPE_SIZE): Poison.
>         (DOUBLE_TYPE_SIZE): Likewise.
>         (LONG_DOUBLE_TYPE_SIZE): Likewise.
>         * target.def (mode_for_floating_type): New hook.
>         * targhooks.cc (default_mode_for_floating_type): New function.
>         (default_scalar_mode_supported_p): Update macros
>         {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE by calling
>         targetm.c.mode_for_floating_type with
>         TI_{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE.
>         * targhooks.h (default_mode_for_floating_type): New declaration.
>         * tree-core.h (enum tree_index): Specify underlying type unsigned
>         to sync with forward declaration in coretypes.h.
>         (NUM_FLOATN_TYPES): Explicitly convert to int.
>         (NUM_FLOATNX_TYPES): Likewise.
>         (NUM_FLOATN_NX_TYPES): Likewise.
>         * tree.cc (build_common_tree_nodes): Update macros
>         {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE by calling
>         targetm.c.mode_for_floating_type with
>         TI_{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE and set type mode accordingly.
> ---
>  gcc/coretypes.h    |  1 +
>  gcc/defaults.h     | 12 ------------
>  gcc/doc/rtl.texi   |  2 +-
>  gcc/doc/tm.texi    | 33 +++++++++++++--------------------
>  gcc/doc/tm.texi.in | 27 +++++++--------------------
>  gcc/emit-rtl.cc    |  3 ++-
>  gcc/real.h         |  7 ++++---
>  gcc/system.h       |  3 ++-
>  gcc/target.def     |  9 +++++++++
>  gcc/targhooks.cc   | 18 +++++++++++++++---
>  gcc/targhooks.h    |  1 +
>  gcc/tree-core.h    | 13 +++++++------
>  gcc/tree.cc        | 18 +++++++++++++++---
>  13 files changed, 77 insertions(+), 70 deletions(-)
>
> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
> index 1ac6f0abea3..00c1c58bd8c 100644
> --- a/gcc/coretypes.h
> +++ b/gcc/coretypes.h
> @@ -100,6 +100,7 @@ struct gimple;
>  typedef gimple *gimple_seq;
>  struct gimple_stmt_iterator;
>  class code_helper;
> +enum tree_index : unsigned;
>
>  /* Forward declare rtx_code, so that we can use it in target hooks without
>     needing to pull in rtl.h.  */
> diff --git a/gcc/defaults.h b/gcc/defaults.h
> index 92f3e07f742..ac2d25852ab 100644
> --- a/gcc/defaults.h
> +++ b/gcc/defaults.h
> @@ -513,18 +513,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>  #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
>  #endif
>
> -#ifndef FLOAT_TYPE_SIZE
> -#define FLOAT_TYPE_SIZE BITS_PER_WORD
> -#endif
> -
> -#ifndef DOUBLE_TYPE_SIZE
> -#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
> -#endif
> -
> -#ifndef LONG_DOUBLE_TYPE_SIZE
> -#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
> -#endif
> -
>  #ifndef DECIMAL32_TYPE_SIZE
>  #define DECIMAL32_TYPE_SIZE 32
>  #endif
> diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
> index aa10b5235b5..d85b6dcbf1a 100644
> --- a/gcc/doc/rtl.texi
> +++ b/gcc/doc/rtl.texi
> @@ -1326,7 +1326,7 @@ whose size is @code{BITS_PER_WORD}, @code{SImode} on 32-bit machines.
>
>  The only modes which a machine description @i{must} support are
>  @code{QImode}, and the modes corresponding to @code{BITS_PER_WORD},
> -@code{FLOAT_TYPE_SIZE} and @code{DOUBLE_TYPE_SIZE}.
> +C type @code{float} and C type type @code{double}.

type type

OK with that fixed and no comments from others.

Richard.

>  The compiler will attempt to use @code{DImode} for 8-byte structures and
>  unions, but this can be prevented by overriding the definition of
>  @code{MAX_FIXED_MODE_SIZE}.  Alternatively, you can have the compiler
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index cd50078227d..07bf8ed9e0e 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -1044,6 +1044,14 @@ are zero or sign extended depending on if it is
>  @code{GET_MODE_ALIGNMENT (info->limb_mode)}.
>  @end deftypefn
>
> +@deftypefn {Target Hook} machine_mode TARGET_C_MODE_FOR_FLOATING_TYPE (enum tree_index @var{ti})
> +Return machine mode for a C floating point type which is indicated by
> + a given @code{enum tree_index} @var{ti}, @var{ti} should be
> + @code{TI_FLOAT_TYPE}, @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.
> + The default implementation returns @code{SFmode} for @code{TI_FLOAT_TYPE},
> + and @code{DFmode} for @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.
> +@end deftypefn
> +
>  @deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
>  Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
>  function return values.  The target hook should return the new mode
> @@ -1610,23 +1618,6 @@ C99 type @code{_Bool} on the target machine.  If you don't define
>  this, and you probably shouldn't, the default is @code{CHAR_TYPE_SIZE}.
>  @end defmac
>
> -@defmac FLOAT_TYPE_SIZE
> -A C expression for the size in bits of the type @code{float} on the
> -target machine.  If you don't define this, the default is one word.
> -@end defmac
> -
> -@defmac DOUBLE_TYPE_SIZE
> -A C expression for the size in bits of the type @code{double} on the
> -target machine.  If you don't define this, the default is two
> -words.
> -@end defmac
> -
> -@defmac LONG_DOUBLE_TYPE_SIZE
> -A C expression for the size in bits of the type @code{long double} on
> -the target machine.  If you don't define this, the default is two
> -words.
> -@end defmac
> -
>  @defmac SHORT_FRACT_TYPE_SIZE
>  A C expression for the size in bits of the type @code{short _Fract} on
>  the target machine.  If you don't define this, the default is
> @@ -1687,9 +1678,11 @@ the libgcc @file{config.host}.
>  @defmac WIDEST_HARDWARE_FP_SIZE
>  A C expression for the size in bits of the widest floating-point format
>  supported by the hardware.  If you define this macro, you must specify a
> -value less than or equal to the value of @code{LONG_DOUBLE_TYPE_SIZE}.
> -If you do not define this macro, the value of @code{LONG_DOUBLE_TYPE_SIZE}
> -is the default.
> +value less than or equal to mode precision of the mode used for C type
> +@code{long double} (from hook @code{targetm.c.mode_for_floating_type}
> +with tree_index TI_LONG_DOUBLE_TYPE).  If you do not define this macro,
> +mode precision of the mode used for C type @code{long double} is the
> +default.
>  @end defmac
>
>  @defmac DEFAULT_SIGNED_CHAR
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index 058bd56487a..f6e2372f262 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -947,6 +947,8 @@ applied.
>
>  @hook TARGET_C_BITINT_TYPE_INFO
>
> +@hook TARGET_C_MODE_FOR_FLOATING_TYPE
> +
>  @hook TARGET_PROMOTE_FUNCTION_MODE
>
>  @defmac PARM_BOUNDARY
> @@ -1351,23 +1353,6 @@ C99 type @code{_Bool} on the target machine.  If you don't define
>  this, and you probably shouldn't, the default is @code{CHAR_TYPE_SIZE}.
>  @end defmac
>
> -@defmac FLOAT_TYPE_SIZE
> -A C expression for the size in bits of the type @code{float} on the
> -target machine.  If you don't define this, the default is one word.
> -@end defmac
> -
> -@defmac DOUBLE_TYPE_SIZE
> -A C expression for the size in bits of the type @code{double} on the
> -target machine.  If you don't define this, the default is two
> -words.
> -@end defmac
> -
> -@defmac LONG_DOUBLE_TYPE_SIZE
> -A C expression for the size in bits of the type @code{long double} on
> -the target machine.  If you don't define this, the default is two
> -words.
> -@end defmac
> -
>  @defmac SHORT_FRACT_TYPE_SIZE
>  A C expression for the size in bits of the type @code{short _Fract} on
>  the target machine.  If you don't define this, the default is
> @@ -1428,9 +1413,11 @@ the libgcc @file{config.host}.
>  @defmac WIDEST_HARDWARE_FP_SIZE
>  A C expression for the size in bits of the widest floating-point format
>  supported by the hardware.  If you define this macro, you must specify a
> -value less than or equal to the value of @code{LONG_DOUBLE_TYPE_SIZE}.
> -If you do not define this macro, the value of @code{LONG_DOUBLE_TYPE_SIZE}
> -is the default.
> +value less than or equal to mode precision of the mode used for C type
> +@code{long double} (from hook @code{targetm.c.mode_for_floating_type}
> +with tree_index TI_LONG_DOUBLE_TYPE).  If you do not define this macro,
> +mode precision of the mode used for C type @code{long double} is the
> +default.
>  @end defmac
>
>  @defmac DEFAULT_SIGNED_CHAR
> diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
> index 1856fa4884f..cb04aa1a8c6 100644
> --- a/gcc/emit-rtl.cc
> +++ b/gcc/emit-rtl.cc
> @@ -6366,7 +6366,8 @@ init_emit_once (void)
>    else
>      const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE);
>
> -  double_mode = float_mode_for_size (DOUBLE_TYPE_SIZE).require ();
> +  mode = targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE);
> +  double_mode = as_a<scalar_float_mode> (mode);
>
>    real_from_integer (&dconst0, double_mode, 0, SIGNED);
>    real_from_integer (&dconst1, double_mode, 1, SIGNED);
> diff --git a/gcc/real.h b/gcc/real.h
> index 2e40817a2d7..f28022769b3 100644
> --- a/gcc/real.h
> +++ b/gcc/real.h
> @@ -406,9 +406,10 @@ extern const struct real_format arm_bfloat_half_format;
>  #define REAL_VALUE_MINUS_ZERO(x)       real_isnegzero (&(x))
>
>  /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs.  */
> -#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT)                      \
> -  real_to_target (OUT, &(IN),                                          \
> -                 float_mode_for_size (LONG_DOUBLE_TYPE_SIZE).require ())
> +#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT)                         \
> +  real_to_target (OUT, &(IN),                                             \
> +                 float_mode_for_size (TYPE_PRECISION                      \
> +                                      (long_double_type_node)).require ())
>
>  #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
>    real_to_target (OUT, &(IN), float_mode_for_size (64).require ())
> diff --git a/gcc/system.h b/gcc/system.h
> index 1028dcb1eb3..cbb14fb167d 100644
> --- a/gcc/system.h
> +++ b/gcc/system.h
> @@ -1000,7 +1000,8 @@ extern void fancy_abort (const char *, int, const char *)
>         HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE                   \
>         SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS                \
>         TRULY_NOOP_TRUNCATION FUNCTION_ARG_OFFSET CONSTANT_ALIGNMENT    \
> -       STARTING_FRAME_OFFSET
> +       STARTING_FRAME_OFFSET FLOAT_TYPE_SIZE DOUBLE_TYPE_SIZE          \
> +       LONG_DOUBLE_TYPE_SIZE
>
>  /* Target macros only used for code built for the target, that have
>     moved to libgcc-tm.h or have never been present elsewhere.  */
> diff --git a/gcc/target.def b/gcc/target.def
> index c27df8095be..4780ba9c15b 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -6370,6 +6370,15 @@ are zero or sign extended depending on if it is\n\
>   bool, (int n, struct bitint_info *info),
>   default_bitint_type_info)
>
> +DEFHOOK
> +(mode_for_floating_type,
> +"Return machine mode for a C floating point type which is indicated by\n\
> + a given @code{enum tree_index} @var{ti}, @var{ti} should be\n\
> + @code{TI_FLOAT_TYPE}, @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.\n\
> + The default implementation returns @code{SFmode} for @code{TI_FLOAT_TYPE},\n\
> + and @code{DFmode} for @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.",
> + machine_mode, (enum tree_index ti), default_mode_for_floating_type)
> +
>  HOOK_VECTOR_END (c)
>
>  /* Functions specific to the C++ frontend.  */
> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
> index fb339bf75dd..5111e069f0c 100644
> --- a/gcc/targhooks.cc
> +++ b/gcc/targhooks.cc
> @@ -298,6 +298,18 @@ default_mode_for_suffix (char suffix ATTRIBUTE_UNUSED)
>    return VOIDmode;
>  }
>
> +/* Return machine mode for a floating type which is indicated
> +   by the given enum tree_index.  */
> +
> +machine_mode
> +default_mode_for_floating_type (enum tree_index ti)
> +{
> +  if (ti == TI_FLOAT_TYPE)
> +    return SFmode;
> +  gcc_assert (ti == TI_DOUBLE_TYPE || ti == TI_LONG_DOUBLE_TYPE);
> +  return DFmode;
> +}
> +
>  /* The generic C++ ABI specifies this is a 64-bit value.  */
>  tree
>  default_cxx_guard_type (void)
> @@ -449,11 +461,11 @@ default_scalar_mode_supported_p (scalar_mode mode)
>        return false;
>
>      case MODE_FLOAT:
> -      if (precision == FLOAT_TYPE_SIZE)
> +      if (mode == targetm.c.mode_for_floating_type (TI_FLOAT_TYPE))
>         return true;
> -      if (precision == DOUBLE_TYPE_SIZE)
> +      if (mode == targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE))
>         return true;
> -      if (precision == LONG_DOUBLE_TYPE_SIZE)
> +      if (mode == targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE))
>         return true;
>        return false;
>
> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> index 85f3817c176..fdc17c3b7c0 100644
> --- a/gcc/targhooks.h
> +++ b/gcc/targhooks.h
> @@ -289,6 +289,7 @@ extern unsigned int default_min_arithmetic_precision (void);
>  extern enum flt_eval_method
>  default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
>  extern bool default_bitint_type_info (int, struct bitint_info *);
> +extern machine_mode default_mode_for_floating_type (enum tree_index);
>  extern HOST_WIDE_INT default_stack_clash_protection_alloca_probe_range (void);
>  extern void default_select_early_remat_modes (sbitmap);
>  extern tree default_preferred_else_value (unsigned, tree, unsigned, tree *);
> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> index 9fa74342919..0b5000acb80 100644
> --- a/gcc/tree-core.h
> +++ b/gcc/tree-core.h
> @@ -624,7 +624,7 @@ enum cv_qualifier {
>  };
>
>  /* Standard named or nameless data types of the C compiler.  */
> -enum tree_index {
> +enum tree_index : unsigned {
>    TI_ERROR_MARK,
>    TI_INTQI_TYPE,
>    TI_INTHI_TYPE,
> @@ -691,17 +691,18 @@ enum tree_index {
>    TI_FLOAT64_TYPE,
>    TI_FLOAT128_TYPE,
>    TI_FLOATN_TYPE_LAST = TI_FLOAT128_TYPE,
> -#define NUM_FLOATN_TYPES (TI_FLOATN_TYPE_LAST - TI_FLOATN_TYPE_FIRST + 1)
> +#define NUM_FLOATN_TYPES ((int) (TI_FLOATN_TYPE_LAST           \
> +                                - TI_FLOATN_TYPE_FIRST + 1))
>    TI_FLOAT32X_TYPE,
>    TI_FLOATNX_TYPE_FIRST = TI_FLOAT32X_TYPE,
>    TI_FLOAT64X_TYPE,
>    TI_FLOAT128X_TYPE,
>    TI_FLOATNX_TYPE_LAST = TI_FLOAT128X_TYPE,
>    TI_FLOATN_NX_TYPE_LAST = TI_FLOAT128X_TYPE,
> -#define NUM_FLOATNX_TYPES (TI_FLOATNX_TYPE_LAST - TI_FLOATNX_TYPE_FIRST + 1)
> -#define NUM_FLOATN_NX_TYPES (TI_FLOATN_NX_TYPE_LAST            \
> -                            - TI_FLOATN_NX_TYPE_FIRST          \
> -                            + 1)
> +#define NUM_FLOATNX_TYPES ((int) (TI_FLOATNX_TYPE_LAST         \
> +                                 - TI_FLOATNX_TYPE_FIRST + 1))
> +#define NUM_FLOATN_NX_TYPES ((int) (TI_FLOATN_NX_TYPE_LAST     \
> +                                 - TI_FLOATN_NX_TYPE_FIRST + 1))
>
>    /* Type used by certain backends for __float128, which in C++ should be
>       distinct type from _Float128 for backwards compatibility reasons.  */
> diff --git a/gcc/tree.cc b/gcc/tree.cc
> index 6564b002dc1..bc5175f591e 100644
> --- a/gcc/tree.cc
> +++ b/gcc/tree.cc
> @@ -9596,15 +9596,27 @@ build_common_tree_nodes (bool signed_char)
>    pointer_sized_int_node = build_nonstandard_integer_type (POINTER_SIZE, 1);
>
>    float_type_node = make_node (REAL_TYPE);
> -  TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
> +  machine_mode float_type_mode
> +    = targetm.c.mode_for_floating_type (TI_FLOAT_TYPE);
> +  SET_TYPE_MODE (float_type_node, float_type_mode);
> +  TYPE_PRECISION (float_type_node)
> +    = GET_MODE_PRECISION (float_type_mode).to_constant ();
>    layout_type (float_type_node);
>
>    double_type_node = make_node (REAL_TYPE);
> -  TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
> +  machine_mode double_type_mode
> +    = targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE);
> +  SET_TYPE_MODE (double_type_node, double_type_mode);
> +  TYPE_PRECISION (double_type_node)
> +    = GET_MODE_PRECISION (double_type_mode).to_constant ();
>    layout_type (double_type_node);
>
>    long_double_type_node = make_node (REAL_TYPE);
> -  TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
> +  machine_mode long_double_type_mode
> +    = targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE);
> +  SET_TYPE_MODE (long_double_type_node, long_double_type_mode);
> +  TYPE_PRECISION (long_double_type_node)
> +    = GET_MODE_PRECISION (long_double_type_mode).to_constant ();
>    layout_type (long_double_type_node);
>
>    for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
> --
> 2.43.0
>
Kewen.Lin June 3, 2024, 9:36 a.m. UTC | #2
Hi Richi,

on 2024/6/3 14:49, Richard Biener wrote:
> On Mon, Jun 3, 2024 at 5:02 AM Kewen Lin <linkw@linux.ibm.com> wrote:
>>
>> Currently how we determine which mode will be used for a
>> floating point type is that for a given type precision
>> (size) call mode_for_size to get the first mode which has
>> this size in the specified class.  On Powerpc, we have
>> three modes (TF/KF/IF) having the same mode precision 128
>> (see[1]), so the processing forces us to have to place TF
>> at the first place, it would require us to make more
>> adjustment in some generic code to avoid some unexpected
>> mode conversions and it would be even worse if we get rid
>> of TF eventually one day.  And as Joseph pointed out in [2],
>> "floating types should have their mode, not a poorly
>> defined precision value", as Joseph and Richi suggested,
>> this patch is to introduce one hook mode_for_floating_type
>> which returns the corresponding mode for type float, double
>> or long double.  The default implementation returns SFmode
>> for float and DFmode for double or long double.  For ports
>> which need special treatment, there are some other patches
>> for their own port specific implementation (referring to
>> how {,LONG_}DOUBLE_TYPE_SIZE get used there).  For all
>> generic uses of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE, depending
>> on the context, some of them are replaced with TYPE_PRECISION
>> of the according type node, some other are replaced with
>> GET_MODE_PRECISION on the mode from mode_for_floating_type.
>> This patch also poisons {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE,
>> so most defines of {FLOAT,{,LONG_}DOUBLE}_TYPE_SIZE in port
>> specific are removed, but there are still some which are
>> good to be kept for readability then they get renamed with
>> port specific prefix.
>>
>> [1] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651017.html
>> [2] https://gcc.gnu.org/pipermail/gcc-patches/2024-May/651209.html
>>
>> gcc/ChangeLog:
>>
>>         * coretypes.h (enum tree_index): Forward declaration.
>>         * defaults.h (FLOAT_TYPE_SIZE): Remove.
>>         (DOUBLE_TYPE_SIZE): Likewise.
>>         (LONG_DOUBLE_TYPE_SIZE): Likewise.
>>         * doc/rtl.texi: Update document by replacing {FLOAT,DOUBLE}_TYPE_SIZE
>>         with C type {float,double}.
>>         * doc/tm.texi.in: Document new hook mode_for_floating_type, remove
>>         document entries for {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE and
>>         update document for WIDEST_HARDWARE_FP_SIZE.
>>         * doc/tm.texi: Regenerate.
>>         * emit-rtl.cc (init_emit_once): Replace DOUBLE_TYPE_SIZE by
>>         calling targetm.c.mode_for_floating_type with TI_DOUBLE_TYPE.
>>         * real.h (REAL_VALUE_TO_TARGET_LONG_DOUBLE): Use TYPE_PRECISION of
>>         long_double_type_node to replace LONG_DOUBLE_TYPE_SIZE.
>>         * system.h (FLOAT_TYPE_SIZE): Poison.
>>         (DOUBLE_TYPE_SIZE): Likewise.
>>         (LONG_DOUBLE_TYPE_SIZE): Likewise.
>>         * target.def (mode_for_floating_type): New hook.
>>         * targhooks.cc (default_mode_for_floating_type): New function.
>>         (default_scalar_mode_supported_p): Update macros
>>         {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE by calling
>>         targetm.c.mode_for_floating_type with
>>         TI_{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE.
>>         * targhooks.h (default_mode_for_floating_type): New declaration.
>>         * tree-core.h (enum tree_index): Specify underlying type unsigned
>>         to sync with forward declaration in coretypes.h.
>>         (NUM_FLOATN_TYPES): Explicitly convert to int.
>>         (NUM_FLOATNX_TYPES): Likewise.
>>         (NUM_FLOATN_NX_TYPES): Likewise.
>>         * tree.cc (build_common_tree_nodes): Update macros
>>         {FLOAT,DOUBLE,LONG_DOUBLE}_TYPE_SIZE by calling
>>         targetm.c.mode_for_floating_type with
>>         TI_{FLOAT,DOUBLE,LONG_DOUBLE}_TYPE and set type mode accordingly.
>> ---
>>  gcc/coretypes.h    |  1 +
>>  gcc/defaults.h     | 12 ------------
>>  gcc/doc/rtl.texi   |  2 +-
>>  gcc/doc/tm.texi    | 33 +++++++++++++--------------------
>>  gcc/doc/tm.texi.in | 27 +++++++--------------------
>>  gcc/emit-rtl.cc    |  3 ++-
>>  gcc/real.h         |  7 ++++---
>>  gcc/system.h       |  3 ++-
>>  gcc/target.def     |  9 +++++++++
>>  gcc/targhooks.cc   | 18 +++++++++++++++---
>>  gcc/targhooks.h    |  1 +
>>  gcc/tree-core.h    | 13 +++++++------
>>  gcc/tree.cc        | 18 +++++++++++++++---
>>  13 files changed, 77 insertions(+), 70 deletions(-)
>>
>> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
>> index 1ac6f0abea3..00c1c58bd8c 100644
>> --- a/gcc/coretypes.h
>> +++ b/gcc/coretypes.h
>> @@ -100,6 +100,7 @@ struct gimple;
>>  typedef gimple *gimple_seq;
>>  struct gimple_stmt_iterator;
>>  class code_helper;
>> +enum tree_index : unsigned;
>>
>>  /* Forward declare rtx_code, so that we can use it in target hooks without
>>     needing to pull in rtl.h.  */
>> diff --git a/gcc/defaults.h b/gcc/defaults.h
>> index 92f3e07f742..ac2d25852ab 100644
>> --- a/gcc/defaults.h
>> +++ b/gcc/defaults.h
>> @@ -513,18 +513,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
>>  #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
>>  #endif
>>
>> -#ifndef FLOAT_TYPE_SIZE
>> -#define FLOAT_TYPE_SIZE BITS_PER_WORD
>> -#endif
>> -
>> -#ifndef DOUBLE_TYPE_SIZE
>> -#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
>> -#endif
>> -
>> -#ifndef LONG_DOUBLE_TYPE_SIZE
>> -#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
>> -#endif
>> -
>>  #ifndef DECIMAL32_TYPE_SIZE
>>  #define DECIMAL32_TYPE_SIZE 32
>>  #endif
>> diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
>> index aa10b5235b5..d85b6dcbf1a 100644
>> --- a/gcc/doc/rtl.texi
>> +++ b/gcc/doc/rtl.texi
>> @@ -1326,7 +1326,7 @@ whose size is @code{BITS_PER_WORD}, @code{SImode} on 32-bit machines.
>>
>>  The only modes which a machine description @i{must} support are
>>  @code{QImode}, and the modes corresponding to @code{BITS_PER_WORD},
>> -@code{FLOAT_TYPE_SIZE} and @code{DOUBLE_TYPE_SIZE}.
>> +C type @code{float} and C type type @code{double}.
> 
> type type

Oops, thanks for catching, will fix it.

> 
> OK with that fixed and no comments from others.

Thanks!

BR,
Kewen
Joseph Myers June 3, 2024, 5:59 p.m. UTC | #3
On Sun, 2 Jun 2024, Kewen Lin wrote:

> +value less than or equal to mode precision of the mode used for C type
> +@code{long double} (from hook @code{targetm.c.mode_for_floating_type}
> +with tree_index TI_LONG_DOUBLE_TYPE).  If you do not define this macro,
> +mode precision of the mode used for C type @code{long double} is the
> +default.

Identifiers such as tree_index and TI_LONG_DOUBLE_TYPE should be enclosed 
in @code{} in documentation (in this case it would be better to say "with 
argument @code{TI_LONG_DOUBLE_TYPE}" rather than mentioning the tree_index 
type of the argument).

> @@ -1428,9 +1413,11 @@ the libgcc @file{config.host}.
>  @defmac WIDEST_HARDWARE_FP_SIZE
>  A C expression for the size in bits of the widest floating-point format
>  supported by the hardware.  If you define this macro, you must specify a
> -value less than or equal to the value of @code{LONG_DOUBLE_TYPE_SIZE}.
> -If you do not define this macro, the value of @code{LONG_DOUBLE_TYPE_SIZE}
> -is the default.
> +value less than or equal to mode precision of the mode used for C type
> +@code{long double} (from hook @code{targetm.c.mode_for_floating_type}
> +with tree_index TI_LONG_DOUBLE_TYPE).  If you do not define this macro,
> +mode precision of the mode used for C type @code{long double} is the
> +default.

Likewise.
diff mbox series

Patch

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 1ac6f0abea3..00c1c58bd8c 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -100,6 +100,7 @@  struct gimple;
 typedef gimple *gimple_seq;
 struct gimple_stmt_iterator;
 class code_helper;
+enum tree_index : unsigned;
 
 /* Forward declare rtx_code, so that we can use it in target hooks without
    needing to pull in rtl.h.  */
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 92f3e07f742..ac2d25852ab 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -513,18 +513,6 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define WCHAR_TYPE_SIZE INT_TYPE_SIZE
 #endif
 
-#ifndef FLOAT_TYPE_SIZE
-#define FLOAT_TYPE_SIZE BITS_PER_WORD
-#endif
-
-#ifndef DOUBLE_TYPE_SIZE
-#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
-#ifndef LONG_DOUBLE_TYPE_SIZE
-#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
-#endif
-
 #ifndef DECIMAL32_TYPE_SIZE
 #define DECIMAL32_TYPE_SIZE 32
 #endif
diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi
index aa10b5235b5..d85b6dcbf1a 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -1326,7 +1326,7 @@  whose size is @code{BITS_PER_WORD}, @code{SImode} on 32-bit machines.
 
 The only modes which a machine description @i{must} support are
 @code{QImode}, and the modes corresponding to @code{BITS_PER_WORD},
-@code{FLOAT_TYPE_SIZE} and @code{DOUBLE_TYPE_SIZE}.
+C type @code{float} and C type type @code{double}.
 The compiler will attempt to use @code{DImode} for 8-byte structures and
 unions, but this can be prevented by overriding the definition of
 @code{MAX_FIXED_MODE_SIZE}.  Alternatively, you can have the compiler
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index cd50078227d..07bf8ed9e0e 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1044,6 +1044,14 @@  are zero or sign extended depending on if it is
 @code{GET_MODE_ALIGNMENT (info->limb_mode)}.
 @end deftypefn
 
+@deftypefn {Target Hook} machine_mode TARGET_C_MODE_FOR_FLOATING_TYPE (enum tree_index @var{ti})
+Return machine mode for a C floating point type which is indicated by
+ a given @code{enum tree_index} @var{ti}, @var{ti} should be
+ @code{TI_FLOAT_TYPE}, @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.
+ The default implementation returns @code{SFmode} for @code{TI_FLOAT_TYPE},
+ and @code{DFmode} for @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.
+@end deftypefn
+
 @deftypefn {Target Hook} machine_mode TARGET_PROMOTE_FUNCTION_MODE (const_tree @var{type}, machine_mode @var{mode}, int *@var{punsignedp}, const_tree @var{funtype}, int @var{for_return})
 Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or
 function return values.  The target hook should return the new mode
@@ -1610,23 +1618,6 @@  C99 type @code{_Bool} on the target machine.  If you don't define
 this, and you probably shouldn't, the default is @code{CHAR_TYPE_SIZE}.
 @end defmac
 
-@defmac FLOAT_TYPE_SIZE
-A C expression for the size in bits of the type @code{float} on the
-target machine.  If you don't define this, the default is one word.
-@end defmac
-
-@defmac DOUBLE_TYPE_SIZE
-A C expression for the size in bits of the type @code{double} on the
-target machine.  If you don't define this, the default is two
-words.
-@end defmac
-
-@defmac LONG_DOUBLE_TYPE_SIZE
-A C expression for the size in bits of the type @code{long double} on
-the target machine.  If you don't define this, the default is two
-words.
-@end defmac
-
 @defmac SHORT_FRACT_TYPE_SIZE
 A C expression for the size in bits of the type @code{short _Fract} on
 the target machine.  If you don't define this, the default is
@@ -1687,9 +1678,11 @@  the libgcc @file{config.host}.
 @defmac WIDEST_HARDWARE_FP_SIZE
 A C expression for the size in bits of the widest floating-point format
 supported by the hardware.  If you define this macro, you must specify a
-value less than or equal to the value of @code{LONG_DOUBLE_TYPE_SIZE}.
-If you do not define this macro, the value of @code{LONG_DOUBLE_TYPE_SIZE}
-is the default.
+value less than or equal to mode precision of the mode used for C type
+@code{long double} (from hook @code{targetm.c.mode_for_floating_type}
+with tree_index TI_LONG_DOUBLE_TYPE).  If you do not define this macro,
+mode precision of the mode used for C type @code{long double} is the
+default.
 @end defmac
 
 @defmac DEFAULT_SIGNED_CHAR
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 058bd56487a..f6e2372f262 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -947,6 +947,8 @@  applied.
 
 @hook TARGET_C_BITINT_TYPE_INFO
 
+@hook TARGET_C_MODE_FOR_FLOATING_TYPE
+
 @hook TARGET_PROMOTE_FUNCTION_MODE
 
 @defmac PARM_BOUNDARY
@@ -1351,23 +1353,6 @@  C99 type @code{_Bool} on the target machine.  If you don't define
 this, and you probably shouldn't, the default is @code{CHAR_TYPE_SIZE}.
 @end defmac
 
-@defmac FLOAT_TYPE_SIZE
-A C expression for the size in bits of the type @code{float} on the
-target machine.  If you don't define this, the default is one word.
-@end defmac
-
-@defmac DOUBLE_TYPE_SIZE
-A C expression for the size in bits of the type @code{double} on the
-target machine.  If you don't define this, the default is two
-words.
-@end defmac
-
-@defmac LONG_DOUBLE_TYPE_SIZE
-A C expression for the size in bits of the type @code{long double} on
-the target machine.  If you don't define this, the default is two
-words.
-@end defmac
-
 @defmac SHORT_FRACT_TYPE_SIZE
 A C expression for the size in bits of the type @code{short _Fract} on
 the target machine.  If you don't define this, the default is
@@ -1428,9 +1413,11 @@  the libgcc @file{config.host}.
 @defmac WIDEST_HARDWARE_FP_SIZE
 A C expression for the size in bits of the widest floating-point format
 supported by the hardware.  If you define this macro, you must specify a
-value less than or equal to the value of @code{LONG_DOUBLE_TYPE_SIZE}.
-If you do not define this macro, the value of @code{LONG_DOUBLE_TYPE_SIZE}
-is the default.
+value less than or equal to mode precision of the mode used for C type
+@code{long double} (from hook @code{targetm.c.mode_for_floating_type}
+with tree_index TI_LONG_DOUBLE_TYPE).  If you do not define this macro,
+mode precision of the mode used for C type @code{long double} is the
+default.
 @end defmac
 
 @defmac DEFAULT_SIGNED_CHAR
diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index 1856fa4884f..cb04aa1a8c6 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -6366,7 +6366,8 @@  init_emit_once (void)
   else
     const_true_rtx = gen_rtx_CONST_INT (VOIDmode, STORE_FLAG_VALUE);
 
-  double_mode = float_mode_for_size (DOUBLE_TYPE_SIZE).require ();
+  mode = targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE);
+  double_mode = as_a<scalar_float_mode> (mode);
 
   real_from_integer (&dconst0, double_mode, 0, SIGNED);
   real_from_integer (&dconst1, double_mode, 1, SIGNED);
diff --git a/gcc/real.h b/gcc/real.h
index 2e40817a2d7..f28022769b3 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -406,9 +406,10 @@  extern const struct real_format arm_bfloat_half_format;
 #define REAL_VALUE_MINUS_ZERO(x)	real_isnegzero (&(x))
 
 /* IN is a REAL_VALUE_TYPE.  OUT is an array of longs.  */
-#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT)			\
-  real_to_target (OUT, &(IN),						\
-		  float_mode_for_size (LONG_DOUBLE_TYPE_SIZE).require ())
+#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT)			   \
+  real_to_target (OUT, &(IN),						   \
+		  float_mode_for_size (TYPE_PRECISION			   \
+				       (long_double_type_node)).require ())
 
 #define REAL_VALUE_TO_TARGET_DOUBLE(IN, OUT) \
   real_to_target (OUT, &(IN), float_mode_for_size (64).require ())
diff --git a/gcc/system.h b/gcc/system.h
index 1028dcb1eb3..cbb14fb167d 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -1000,7 +1000,8 @@  extern void fancy_abort (const char *, int, const char *)
 	HARD_REGNO_NREGS SECONDARY_MEMORY_NEEDED_MODE			\
 	SECONDARY_MEMORY_NEEDED CANNOT_CHANGE_MODE_CLASS		\
 	TRULY_NOOP_TRUNCATION FUNCTION_ARG_OFFSET CONSTANT_ALIGNMENT	\
-	STARTING_FRAME_OFFSET
+	STARTING_FRAME_OFFSET FLOAT_TYPE_SIZE DOUBLE_TYPE_SIZE		\
+	LONG_DOUBLE_TYPE_SIZE
 
 /* Target macros only used for code built for the target, that have
    moved to libgcc-tm.h or have never been present elsewhere.  */
diff --git a/gcc/target.def b/gcc/target.def
index c27df8095be..4780ba9c15b 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -6370,6 +6370,15 @@  are zero or sign extended depending on if it is\n\
  bool, (int n, struct bitint_info *info),
  default_bitint_type_info)
 
+DEFHOOK
+(mode_for_floating_type,
+"Return machine mode for a C floating point type which is indicated by\n\
+ a given @code{enum tree_index} @var{ti}, @var{ti} should be\n\
+ @code{TI_FLOAT_TYPE}, @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.\n\
+ The default implementation returns @code{SFmode} for @code{TI_FLOAT_TYPE},\n\
+ and @code{DFmode} for @code{TI_DOUBLE_TYPE} or @code{TI_LONG_DOUBLE_TYPE}.",
+ machine_mode, (enum tree_index ti), default_mode_for_floating_type)
+
 HOOK_VECTOR_END (c)
 
 /* Functions specific to the C++ frontend.  */
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index fb339bf75dd..5111e069f0c 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -298,6 +298,18 @@  default_mode_for_suffix (char suffix ATTRIBUTE_UNUSED)
   return VOIDmode;
 }
 
+/* Return machine mode for a floating type which is indicated
+   by the given enum tree_index.  */
+
+machine_mode
+default_mode_for_floating_type (enum tree_index ti)
+{
+  if (ti == TI_FLOAT_TYPE)
+    return SFmode;
+  gcc_assert (ti == TI_DOUBLE_TYPE || ti == TI_LONG_DOUBLE_TYPE);
+  return DFmode;
+}
+
 /* The generic C++ ABI specifies this is a 64-bit value.  */
 tree
 default_cxx_guard_type (void)
@@ -449,11 +461,11 @@  default_scalar_mode_supported_p (scalar_mode mode)
       return false;
 
     case MODE_FLOAT:
-      if (precision == FLOAT_TYPE_SIZE)
+      if (mode == targetm.c.mode_for_floating_type (TI_FLOAT_TYPE))
 	return true;
-      if (precision == DOUBLE_TYPE_SIZE)
+      if (mode == targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE))
 	return true;
-      if (precision == LONG_DOUBLE_TYPE_SIZE)
+      if (mode == targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE))
 	return true;
       return false;
 
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 85f3817c176..fdc17c3b7c0 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -289,6 +289,7 @@  extern unsigned int default_min_arithmetic_precision (void);
 extern enum flt_eval_method
 default_excess_precision (enum excess_precision_type ATTRIBUTE_UNUSED);
 extern bool default_bitint_type_info (int, struct bitint_info *);
+extern machine_mode default_mode_for_floating_type (enum tree_index);
 extern HOST_WIDE_INT default_stack_clash_protection_alloca_probe_range (void);
 extern void default_select_early_remat_modes (sbitmap);
 extern tree default_preferred_else_value (unsigned, tree, unsigned, tree *);
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 9fa74342919..0b5000acb80 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -624,7 +624,7 @@  enum cv_qualifier {
 };
 
 /* Standard named or nameless data types of the C compiler.  */
-enum tree_index {
+enum tree_index : unsigned {
   TI_ERROR_MARK,
   TI_INTQI_TYPE,
   TI_INTHI_TYPE,
@@ -691,17 +691,18 @@  enum tree_index {
   TI_FLOAT64_TYPE,
   TI_FLOAT128_TYPE,
   TI_FLOATN_TYPE_LAST = TI_FLOAT128_TYPE,
-#define NUM_FLOATN_TYPES (TI_FLOATN_TYPE_LAST - TI_FLOATN_TYPE_FIRST + 1)
+#define NUM_FLOATN_TYPES ((int) (TI_FLOATN_TYPE_LAST		\
+				 - TI_FLOATN_TYPE_FIRST + 1))
   TI_FLOAT32X_TYPE,
   TI_FLOATNX_TYPE_FIRST = TI_FLOAT32X_TYPE,
   TI_FLOAT64X_TYPE,
   TI_FLOAT128X_TYPE,
   TI_FLOATNX_TYPE_LAST = TI_FLOAT128X_TYPE,
   TI_FLOATN_NX_TYPE_LAST = TI_FLOAT128X_TYPE,
-#define NUM_FLOATNX_TYPES (TI_FLOATNX_TYPE_LAST - TI_FLOATNX_TYPE_FIRST + 1)
-#define NUM_FLOATN_NX_TYPES (TI_FLOATN_NX_TYPE_LAST		\
-			     - TI_FLOATN_NX_TYPE_FIRST		\
-			     + 1)
+#define NUM_FLOATNX_TYPES ((int) (TI_FLOATNX_TYPE_LAST		\
+				  - TI_FLOATNX_TYPE_FIRST + 1))
+#define NUM_FLOATN_NX_TYPES ((int) (TI_FLOATN_NX_TYPE_LAST	\
+				  - TI_FLOATN_NX_TYPE_FIRST + 1))
 
   /* Type used by certain backends for __float128, which in C++ should be
      distinct type from _Float128 for backwards compatibility reasons.  */
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 6564b002dc1..bc5175f591e 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -9596,15 +9596,27 @@  build_common_tree_nodes (bool signed_char)
   pointer_sized_int_node = build_nonstandard_integer_type (POINTER_SIZE, 1);
 
   float_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
+  machine_mode float_type_mode
+    = targetm.c.mode_for_floating_type (TI_FLOAT_TYPE);
+  SET_TYPE_MODE (float_type_node, float_type_mode);
+  TYPE_PRECISION (float_type_node)
+    = GET_MODE_PRECISION (float_type_mode).to_constant ();
   layout_type (float_type_node);
 
   double_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
+  machine_mode double_type_mode
+    = targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE);
+  SET_TYPE_MODE (double_type_node, double_type_mode);
+  TYPE_PRECISION (double_type_node)
+    = GET_MODE_PRECISION (double_type_mode).to_constant ();
   layout_type (double_type_node);
 
   long_double_type_node = make_node (REAL_TYPE);
-  TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
+  machine_mode long_double_type_mode
+    = targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE);
+  SET_TYPE_MODE (long_double_type_node, long_double_type_mode);
+  TYPE_PRECISION (long_double_type_node)
+    = GET_MODE_PRECISION (long_double_type_mode).to_constant ();
   layout_type (long_double_type_node);
 
   for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)