https://gcc.gnu.org/g:3f6e6d4b408a26f69816f18d88dde4d983677488

commit r15-2083-g3f6e6d4b408a26f69816f18d88dde4d983677488
Author: Kewen Lin <li...@linux.ibm.com>
Date:   Wed Jul 17 00:14:18 2024 -0500

    expr: Allow same precision modes conversion between {ibm_extended, 
ieee_quad}_format
    
    With some historical reasons, rs6000 defines KFmode, TFmode
    and IFmode to have different mode precisions, but it causes
    some issues and needs some workarounds such as PR112993.
    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.  Besides, similar to ieee fp16
    -> bfloat conversion, it adopts trunc_optab rather than
    sext_optab for ibm128 to ieee128 conversion.
    
            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.  Use
            trunc_optab rather than sext_optab for ibm128 to ieee128 conversion.
            * optabs-libfuncs.cc (gen_trunc_conv_libfunc): Use trunc_optab 
rather
            than sext_optab for ibm128 to ieee128 conversion.

Diff:
---
 gcc/expr.cc            | 39 ++++++++++++++++++++++++++++++---------
 gcc/optabs-libfuncs.cc |  4 +++-
 2 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index ffbac5136923..2089c2b86a98 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,18 +369,16 @@ 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))
        {
-         if (REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
-             && REAL_MODE_FORMAT (from_mode) == &ieee_half_format)
-           /* libgcc implements just __trunchfbf2, not __extendhfbf2.  */
+         if ((REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
+              && REAL_MODE_FORMAT (from_mode) == &ieee_half_format)
+             || (REAL_MODE_FORMAT (to_mode) == &ieee_quad_format
+                 && REAL_MODE_FORMAT (from_mode) == &ibm_extended_format))
+           /* libgcc implements just __trunchfbf2, not __extendhfbf2;
+              and __trunctfkf2, not __extendtfkf2.  */
            tab = trunc_optab;
          else
            /* Conversion between decimal float and binary float, same
diff --git a/gcc/optabs-libfuncs.cc b/gcc/optabs-libfuncs.cc
index 26729910d92b..ab97eace80e5 100644
--- a/gcc/optabs-libfuncs.cc
+++ b/gcc/optabs-libfuncs.cc
@@ -591,7 +591,9 @@ gen_trunc_conv_libfunc (convert_optab tab,
 
   if (GET_MODE_PRECISION (float_fmode) <= GET_MODE_PRECISION (float_tmode)
       && (REAL_MODE_FORMAT (float_tmode) != &arm_bfloat_half_format
-         || REAL_MODE_FORMAT (float_fmode) != &ieee_half_format))
+         || REAL_MODE_FORMAT (float_fmode) != &ieee_half_format)
+      && (REAL_MODE_FORMAT (float_tmode) != &ieee_quad_format
+         || REAL_MODE_FORMAT (float_fmode) != &ibm_extended_format))
     return;
 
   if (GET_MODE_CLASS (float_tmode) == GET_MODE_CLASS (float_fmode))

Reply via email to