On Mon, Jul 14, 2025, at 10:43 PM, Hans-Peter Nilsson wrote:
> 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.
FYI, this patch also fixes PR120144, similar ICE related to
MAX_FIXED_MODE_SIZE/int128 when building libstdc++ for mips64-elf.
pietro.
> 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