https://gcc.gnu.org/g:6d842965024cad9f6d3588d300c11c2c2e4a2dba
commit r17-1765-g6d842965024cad9f6d3588d300c11c2c2e4a2dba Author: Richard Biener <[email protected]> Date: Fri Jun 19 11:45:46 2026 +0200 tree-optimization/110743 - do not warn for bit sets/clears to uninit memory 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. 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. Diff: --- gcc/testsuite/gcc.dg/uninit-pr110743.c | 22 ++++++++++++++++++++++ gcc/tree-ssa-uninit.cc | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/gcc/testsuite/gcc.dg/uninit-pr110743.c b/gcc/testsuite/gcc.dg/uninit-pr110743.c new file mode 100644 index 000000000000..5a95f60cf9b0 --- /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 dbd187e21d7a..107ed21e10b8 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; + } + bool warned = false; /* We didn't find any may-defs so on all paths either reached function entry or a killing clobber. */
