https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114161
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Ever confirmed|0 |1 CC| |hubicka at gcc dot gnu.org Last reconfirmed| |2024-02-29 --- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- Yeah, we don't have any sort of IPA pass that would optimistically treat 'a' as constant [zero] and figure the stores from non-constant would not be executed. I bet it breaks down with clang if you had two of those functions in the TU. In other context we spoke about that knowing a variable is only ever set in a single function would help and might get this optimized during value-numbering. But I think no such feature ever materialized? There is the partly matching used_by_single_function flag in the cgraph which would be good enough here but if there's another function reading from a it would break down. For example the following fixes the testcase, but this really isn't enough because if a store to 'a' prevails this is an invalid transform so we'd have to make sure to iterate and somehow invalidate the global. I bet that clang has some very simple IPA hack that makes this work since IIRC it comes up in SPEC libquantum which has a global 'debug' initialized to zero in main() but read in many places, guarding printf calls. So you'd need the written-in-single-function and there written-with-same-as-static-init-value. IIRC there's a similar case in some SPEC 2000 benchmark. diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc index 2ee02e45d56..8f094c05bae 100644 --- a/gcc/tree-ssa-sccvn.cc +++ b/gcc/tree-ssa-sccvn.cc @@ -2401,6 +2401,11 @@ vn_reference_lookup_2 (ao_ref *op, tree vuse, void *data_) SSA_NAME_VAR (TREE_OPERAND (base, 0)), true, op_offset, op_size); } + if (base + && VAR_P (base)) + if (auto n = varpool_node::get (base)) + if (n->used_by_single_function) + v = DECL_INITIAL (base); if (v) return data->finish (vr->set, vr->base_set, v); }