"Kewen.Lin" <li...@linux.ibm.com> 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