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