Tested to fix build for MMIX (and to fix a few type-generic-builtin
test-cases; c-c++-common/pr111309-1.c, gcc.dg/torture/pr116480-1.c).
Also regtested cris-elf and native x86_64-pc-linux-gnu.

Ok for master and gcc-15?

-- >8 --
MMIX uses the default definition of MAX_FIXED_MODE_SIZE, which is
GET_MODE_SIZE (DImode) (arguably a suboptimal default, but that's for
another patch).

That macro doesn't reflect the size of the largest mode *valid* on the
target, but rather the size of the largest mode that *should* be
generated when synthesizing operations doing optimizations.  The
keyword "generated" appears to be missing from the documentation for
MAX_FIXED_MODE_SIZE or is meant to be implied by "use": (perhaps,
s/should actually be used/should actually be generated/, and note,
still "should" not "must").  For example, when putting
larger-than-register objects on the stack it could be the threshold
when to use BLKmode instead of an integer mode (e.g. TImode).  But,
this should affect only optimization, not validness of code and
certainly not cause an ICE, as in PR 120935.

The function fold_builtin_bit_query is responsible for transforming
type-generic calls into type-specific calls.  It currently makes use
of MAX_FIXED_MODE_SIZE.  The effect is here, when transforming
__builtin_clzg(__int128 x), instead of an expression with calls to
__builtin_clzl, it's wrongly changed into a call to an internal
function .CLZ (x).  (N.B. this would validly happen when there's a
matching instruction.)  When later on, another part of gcc sees that
there is no such internal function; no such instruction, boom: ICE.

Here, what's intended to be generated, is *half* the size of the
existing incoming type.  Actually, MAX_FIXED_MODE_SIZE seems to be
inconsistently used instead of the size of unsigned long long.  That
macro just doesn't have to be consulted in this code.

        PR middle-end/120935
        * builtins.cc (fold_builtin_bit_query): Do not consider
        MAX_FIXED_MODE_SIZE.
---
 gcc/builtins.cc | 36 +++++++++++++-----------------------
 1 file changed, 13 insertions(+), 23 deletions(-)

diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 7f580a3145ff..728ae5e6c2c0 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -10283,8 +10283,8 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
       gcc_unreachable ();
     }
 
-  if (TYPE_PRECISION (arg0_type)
-      <= TYPE_PRECISION (long_long_unsigned_type_node))
+  unsigned int llu_size = TYPE_PRECISION (long_long_unsigned_type_node);
+  if (TYPE_PRECISION (arg0_type) <= llu_size)
     {
       if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
 
@@ -10305,13 +10305,12 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
          fcodei = fcodell;
        }
     }
-  else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
+  else if (TYPE_PRECISION (arg0_type) <= 2 * llu_size)
     {
       cast_type
-       = build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
+       = build_nonstandard_integer_type (2 * llu_size,
                                          TYPE_UNSIGNED (arg0_type));
-      gcc_assert (TYPE_PRECISION (cast_type)
-                 == 2 * TYPE_PRECISION (long_long_unsigned_type_node));
+      gcc_assert (TYPE_PRECISION (cast_type) == 2 * llu_size);
       fcodei = END_BUILTINS;
     }
   else
@@ -10342,9 +10341,7 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
       arg2 = NULL_TREE;
     }
   tree call = NULL_TREE, tem;
-  if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
-      && (TYPE_PRECISION (arg0_type)
-         == 2 * TYPE_PRECISION (long_long_unsigned_type_node))
+  if ((TYPE_PRECISION (arg0_type) == 2 * llu_size)
       /* If the target supports the optab, then don't do the expansion. */
       && !direct_internal_fn_supported_p (ifn, arg0_type, OPTIMIZE_FOR_BOTH))
     {
@@ -10354,8 +10351,7 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
                   ? long_long_unsigned_type_node
                   : long_long_integer_type_node);
       tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
-                            build_int_cst (integer_type_node,
-                                           MAX_FIXED_MODE_SIZE / 2));
+                            build_int_cst (integer_type_node, llu_size));
       hi = fold_convert (type, hi);
       tree lo = fold_convert (type, arg0);
       switch (fcode)
@@ -10363,8 +10359,7 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
        case BUILT_IN_CLZG:
          call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
          call = fold_build2 (PLUS_EXPR, integer_type_node, call,
-                             build_int_cst (integer_type_node,
-                                            MAX_FIXED_MODE_SIZE / 2));
+                             build_int_cst (integer_type_node, llu_size));
          if (arg2)
            call = fold_build3 (COND_EXPR, integer_type_node,
                                fold_build2 (NE_EXPR, boolean_type_node,
@@ -10380,8 +10375,7 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
        case BUILT_IN_CTZG:
          call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
          call = fold_build2 (PLUS_EXPR, integer_type_node, call,
-                             build_int_cst (integer_type_node,
-                                            MAX_FIXED_MODE_SIZE / 2));
+                             build_int_cst (integer_type_node, llu_size));
          if (arg2)
            call = fold_build3 (COND_EXPR, integer_type_node,
                                fold_build2 (NE_EXPR, boolean_type_node,
@@ -10397,15 +10391,13 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
        case BUILT_IN_CLRSBG:
          tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
          tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
-                            build_int_cst (integer_type_node,
-                                           MAX_FIXED_MODE_SIZE / 2));
+                            build_int_cst (integer_type_node, llu_size));
          tem = fold_build3 (COND_EXPR, integer_type_node,
                             fold_build2 (LT_EXPR, boolean_type_node,
                                          fold_build2 (BIT_XOR_EXPR, type,
                                                       lo, hi),
                                          build_zero_cst (type)),
-                            build_int_cst (integer_type_node,
-                                           MAX_FIXED_MODE_SIZE / 2 - 1),
+                            build_int_cst (integer_type_node, llu_size - 1),
                             tem);
          call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
          call = save_expr (call);
@@ -10413,15 +10405,13 @@ fold_builtin_bit_query (location_t loc, enum 
built_in_function fcode,
                              fold_build2 (NE_EXPR, boolean_type_node,
                                           call,
                                           build_int_cst (integer_type_node,
-                                                         MAX_FIXED_MODE_SIZE
-                                                         / 2 - 1)),
+                                                         llu_size - 1)),
                              call, tem);
          break;
        case BUILT_IN_FFSG:
          call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
          call = fold_build2 (PLUS_EXPR, integer_type_node, call,
-                             build_int_cst (integer_type_node,
-                                            MAX_FIXED_MODE_SIZE / 2));
+                             build_int_cst (integer_type_node, llu_size));
          call = fold_build3 (COND_EXPR, integer_type_node,
                              fold_build2 (NE_EXPR, boolean_type_node,
                                           hi, build_zero_cst (type)),
-- 
2.39.2

Reply via email to