aboutsummaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2019-01-16 20:13:23 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2019-01-16 20:13:23 +0000
commit15b93db9ca258710e3abb43e2378ef3601e3a697 (patch)
tree843768dfbe9461304aa053363cc987e1a4fe8b18 /gcc/combine.c
parent33b5a38c2dc961e9dd3e28ffd535d81c40d2b7bb (diff)
downloadgcc-15b93db9ca258710e3abb43e2378ef3601e3a697.zip
gcc-15b93db9ca258710e3abb43e2378ef3601e3a697.tar.gz
gcc-15b93db9ca258710e3abb43e2378ef3601e3a697.tar.bz2
Fix ICE due to "combine" creating unreachable EH blocks (PR target/88861)
PR target/88861 reports an ICE in "ce2" due to an unreachable basic block. The block becomes unreachable in "combine" when delete_noop_moves deletes an insn with a REG_EH_REGION, deleting the EH edge, the only edge leading to the basic block. Normally, rest_of_handle_combine would call cleanup_cfg, deleting unreachable blocks, if combine_instructions returns true, and combine_instructions does return true for some cases of edge-removal, but it doesn't for this case, leading to the ICE. This patch updates delete_noop_moves so that it returns true if it deletes any edges, and passes that through to combine_instructions, so that it too will return true if any edges were deleted, ensuring that cleanup_cfg will be called by rest_of_handle_combine for this case, deleting the now-unreachable block, and fixing the ICE. gcc/ChangeLog: PR target/88861 * combine.c (delete_noop_moves): Convert to "bool" return, returning true if any edges are eliminated. (combine_instructions): Also return true if delete_noop_moves returns true. gcc/testsuite/ChangeLog: PR target/88861 * g++.dg/torture/pr88861.C: New test. From-SVN: r267984
Diffstat (limited to 'gcc/combine.c')
-rw-r--r--gcc/combine.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index e226c7dd..c108f65 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -983,14 +983,17 @@ combine_validate_cost (rtx_insn *i0, rtx_insn *i1, rtx_insn *i2, rtx_insn *i3,
}
-/* Delete any insns that copy a register to itself. */
+/* Delete any insns that copy a register to itself.
+ Return true if the CFG was changed. */
-static void
+static bool
delete_noop_moves (void)
{
rtx_insn *insn, *next;
basic_block bb;
+ bool edges_deleted = false;
+
FOR_EACH_BB_FN (bb, cfun)
{
for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb)); insn = next)
@@ -1001,10 +1004,12 @@ delete_noop_moves (void)
if (dump_file)
fprintf (dump_file, "deleting noop move %d\n", INSN_UID (insn));
- delete_insn_and_edges (insn);
+ edges_deleted |= delete_insn_and_edges (insn);
}
}
}
+
+ return edges_deleted;
}
@@ -1143,8 +1148,8 @@ insn_a_feeds_b (rtx_insn *a, rtx_insn *b)
/* Main entry point for combiner. F is the first insn of the function.
NREGS is the first unused pseudo-reg number.
- Return nonzero if the combiner has turned an indirect jump
- instruction into a direct jump. */
+ Return nonzero if the CFG was changed (e.g. if the combiner has
+ turned an indirect jump instruction into a direct jump). */
static int
combine_instructions (rtx_insn *f, unsigned int nregs)
{
@@ -1529,7 +1534,7 @@ retry:
default_rtl_profile ();
clear_bb_flags ();
new_direct_jump_p |= purge_all_dead_edges ();
- delete_noop_moves ();
+ new_direct_jump_p |= delete_noop_moves ();
/* Clean up. */
obstack_free (&insn_link_obstack, NULL);