This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug tree-optimization/86318] const local aggregates can be assumed not to be modified even when escaped


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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2018-06-26
                 CC|                            |rguenth at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Confirmed.  It is the frontend doing the optimization likely during its
folding.

The middle-end doesn't in any way honor 'const' since

 const S s = { .... };

can be expanded (gimplified) to a automatic variable initialized by
one or multiple assignments (so that automatic variable isn't "constant"):

For example g1:

g1 ()
{
  const int a[1];
  int _1;

  <bb 2> :
  a[0] = 1;
  f (&a);
  _1 = a[0];
  if (_1 != 1)

so here a[0] is assigned to.

If we'd always place such constants in .rodata (use a CONST_DECL) things
might work but then optimization cannot elide (parts of) such initializer.

Previously RTL had a thing like RTX_UNCHANGING which meant values do not
change once set.  But that was a recipie for desaster (wrong-code).

For simple cases like g1 the FE could fold the read from *a but I could
see the following case as difficult for the FE to "fold" (unless you
want to "constexpr" evaluate all stmts).

void g3 (void)
{
  const struct S s = { 1 };
  f (&s);
  struct S q = s;
  if (q.i != 1)
    abort ();
}

A solution on the optimizer side is difficult, it would likely need to
separate "initialization" from "modification" somehow.  Like wrapping
the "const" a's in the accesses:

g1 ()
{
  const int a[1];
  int _1;

  <bb 2> :
  a[0] = 1;
  f (&CONST<a>);
  _1 = CONST<a>[0];

either by a bit on the reference trees or by an explicit handled-component.
The address-taking context is somewhat awkward to deal with I think.

In the end it would be the FEs responsibility to "wrap" stuff or the
gimplifier could wrap all but the initialization stmts.

Or we could do it the other way around, wrap the initialization refs.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]