"Kewen.Lin" <[email protected]> writes:
> Hi,
>
> With some historical reasons, rs6000 defines KFmode, TFmode
> and IFmode to have different mode precision, but it causes
> some issues and needs some workarounds such as r14-6478 for
> PR112788. So we are going to make all rs6000 128 bit scalar
> FP modes have 128 bit precision. Be prepared for that, this
> patch is to make function convert_mode_scalar allow same
> precision FP modes conversion if their underlying formats are
> ibm_extended_format and ieee_quad_format respectively, just
> like the existing special treatment on arm_bfloat_half_format
> <-> ieee_half_format. It also factors out all the relevant
> checks into a lambda function.
>
> Bootstrapped and regtested on x86_64-redhat-linux and
> powerpc64{,le}-linux-gnu.
>
> Is it ok for trunk?
>
> BR,
> Kewen
> -----
> PR target/112993
>
> gcc/ChangeLog:
>
> * expr.cc (convert_mode_scalar): Allow same precision conversion
> between scalar floating point modes if whose underlying format is
> ibm_extended_format or ieee_quad_format, and refactor assertion
> with new lambda function acceptable_same_precision_modes.
> ---
> gcc/expr.cc | 30 ++++++++++++++++++++++++------
> 1 file changed, 24 insertions(+), 6 deletions(-)
>
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index ffbac513692..eac4dcc982e 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -338,6 +338,29 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
> enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
> : (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
>
> + auto acceptable_same_precision_modes
> + = [] (scalar_mode from_mode, scalar_mode to_mode) -> bool
> + {
> + if (DECIMAL_FLOAT_MODE_P (from_mode) != DECIMAL_FLOAT_MODE_P (to_mode))
> + return true;
> +
> + /* arm_bfloat_half_format <-> ieee_half_format */
> + if ((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))
> + return true;
> +
> + /* ibm_extended_format <-> ieee_quad_format */
> + if ((REAL_MODE_FORMAT (from_mode) == &ibm_extended_format
> + && REAL_MODE_FORMAT (to_mode) == &ieee_quad_format)
> + || (REAL_MODE_FORMAT (from_mode) == &ieee_quad_format
> + && REAL_MODE_FORMAT (to_mode) == &ibm_extended_format))
> + return true;
> +
> + return false;
> + };
> +
> if (to_real)
> {
> rtx value;
> @@ -346,12 +369,7 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
>
> gcc_assert ((GET_MODE_PRECISION (from_mode)
> != GET_MODE_PRECISION (to_mode))
> - || (DECIMAL_FLOAT_MODE_P (from_mode)
> - != DECIMAL_FLOAT_MODE_P (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));
> + || acceptable_same_precision_modes (from_mode, to_mode));
>
> if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode))
> {
> --
> 2.39.1
This part looks good to me FWIW, but what's the correct behaviour of:
if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode))
{
if (REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
&& REAL_MODE_FORMAT (from_mode) == &ieee_half_format)
/* libgcc implements just __trunchfbf2, not __extendhfbf2. */
tab = trunc_optab;
else
/* Conversion between decimal float and binary float, same
size. */
tab = DECIMAL_FLOAT_MODE_P (from_mode) ? trunc_optab : sext_optab;
for the new pairing? The intent for bfloat/half seems to be that bfloat
is treated as arbitrarily “lesser than” half, so half->bfloat is a
truncation and bfloat->half is an extension. It seems like it would be
good to do something similar for the new pair, so that the float modes
still form a total order in terms of extension & truncation.
Thanks,
Richard