The reassoc pass currently walks dominators in a recursive way where I ran into a stack overflow with. The following replaces it with worklists following patterns used elsewhere.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. * tree-ssa-reassoc.cc (break_up_subtract_bb): Remove recursion. (reassociate_bb): Likewise. (do_reassoc): Implement worklist based dominator walks for both break_up_subtract_bb and reassociate_bb. --- gcc/tree-ssa-reassoc.cc | 45 +++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc index 70c810c5198..347350fc98d 100644 --- a/gcc/tree-ssa-reassoc.cc +++ b/gcc/tree-ssa-reassoc.cc @@ -6346,7 +6346,6 @@ static void break_up_subtract_bb (basic_block bb) { gimple_stmt_iterator gsi; - basic_block son; unsigned int uid = 1; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -6378,10 +6377,6 @@ break_up_subtract_bb (basic_block bb) && can_reassociate_op_p (gimple_assign_rhs1 (stmt))) plus_negates.safe_push (gimple_assign_lhs (stmt)); } - for (son = first_dom_son (CDI_DOMINATORS, bb); - son; - son = next_dom_son (CDI_DOMINATORS, son)) - break_up_subtract_bb (son); } /* Used for repeated factor analysis. */ @@ -7007,7 +7002,6 @@ static bool reassociate_bb (basic_block bb) { gimple_stmt_iterator gsi; - basic_block son; gimple *stmt = last_nondebug_stmt (bb); bool cfg_cleanup_needed = false; @@ -7270,10 +7264,6 @@ reassociate_bb (basic_block bb) } } } - for (son = first_dom_son (CDI_POST_DOMINATORS, bb); - son; - son = next_dom_son (CDI_POST_DOMINATORS, son)) - cfg_cleanup_needed |= reassociate_bb (son); return cfg_cleanup_needed; } @@ -7382,10 +7372,39 @@ debug_ops_vector (vec<operand_entry *> ops) /* Bubble up return status from reassociate_bb. */ static bool -do_reassoc (void) +do_reassoc () { - break_up_subtract_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun)); - return reassociate_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)); + bool cfg_cleanup_needed = false; + basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun)); + + unsigned sp = 0; + for (auto son = first_dom_son (CDI_DOMINATORS, ENTRY_BLOCK_PTR_FOR_FN (cfun)); + son; son = next_dom_son (CDI_DOMINATORS, son)) + worklist[sp++] = son; + while (sp) + { + basic_block bb = worklist[--sp]; + break_up_subtract_bb (bb); + for (auto son = first_dom_son (CDI_DOMINATORS, bb); + son; son = next_dom_son (CDI_DOMINATORS, son)) + worklist[sp++] = son; + } + + for (auto son = first_dom_son (CDI_POST_DOMINATORS, + EXIT_BLOCK_PTR_FOR_FN (cfun)); + son; son = next_dom_son (CDI_POST_DOMINATORS, son)) + worklist[sp++] = son; + while (sp) + { + basic_block bb = worklist[--sp]; + cfg_cleanup_needed |= reassociate_bb (bb); + for (auto son = first_dom_son (CDI_POST_DOMINATORS, bb); + son; son = next_dom_son (CDI_POST_DOMINATORS, son)) + worklist[sp++] = son; + } + + free (worklist); + return cfg_cleanup_needed; } /* Initialize the reassociation pass. */ -- 2.43.0