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.