]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
bitintlower: Fix _BitInt SSA_NAME coalescing ICE [PR126447]
authorJakub Jelinek <jakub@redhat.com>
Wed, 29 Jul 2026 08:04:30 +0000 (10:04 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 29 Jul 2026 08:04:30 +0000 (10:04 +0200)
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  <jakub@redhat.com>

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 <andrew.pinski@oss.qualcomm.com>
gcc/gimple-lower-bitint.cc
gcc/testsuite/gcc.dg/bitint-138.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/ubsan/bitint-5.c [new file with mode: 0644]

index 9767e9821f86fead8396893d02f2d207bd636636..2fabda01fcf8d41eb06dee35c8903d1a5525fb95 100644 (file)
@@ -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 (file)
index 0000000..41780c1
--- /dev/null
@@ -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 (file)
index 0000000..22a613d
--- /dev/null
@@ -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;
+}