Hi! The following testcase takes very long time to compile, because skip_simple_arithmetic decides to first call tree_invariant_p on the second argument (and indirectly recurse there). I think before canonicalization of operands for commutative binary expressions (and for non-commutative ones always) it is pretty common that the first operand is a constant, something which tree_invariant_p handles immediately, so the following patch special cases that; I've added there a tree_invariant_p call too after the checks, while it is not really needed currently, tree_invariant_p has the same checks, I wanted to be prepared in case tree_invariant_p changes. But if you think I should avoid it, I can drop it too.
This is just a partial fix, I think one can certainly construct a testcase which will still have horrible compile time complexity (but I've tried and haven't managed to do so), so perhaps we should just limit the recursion depth through skip_simple_arithmetic/tree_invariant_p with some defaulted argument. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2025-03-11 Jakub Jelinek <ja...@redhat.com> PR c/119183 * tree.cc (skip_simple_arithmetic): If first operand of binary expr is TREE_CONSTANT or TREE_READONLY with no side-effects, call tree_invariant_p on that operand first instead of on the second. * gcc.dg/pr119183.c: New test. --- 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); --- gcc/testsuite/gcc.dg/pr119183.c.jj 2025-03-10 17:48:57.839774108 +0100 +++ gcc/testsuite/gcc.dg/pr119183.c 2025-03-10 17:48:22.960253026 +0100 @@ -0,0 +1,12 @@ +/* PR c/119183 */ +/* { dg-do compile } */ + +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; +} Jakub