https://gcc.gnu.org/g:a4844311b2f48436998f02c8a1c224086426a0cc

commit r17-5400-ga4844311b2f48436998f02c8a1c224086426a0cc
Author: Jakub Jelinek <[email protected]>
Date:   Tue Oct 20 12:05:03 2026 +0200

    bitintlower: Fix up the single use SSA_NAME optimization [PR127905]
    
    The _BitInt lowering contains an optimization, if a SSA_NAME has a single
    use and if its partition is reused for other SSA_NAMEs, we try to emit
    a CLOBBER on the underlying variable of the partition after the use if
    possible, so that GIMPLE opts know it is dead and can optimize better.
    Already in the past I had to fix this up once, if there are SSA_NAME
    copies, this can misbehave in some cases due to the coalescing algorithm
    special casing those.
    
    The following testcase shows a different problem.  There is an SSA_NAME
    with a single use, but the definition of the SSA_NAME is before a loop
    and the use within a loop.  In this case emitting a CLOBBER inside of
    the loop is wrong, the first loop's iteration will use correct value
    of the underlying var, but second and following iteration will be after
    a CLOBBER, so e.g. if it is unrolled, the uses in those iterations will
    be handled as if they read uninitialized memory.
    
    The following patch is my attempt to detect the case where the use
    stmt can be invoked more often than the definition.
    If def and use are in the same bb, it is IMHO fine, otherwise I compare
    whether the def and use are in the same loop (that is IMHO also ok as
    long as no irreducible loop is involved).
    
    I've also collected statistics, and this patch in the testsuite emits just
    0.137% fewer clobbers than before, so I'm not worried it will pessimize 
stuff
    too much.
    
    2026-10-20  Jakub Jelinek  <[email protected]>
    
            PR tree-optimization/127905
            * gimple-lower-bitint.cc (gimple_lower_bitint): Don't add to
            m_single_use_names versions of SSA_NAMEs where their single use
            is within a different loop from the definition (or if use is
            in irreducible loop, in a different bb than def).
    
            * gcc.dg/torture/bitint-112.c: New test.
    
    Reviewed-by: Richard Biener <[email protected]>

Diff:
---
 gcc/gimple-lower-bitint.cc                | 53 ++++++++++++++++++++++++++++---
 gcc/testsuite/gcc.dg/torture/bitint-112.c | 35 ++++++++++++++++++++
 2 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc
index 5d844d2a9561..f871f68ba1e6 100644
--- a/gcc/gimple-lower-bitint.cc
+++ b/gcc/gimple-lower-bitint.cc
@@ -7247,6 +7247,7 @@ gimple_lower_bitint (void)
   small_max_prec = mid_min_prec = large_min_prec = huge_min_prec = 0;
   limb_prec = abi_limb_prec = 0;
   bitint_big_endian = false;
+  bool loop_init_done = false;
 
   unsigned int i;
   for (i = 0; i < num_ssa_names; ++i)
@@ -7975,7 +7976,7 @@ gimple_lower_bitint (void)
          bitmap_set_bit (large_huge.m_names, SSA_NAME_VERSION (s));
          if (has_single_use (s))
            {
-             tree s2 = s;
+             tree s2 = s, s3 = s;
              /* The coalescing hook special cases SSA_NAME copies.
                 Make sure not to mark in m_single_use_names single
                 use SSA_NAMEs copied from non-single use SSA_NAMEs.  */
@@ -7989,13 +7990,52 @@ gimple_lower_bitint (void)
                      s2 = NULL_TREE;
                      break;
                    }
+                 s3 = s2;
                }
              if (s2)
                {
-                 if (!large_huge.m_single_use_names)
-                   large_huge.m_single_use_names = BITMAP_ALLOC (NULL);
-                 bitmap_set_bit (large_huge.m_single_use_names,
-                                 SSA_NAME_VERSION (s));
+                 /* Only set m_single_use_names for SSA_NAMEs where
+                    the definition and use are within the same loop,
+                    otherwise if the use could be executed more times
+                    than the def stmt, we can't emit clobbers.
+                    Or if irreducible loops are involved, only handle
+                    same bb definitions.  */
+                 gimple *def = SSA_NAME_DEF_STMT (s3), *use;
+                 use_operand_p use_p;
+                 single_imm_use (s, &use_p, &use);
+                 basic_block def_bb, use_bb;
+                 if (SSA_NAME_IS_DEFAULT_DEF (s3))
+                   def_bb = NULL;
+                 else
+                   def_bb = gimple_bb (def);
+                 use_bb = gimple_bb (use);
+                 if (def_bb != use_bb)
+                   {
+                     if (!loop_init_done)
+                       {
+                         unsigned flags
+                           = (AVOID_CFG_MODIFICATIONS
+                              | LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS);
+                         loop_optimizer_init (flags);
+                         loop_init_done = true;
+                       }
+                     if ((use_bb->flags & BB_IRREDUCIBLE_LOOP) == 0)
+                       {
+                         class loop *def_loop
+                           = def_bb ? def_bb->loop_father
+                                    : get_loop (cfun, 0);
+                         class loop *use_loop = use_bb->loop_father;
+                         if (def_loop == use_loop)
+                           def_bb = use_bb;
+                       }
+                   }
+                 if (def_bb == use_bb)
+                   {
+                     if (!large_huge.m_single_use_names)
+                       large_huge.m_single_use_names = BITMAP_ALLOC (NULL);
+                     bitmap_set_bit (large_huge.m_single_use_names,
+                                     SSA_NAME_VERSION (s));
+                   }
                }
            }
          if (SSA_NAME_VAR (s)
@@ -8677,6 +8717,9 @@ gimple_lower_bitint (void)
        }
     }
 
+  if (loop_init_done)
+    loop_optimizer_finalize ();
+
   return ret;
 }
 
diff --git a/gcc/testsuite/gcc.dg/torture/bitint-112.c 
b/gcc/testsuite/gcc.dg/torture/bitint-112.c
index 4d4dab67b890..521d8426646f 100644
--- a/gcc/testsuite/gcc.dg/torture/bitint-112.c
+++ b/gcc/testsuite/gcc.dg/torture/bitint-112.c
@@ -1,3 +1,38 @@
+/* PR tree-optimization/127905 */
+/* { dg-do run { target bitint } } */
+
+#if __BITINT_MAXWIDTH__ >= 135
+typedef unsigned _BitInt(135) B;
+
+[[gnu::noipa]] B
+foo (B b, int c, unsigned n)
+{
+  B x = c ? b : 7;
+  B y = b;
+  for (unsigned i = 0; i < n; i++)
+    y = x + i;
+  return y;
+}
+
+[[gnu::noipa]] B
+bar (B b, B a, int c, unsigned n)
+{
+  B x = c ? b : 7;
+  B y = b;
+  for (unsigned i = 0; i < n; i++)
+    y = c ? x + 7 : a;
+  return y;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 135
+  if (foo (5, 1, 3) != 7 || bar (5, 9, 1, 3) != 12)
+    __builtin_abort ();
+#endif
+}
 /* { dg-do run { target bitint } } */
 /* { dg-options "-std=c23 -pedantic-errors" } */

Reply via email to