https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115802
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu.org, | |rguenth at gcc dot gnu.org Last reconfirmed| |2024-07-08 Component|middle-end |ipa Ever confirmed|0 |1 Keywords| |wrong-code Status|UNCONFIRMED |NEW --- Comment #10 from Richard Biener <rguenth at gcc dot gnu.org> --- I can't comment as to C standards correctness of this, but GCC has no knowledge of locking or of memory model guarantees resulting from atomic operations. Instead the middle-end relies on alias-analysis identifying atomic operations (and locking by means of that being function calls with unknown side-effects on global memory) as possibly clobbering and using global memory. For global statics (and promoted so by LTO due to export constraints) this breaks down when there is no address-use of them (surviving until the end of compilation). The general ref_maybe_used_by_call_p_1 excempts globals from this rule (but because of other reasons). It's interesting that enabling inlining of your mutex ops "fixes" the testcase, as well as using noipa instead of noinline. DOM does the "bad" transform instead using stmt_may_clobber_ref_p_1 and there via IPA reference data: /* Check if base is a global static variable that is not written by the function. */ if (callee != NULL_TREE && VAR_P (base) && TREE_STATIC (base)) { struct cgraph_node *node = cgraph_node::get (callee); bitmap written; int id; if (node && (id = ipa_reference_var_uid (base)) != -1 && (written = ipa_reference_get_written_global (node)) && !bitmap_bit_p (written, id)) return false; IPA reference commputed that mutex_lock does not write to 'val' (but of course it doesn't compute that __atomic_store doesn't write to 'val'). IPA reference circumvents the /* If the reference is based on a decl that is not aliased the call cannot possibly clobber it. */ if (DECL_P (base) && !may_be_aliased (base) /* But local non-readonly statics can be modified through recursion or the call may implement a threading barrier which we must treat as may-def. */ && (TREE_READONLY (base) || !is_global_var (base))) return false; protection against threading barriers. Note this in the end means that exposing the implementation of thread primitives is unsafe and those should be marked with 'noipa' to prevent IPA analysis looking into their implementation. I'm not sure if we should "blacklist" IPA reference when it uses atomics or whether that would reliably help. Honza?