From c1e3e2d94487bf594494cbb8cd32aa332124cd33 Mon Sep 17 00:00:00 2001 From: Steven Bosscher Date: Fri, 11 Jan 2008 14:55:34 +0000 Subject: [PATCH] re PR middle-end/30905 (Fails to cross-jump) 2008-01-11 Steven Bosscher PR rtl-optimization/30905 * cfgcleanup.c: Include dce.h (crossjumps_occured): New global variable. (try_crossjump_bb): Exit loop after finding a fallthru edge. If something changed, set crossjumps_occured to true. (try_optimize_cfg): Clear crossjumps_occured at the beginning. Don't add/remove fake edges to exit here... (cleanup_cfg): ...but do it here, when crossjumping. Run a fast DCE when successful crossjumps occured in the latest iteration of try_optimize_cfg. From-SVN: r131468 --- gcc/ChangeLog | 13 +++++++++++ gcc/cfgcleanup.c | 56 +++++++++++++++++++++++++++++++++++++----------- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d9f5e74cfd..a6017c5b481 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2008-01-11 Steven Bosscher + + PR rtl-optimization/30905 + * cfgcleanup.c: Include dce.h + (crossjumps_occured): New global variable. + (try_crossjump_bb): Exit loop after finding a fallthru edge. + If something changed, set crossjumps_occured to true. + (try_optimize_cfg): Clear crossjumps_occured at the beginning. + Don't add/remove fake edges to exit here... + (cleanup_cfg): ...but do it here, when crossjumping. + Run a fast DCE when successful crossjumps occured in the latest + iteration of try_optimize_cfg. + 2008-01-11 Richard Guenther * tree-ssa-sccvn.c (struct vn_binary_op_s): Move hashcode near opcode. diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index b1c94da8489..3ec7d3f3781 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -54,11 +54,16 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "expr.h" #include "df.h" +#include "dce.h" #define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK) /* Set to true when we are running first pass of try_optimize_cfg loop. */ static bool first_pass; + +/* Set to true if crossjumps occured in the latest run of try_optimize_cfg. */ +static bool crossjumps_occured; + static bool try_crossjump_to_edge (int, edge, edge); static bool try_crossjump_bb (int, basic_block); static bool outgoing_edges_match (int, basic_block, basic_block); @@ -1838,7 +1843,10 @@ try_crossjump_bb (int mode, basic_block bb) FOR_EACH_EDGE (e, ei, bb->preds) { if (e->flags & EDGE_FALLTHRU) - fallthru = e; + { + fallthru = e; + break; + } } changed = false; @@ -1847,7 +1855,8 @@ try_crossjump_bb (int mode, basic_block bb) e = EDGE_PRED (ev, ix); ix++; - /* As noted above, first try with the fallthru predecessor. */ + /* As noted above, first try with the fallthru predecessor (or, a + fallthru predecessor if we are in cfglayout mode). */ if (fallthru) { /* Don't combine the fallthru edge into anything else. @@ -1921,6 +1930,9 @@ try_crossjump_bb (int mode, basic_block bb) } } + if (changed) + crossjumps_occured = true; + return changed; } @@ -1935,12 +1947,11 @@ try_optimize_cfg (int mode) int iterations = 0; basic_block bb, b, next; - if (mode & CLEANUP_CROSSJUMP) - add_noreturn_fake_exit_edges (); - if (mode & (CLEANUP_CROSSJUMP | CLEANUP_THREADING)) clear_bb_flags (); + crossjumps_occured = false; + FOR_EACH_BB (bb) update_forwarder_flag (bb); @@ -2131,9 +2142,6 @@ try_optimize_cfg (int mode) while (changed); } - if (mode & CLEANUP_CROSSJUMP) - remove_fake_exit_edges (); - FOR_ALL_BB (b) b->flags &= ~(BB_FORWARDER_BLOCK | BB_NONTHREADABLE_BLOCK); @@ -2235,20 +2243,44 @@ cleanup_cfg (int mode) compact_blocks (); + /* To tail-merge blocks ending in the same noreturn function (e.g. + a call to abort) we have to insert fake edges to exit. Do this + here once. The fake edges do not interfere with any other CFG + cleanups. */ + if (mode & CLEANUP_CROSSJUMP) + add_noreturn_fake_exit_edges (); + while (try_optimize_cfg (mode)) { delete_unreachable_blocks (), changed = true; - if (!(mode & CLEANUP_NO_INSN_DEL) - && (mode & CLEANUP_EXPENSIVE) - && !reload_completed) + if (!(mode & CLEANUP_NO_INSN_DEL)) { - if (!delete_trivially_dead_insns (get_insns (), max_reg_num ())) + /* Try to remove some trivially dead insns when doing an expensive + cleanup. But delete_trivially_dead_insns doesn't work after + reload (it only handles pseudos) and run_fast_dce is too costly + to run in every iteration. + + For effective cross jumping, we really want to run a fast DCE to + clean up any dead conditions, or they get in the way of performing + useful tail merges. + + Other transformations in cleanup_cfg are not so sensitive to dead + code, so delete_trivially_dead_insns or even doing nothing at all + is good enough. */ + if ((mode & CLEANUP_EXPENSIVE) && !reload_completed + && !delete_trivially_dead_insns (get_insns (), max_reg_num ())) break; + else if ((mode & CLEANUP_CROSSJUMP) + && crossjumps_occured) + run_fast_dce (); } else break; } + if (mode & CLEANUP_CROSSJUMP) + remove_fake_exit_edges (); + /* Don't call delete_dead_jumptables in cfglayout mode, because that function assumes that jump tables are in the insns stream. But we also don't _have_ to delete dead jumptables in cfglayout