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

--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> ---
One of the issues is that

REALPART_EXPR <SAVE_EXPR <COMPLEX_EXPR <IMAGPART_EXPR <x>, 0.0>>

is no longer simplified.  I don't think __real folding can look through
a SAVE_EXPR but instead of building SAVE_EXPR <COMPLEX_EXPR <...>> we
could build COMPLEX_EXPR <IMAGPART_EXPR <SAVE_EXPR <x>>, 0.0> here.

I'm not exactly sure why we consider a function parameter (like in
gcc.dg/fold-complex-1.c) as requiring a SAVE_EXPR, we're only resorting to
tree_invariant_p_1 instead of looking at possible side-effects.

For builtins-20.c we FAIL

  if (hypot (tan(-x), tan(-fabs(y))) != hypot (tan(x), tan(y)))
    link_error ();

  if (ccos(tan(x)+sin(x-y)*1i) != ccos(-tan(-x)-sin(y-x)*1i))
    link_error ();

  if (tan(x)+tan(y)*1i != -~(tan(-x)+tan(y)*1i))
    link_error ();

  if (hypotf (tanf(-x), tanf(-fabsf(y))) != hypotf (tanf(x), tanf(y)))
    link_error ();

  if (ccosf(tanf(x)+sinf(x-y)*1i) != ccosf(-tanf(-x)-sinf(y-x)*1i))
    link_error ();

  if (tanf(x)+tanf(y)*1i != -~(tanf(-x)+tanf(y)*1i))
    link_error ();

  if (hypotl (tanl(-x), tanl(-fabsl(y))) != hypotl (tanl(x), tanl(y)))
    link_error ();

  if (ccosl(tanl(x)+sinl(x-y)*1i) != ccosl(-tanl(-x)-sinl(y-x)*1i))
    link_error ();

  if (tanl(x)+tanl(y)*1i != -~(tanl(-x)+tanl(y)*1i))
    link_error ();

for the first we have (in .optimized):

  <bb 2> [local count: 1073741824]:
  _1 = -x_96(D);
  y_115 = y_97(D) * 3.6e+1;
  _32 = tan (y_115);
  _33 = tan (_1);
  _34 = hypot (_33, _32);
  _36 = tan (x_96(D));
  _37 = hypot (_36, _32);
  if (_34 != _37)

in isolation we still optimize this so it's an odd interaction with
surrounding code.  We do observe similar differences with respect
to SAVE_EXPRs compared to GCC 14.

There's a difference after backprop:

   <bb 2> [local count: 1073741824]:
-  _1 = -x_64(D);
+  _1 = -x_96(D);

   <bb 37> [local count: 1073741824]:
-  _32 = tan (y_83);
-  _33 = tan (x_64(D));
+  _32 = tan (y_115);
+  _33 = tan (_1);
   _34 = hypot (_33, _32);
-  _35 = tan (y_83);
-  _36 = tan (x_64(D));
+  _35 = tan (y_115);
+  _36 = tan (x_96(D));
   _37 = hypot (_36, _35);
   if (_34 != _37)

where GCC 14 does

   <bb 37> [local count: 1073741824]:
-  _31 = .COPYSIGN (y_83, -1.0e+0);
-  _32 = tan (_31);
-  _33 = tan (_1);
+  _32 = tan (y_83);
+  _33 = tan (x_64(D));

but patched trunk only

   <bb 37> [local count: 1073741824]:
-  _31 = .COPYSIGN (y_115, -1.0e+0);
-  _32 = tan (_31);
+  _32 = tan (y_115);
   _33 = tan (_1);

and that's because on trunk there's another use of _33 not ignoring sign
which is already folded on the branch:

  <bb 51> [local count: 1073741824]:
  _65 = COMPLEX_EXPR <-0.0, _35>;
  _66 = _52 + _65;
  _67 = COMPLEX_EXPR <_33, 0.0>;
  _68 = _65 + _67;
  _69 = [conj_expr] _68;
  _70 = -_69;
  if (_66 != _70)

that's the

  if (tan(x)+tan(y)*1i != -~(tan(-x)+tan(y)*1i))
    link_error ();

test which only complex lowering can now turn into something optimized,
but we don't get any backprop after that.

There's a missed optimization in backprop in that it doesn't realize
we already compute tan(x) so instead of changing tan(-x) to compute
tan(x) it could have used the result of the existing tan(x) compute.

That's also something VN could do - for hypot (x, y) see if we have
-x and use that, though it requires we simplify -tan(-x) to tan(x).

The simplest way to avoid the regressions seen is to not build a SAVE_EXPR
when arg0 is a COMPLEX_EXPR as we're then for sure folding - OTOH the
GENERIC folding seems premature as complex lowering should deal with this
as well.  Restricting the transform to arg0 being a COMPLEX_EXPR would
solve the issue as well.  Disabling it completely shows we optimize
the pr30172-1.c test even at -O0 during complex lowering.

Reply via email to