https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119183
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Reduced testcase: int foo (void); #define A(x) (1.0f * (1.0f * (1.0f * (1.0f * (1.0f * (1.0f * (1.0f * (1.0f * (x))))))))) float bar (float r) { r += A (A (A (A (A (A (A (A (foo ())))))))); return r; } No options are needed. Given that I think binary expressions with a constant as first argument are fairly common before we actually try to canonicalize expressions, I think a patch like --- gcc/tree.cc.jj 2025-03-08 00:07:01.848908327 +0100 +++ gcc/tree.cc 2025-03-10 17:04:48.630157371 +0100 @@ -4105,7 +4105,12 @@ skip_simple_arithmetic (tree expr) expr = TREE_OPERAND (expr, 0); else if (BINARY_CLASS_P (expr)) { - if (tree_invariant_p (TREE_OPERAND (expr, 1))) + if ((TREE_CONSTANT (TREE_OPERAND (expr, 0)) + || (TREE_READONLY (TREE_OPERAND (expr, 0)) + && !TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))) + && tree_invariant_p (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 1); + else if (tree_invariant_p (TREE_OPERAND (expr, 1))) expr = TREE_OPERAND (expr, 0); else if (tree_invariant_p (TREE_OPERAND (expr, 0))) expr = TREE_OPERAND (expr, 1); could be useful and fixes this testcase. But I'm afraid one can construct different testcases that will still be too expensive, so wonder if there shouldn't be some depth argument passed through tree_invariant_p/skip_simple_arithmetic and simply punt if it is too deep, we don't want to avoid SAVE_EXPRs for too large subexpressions anyway, recomputing them each time will be too expensive. Or instead of depth compute expression size say in number of subtrees and punt when it is larger than some constant.