https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126554

            Bug ID: 126554
           Summary: GCC emits an unnecessary stack protector when
                    performing an atomic operation on a struct member
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arsen at gcc dot gnu.org
                CC: pedro.falcato at gmail dot com
  Target Milestone: ---
            Target: x86_64-linux-gnu

consider the following:

  struct foo { unsigned int x; };

  void stack_protected(struct foo *p)
  {
      struct foo expected = {0};
      __atomic_compare_exchange_n(&p->x, &expected.x, 1, false,
__ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
  }

  void stack_unprotected(unsigned *p)
  {
      unsigned expected = 0;
      __atomic_compare_exchange_n(p, &expected, 1, false, __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED);
  }

... these two functions should produce the same code, but the former emits a
stack protector.

this is because, in the former, 'expected' is considered addressable:

Breakpoint 5, add_stack_protection_conflicts () at
../../gcc/gcc/cfgexpand.cc:2341
2341            ret = true;
(gdb) list
2336      phase = XNEWVEC (unsigned char, n);
2337      for (i = 0; i < n; ++i)
2338        {
2339          phase[i] = stack_protect_decl_phase (stack_vars[i].decl);
2340          if (TREE_ADDRESSABLE (stack_vars[i].decl))
2341            ret = true;
2342        }
2343
2344      for (i = 0; i < n; ++i)
2345        {
(gdb) p stack_vars[i].decl
$1 = <var_decl 0x7ffff6bd6e40 expected>
(gdb) 

... this  ret = true  later leads to:

        has_addressable_vars = add_stack_protection_conflicts ();

      if (flag_stack_protect == SPCT_FLAG_STRONG && has_addressable_vars)
        gen_stack_protect_signal = true;

ISTM that PR105495 is a similar case, though it manifests differently

Reply via email to