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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot 
gnu.org

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
OK, so the abort () call is only elided during RTL optimization before the
change.  The change itself first manifests during ESRA as

 void testK ()
 {
-  <unnamed-unsigned:10> x$j;
   unsigned int D.1835;
   static unsigned int s = 1388815473;
   unsigned int D.1834;
@@ -167,14 +157,13 @@
   _5 = (<unnamed-unsigned:6>) _51;
   sK.k = _5;
   x = sK;
-  x$j_55 = sK.j;
   y$k_36 = sK.k;
   _37 = (unsigned char) y$k_36;
   _38 = (unsigned char) _46;
   _39 = _37 + _38;
   _40 = (<unnamed-unsigned:6>) _39;
   _41 = (unsigned int) _40;
-  _6 = x$j_55;
+  _6 = x.j;
   _7 = sK.j;
   if (_6 != _7)
     goto <bb 7>; [INV]

there are other uses of 'x' below, unchanged:

  else
    goto <bb 6>; [INV]

  <bb 6> :
  _8 = BIT_FIELD_REF <x, 8, 0>;
  _9 = BIT_FIELD_REF <sK, 8, 0>;
  _10 = _8 ^ _9;
  _11 = _10 & 64;
  if (_11 != 0)
    goto <bb 7>; [INV]
  else
    goto <bb 8>; [INV]

  <bb 7> :
  abort ();

and with the change we now analyze those and run into

! Disqualifying sK - Address taken in a non-call-argument context.
! Disqualifying x - No or inhibitingly overlapping accesses.


That's because fold somehow transformed one but not the other bitfield
compares.

In particular we have the following two accesses

_8 = BIT_FIELD_REF <x, 8, 0>;
_6 = x.j;

where the first is offset = 0, size = 8 and the second offset = 7, size = 10

and those partially overlap.  Previous to the change SRA was doing a
not profitable change in the end causing it to leave 'x' around.

The interesting difference is in FRE though where without the change we
are able to elide the _6 != _7 compare but with it we fail.  That's because
SRA makes the load of sK.j available - while VN can see through the
x = sK assignment it won't derive a value from the result unless there's
a leader for it in the IL.

Swapping the compare to

  if (sK.j != x.j || x.l != sK.l)
    abort ();

makes it optimized and the abort () call vanishes as well - in fact it
now vanishes already in DOM2, much before RTL optimization.

I don't think the SRA change is to be blamed for doing anything wrong, we're
running into natural limitations of CSE and premature folding inhibiting
SRA (which the SRA change itself was supposed to handle a bit better).

When there's actual wrong-code now on mcore this is a latent problem
uncovered by the change.

The missed-optimization is yet another "dead code elimination regression".

I don't see an easy way to solve the missed-optimization regression.  On the
VN side, when we just see

  x = sK;
  _3 = x.j;
  _4 = sK.j;

then visiting the x.j load, when running into x = SK, could eventually
also put sK.j into the hash table (with the same VARYING value we assign
to x.j).  This would require some extra bookkeeping as we actually compute
this expression already but do not keep it as alternate form to record
when we figure there's no actual leader for it.  Testcase:

struct X { int a; int b; } p, o;
void foo ()
{
  p = o;
  if (p.a != o.a)
    __builtin_abort ();
}

Let me take this for this particular VN issue.

Reply via email to