On Fri, Jun 19, 2026 at 4:12 AM Richard Biener <[email protected]> wrote: > > The following avoids diagnosing bit sets/clears that involve RMW > cycles to uninitialized memory. This is for example exposed by > __builtin_clear_padding lowering which suppresses diagnostics but > those can re-surface with vectorization. > > Bootstrapped and tested on x86_64-unknown-linux-gnu. > > OK? > > Thanks, > Richard. > > PR tree-optimization/110743 > * tree-ssa-uninit.cc (maybe_warn_operand): Suppress diagnostics > on RMW cycles setting/clearing bits. > > * gcc.dg/uninit-pr110743.c: New testcase. > --- > gcc/testsuite/gcc.dg/uninit-pr110743.c | 22 ++++++++++++++++++++++ > gcc/tree-ssa-uninit.cc | 24 ++++++++++++++++++++++++ > 2 files changed, 46 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/uninit-pr110743.c > > diff --git a/gcc/testsuite/gcc.dg/uninit-pr110743.c > b/gcc/testsuite/gcc.dg/uninit-pr110743.c > new file mode 100644 > index 00000000000..5a95f60cf9b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/uninit-pr110743.c > @@ -0,0 +1,22 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -Wall" } */ > + > +void foo (int *); > + > +void bar() > +{ > + int x, tem; > + tem = x; /* { dg-bogus "used uninitialized" } */ > + tem = tem | 5; > + x = tem; > + foo (&x); > +} > + > +void baz() > +{ > + int x, tem; > + tem = x; /* { dg-bogus "used uninitialized" } */ > + tem = tem & 5; > + x = tem; > + foo (&x); > +} > diff --git a/gcc/tree-ssa-uninit.cc b/gcc/tree-ssa-uninit.cc > index dbd187e21d7..107ed21e10b 100644 > --- a/gcc/tree-ssa-uninit.cc > +++ b/gcc/tree-ssa-uninit.cc > @@ -758,6 +758,30 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, > tree rhs, > if (is_empty_type (rhstype)) > return NULL_TREE; > > + /* Avoid diagnosing read-modify-write cycles that in the end only > + sets a subset of bits to zero or one. > + ??? Note that further reads will then appear (partly) initialized > + and will not be diagnosed. */ > + gimple *use_stmt; > + if (gimple_assign_load_p (stmt) > + && TREE_CODE (lhs) == SSA_NAME > + && single_imm_use (lhs, &luse_p, &use_stmt)) > + { > + gassign *use_ass = dyn_cast <gassign *> (use_stmt); > + for (int i = 0; i < 2; ++i) > + if (use_ass > + && (gimple_assign_rhs_code (use_ass) == BIT_AND_EXPR > + || gimple_assign_rhs_code (use_ass) == BIT_IOR_EXPR) > + && single_imm_use (gimple_assign_lhs (use_ass), &luse_p, > + &use_stmt)) > + use_ass = dyn_cast <gassign *> (use_stmt); > + if (use_ass > + && gimple_vdef (use_ass) > + && operand_equal_p (gimple_assign_rhs1 (stmt), > + gimple_assign_lhs (use_ass))) > + return NULL_TREE; > + }
Hmm, is there a way to combine this with the BIT_INSERT_EXPR loop since both are basically trying to prevent the same thing? It is handled closer to the top of the function. Thanks, Andrea > + > bool warned = false; > /* We didn't find any may-defs so on all paths either > reached function entry or a killing clobber. */ > -- > 2.51.0
