aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Bosscher <stevenb.gcc@gmail.com>2008-01-11 14:55:34 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-01-11 14:55:34 +0000
commitc1e3e2d94487bf594494cbb8cd32aa332124cd33 (patch)
treeaf89a1d1e50ecbea2a77cdf1f64808b1fdd0dd05
parent8d0eca24faee76ac0ebc169695e4a79f390a5316 (diff)
downloadgcc-c1e3e2d94487bf594494cbb8cd32aa332124cd33.zip
gcc-c1e3e2d94487bf594494cbb8cd32aa332124cd33.tar.gz
gcc-c1e3e2d94487bf594494cbb8cd32aa332124cd33.tar.bz2
re PR middle-end/30905 (Fails to cross-jump)
2008-01-11 Steven Bosscher <stevenb.gcc@gmail.com> 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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/cfgcleanup.c56
2 files changed, 57 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7d9f5e7..a6017c5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2008-01-11 Steven Bosscher <stevenb.gcc@gmail.com>
+
+ 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 <rguenther@suse.de>
* tree-ssa-sccvn.c (struct vn_binary_op_s): Move hashcode near opcode.
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index b1c94da..3ec7d3f 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