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?

Reply via email to