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.