From: Jakub Jelinek Date: Wed, 29 Jul 2026 08:04:30 +0000 (+0200) Subject: bitintlower: Fix _BitInt SSA_NAME coalescing ICE [PR126447] X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=cd9428362b6585e77ea2a171ec030894fcfa4d1c;p=thirdparty%2Fgcc.git bitintlower: Fix _BitInt SSA_NAME coalescing ICE [PR126447] The following testcases ICE, because the build_bitint_stmt_ssa_conflicts function sets for those ifns muldiv_p to true (similarly to the MULT_EXPR and division/modulo ones) to prevent the lhs from being mapped into the same underlying variable as the input operand(s). Now, if the lhs and at least one of the operands SSA_NAME_OCCURS_IN_ABNORMAL_PHI, we can trigger ICE because we fail to coalesce something that has to be coalesced. For MULT_EXPR etc. we handle this in gimple_lower_bitint, by /* For multiplication and division with (ab) lhs and one or both operands force the operands into new SSA_NAMEs to avoid coalescing failures. */ if (TREE_CODE (rhs1) == SSA_NAME && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs1)) { first_large_huge = 0; tree t = make_ssa_name (TREE_TYPE (rhs1)); g = gimple_build_assign (t, SSA_NAME, rhs1); gsi_insert_before (&gsi, g, GSI_SAME_STMT); gimple_set_location (g, loc); gimple_assign_set_rhs1 (stmt, t); if (rhs1 == rhs2) { gimple_assign_set_rhs2 (stmt, t); rhs2 = t; } update_stmt (stmt); } etc. a few lines above the hunk below. This patch just adds the same thing for the problematic internal fn calls (not handling that way the .MUL_OVERFLOW etc. ifns, because those do return COMPLEX_EXPR of BITINT_TYPE and so the problematic case shouldn't exist there). 2026-07-29 Jakub Jelinek PR middle-end/126447 * gimple-lower-bitint.cc (gimple_lower_bitint): For ifn calls with large/huge _BitInt (ab) SSA_NAME lhs if they have such (ab) argument too, force it into temporary SSA_NAME for IFN_BSWAP, IFN_BITREVERSE, IFN_UBSAN_CHECK_MUL and, if bitint_big_endian, also for IFN_UBSAN_CHECK_{ADD,SUB}. * gcc.dg/ubsan/bitint-5.c: New test. * gcc.dg/bitint-138.c: New test. Reviewed-by: Andrea Pinski --- diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc index 9767e9821f8..2fabda01fcf 100644 --- a/gcc/gimple-lower-bitint.cc +++ b/gcc/gimple-lower-bitint.cc @@ -7577,6 +7577,46 @@ gimple_lower_bitint (void) add_phi_arg (phi, rhs2, e3, UNKNOWN_LOCATION); break; } + else if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (s) + && is_gimple_call (stmt) + && gimple_call_internal_p (stmt)) + switch (gimple_call_internal_fn (stmt)) + { + case IFN_UBSAN_CHECK_ADD: + case IFN_UBSAN_CHECK_SUB: + if (!bitint_big_endian) + break; + /* FALLTHRU */ + case IFN_UBSAN_CHECK_MUL: + case IFN_BSWAP: + case IFN_BITREVERSE: + for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i) + { + location_t loc = gimple_location (stmt); + gsi = gsi_for_stmt (stmt); + /* Similar case to multiplication/division with (ab) + above for internal functions which set muldiv_p. */ + tree arg = gimple_call_arg (stmt, i); + if (TREE_CODE (arg) == SSA_NAME + && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg)) + { + first_large_huge = 0; + tree t = make_ssa_name (TREE_TYPE (arg)); + g = gimple_build_assign (t, SSA_NAME, arg); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + gimple_set_location (g, loc); + gimple_call_set_arg (stmt, i, t); + if (i == 0 + && gimple_call_num_args (stmt) >= 2 + && gimple_call_arg (stmt, 1) == arg) + gimple_call_set_arg (stmt, 1, t); + update_stmt (stmt); + } + } + break; + default: + break; + } } /* We need to also rewrite stores of large/huge _BitInt INTEGER_CSTs into memory. Such functions could have no large/huge SSA_NAMEs. */ diff --git a/gcc/testsuite/gcc.dg/bitint-138.c b/gcc/testsuite/gcc.dg/bitint-138.c new file mode 100644 index 00000000000..41780c1d6eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/bitint-138.c @@ -0,0 +1,26 @@ +/* PR target/126447 */ +/* { dg-do compile { target bitint575 } } */ +/* { dg-options "-O0" } */ + +void foo (int); +[[gnu::returns_twice]] void bar (); + +unsigned _BitInt(575) +baz () +{ + unsigned _BitInt(575) w = 1; + bar (); + w = __builtin_bitreverseg (w); + foo (3); + return w; +} + +unsigned _BitInt(512) +qux () +{ + unsigned _BitInt(512) w = 1; + bar (); + w = __builtin_bswapg (w); + foo (3); + return w; +} diff --git a/gcc/testsuite/gcc.dg/ubsan/bitint-5.c b/gcc/testsuite/gcc.dg/ubsan/bitint-5.c new file mode 100644 index 00000000000..22a613dd06a --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/bitint-5.c @@ -0,0 +1,36 @@ +/* PR middle-end/126447 */ +/* { dg-do compile { target bitint575 } } */ +/* { dg-options "-fsanitize=signed-integer-overflow" } */ + +void foo (int); +[[gnu::returns_twice]] void bar (); + +_BitInt(575) +baz () +{ + _BitInt(575) w = 1; + bar (); + w *= 3; + foo (3); + return w; +} + +_BitInt(575) +qux () +{ + _BitInt(575) w = 1; + bar (); + w += 3; + foo (3); + return w; +} + +_BitInt(575) +fred (_BitInt(575) x) +{ + _BitInt(575) w = 1; + bar (); + w -= x; + foo (3); + return w; +}