Message ID | 20190205153229.GT2135@tucnak |
---|---|
State | New |
Headers | show |
Series | Fix RTL DCE (PR target/89188) | expand |
On February 5, 2019 4:32:29 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote: >Hi! > >RTL DCE is called in different modes, sometimes it is allowed to alter >cfg, >in other cases it is not. The following testcase ICEs because when it >is >not allowed to alter cfg (combiner's df_analyze) we remove a noop move >that >was considered to potentially throw and that made a bb unreachable >(which >the pass didn't like), but even removing those unreachable bbs would >ICE >anyway, as the algorithm is for !can_alter_cfg not really prepared to >see >bbs and edges being removed. > >So, the following patch does 3 things: >1) doesn't delete noop moves if they can > throw and we can't alter cfg or delete dead exceptions >2) instead of setting must_clean blindly for any CALL_INSNs, it instead > sets it accurately from delete_insn_and_edges return value >3) it asserts that if !can_alter_cfg we don't actually have must_clean >set > >Bootstrapped/regtested on powerpc64{,le}-linux, ok for trunk? OK. Richard. >2019-02-05 Jakub Jelinek <jakub@redhat.com> > > PR target/89188 > * dce.c (delete_unmarked_insns): Don't remove no-op moves if they > can throw, non-call exceptions are enabled and we can't delete > dead exceptions or alter cfg. Set must_clean if > delete_insn_and_edges returns true, don't set it blindly for calls. > Assert that delete_unreachable_blocks is called only if can_alter_cfg. > > * g++.dg/opt/pr89188.C: New test. > >--- gcc/dce.c.jj 2019-02-05 10:04:16.984062429 +0100 >+++ gcc/dce.c 2019-02-05 10:53:47.655584503 +0100 >@@ -584,7 +584,12 @@ delete_unmarked_insns (void) > rtx turn_into_use = NULL_RTX; > > /* Always delete no-op moves. */ >- if (noop_move_p (insn)) >+ if (noop_move_p (insn) >+ /* Unless the no-op move can throw and we are not allowed >+ to alter cfg. */ >+ && (!cfun->can_throw_non_call_exceptions >+ || (cfun->can_delete_dead_exceptions && can_alter_cfg) >+ || insn_nothrow_p (insn))) > { > if (RTX_FRAME_RELATED_P (insn)) > turn_into_use >@@ -627,12 +632,6 @@ delete_unmarked_insns (void) > for the destination regs in order to avoid dangling notes. */ > remove_reg_equal_equiv_notes_for_defs (insn); > >- /* If a pure or const call is deleted, this may make the cfg >- have unreachable blocks. We rememeber this and call >- delete_unreachable_blocks at the end. */ >- if (CALL_P (insn)) >- must_clean = true; >- > if (turn_into_use) > { > /* Don't remove frame related noop moves if they cary >@@ -645,12 +644,15 @@ delete_unmarked_insns (void) > } > else > /* Now delete the insn. */ >- delete_insn_and_edges (insn); >+ must_clean |= delete_insn_and_edges (insn); > } > > /* Deleted a pure or const call. */ > if (must_clean) >- delete_unreachable_blocks (); >+ { >+ gcc_assert (can_alter_cfg); >+ delete_unreachable_blocks (); >+ } > } > > >--- gcc/testsuite/g++.dg/opt/pr89188.C.jj 2019-02-04 14:20:57.714851393 >+0100 >+++ gcc/testsuite/g++.dg/opt/pr89188.C 2019-02-04 14:52:09.988782531 >+0100 >@@ -0,0 +1,5 @@ >+// PR target/89188 >+// { dg-do compile { target c++11 } } >+// { dg-options "-Og -flive-range-shrinkage -fnon-call-exceptions" } >+ >+#include "../torture/pr88861.C" > > Jakub
--- gcc/dce.c.jj 2019-02-05 10:04:16.984062429 +0100 +++ gcc/dce.c 2019-02-05 10:53:47.655584503 +0100 @@ -584,7 +584,12 @@ delete_unmarked_insns (void) rtx turn_into_use = NULL_RTX; /* Always delete no-op moves. */ - if (noop_move_p (insn)) + if (noop_move_p (insn) + /* Unless the no-op move can throw and we are not allowed + to alter cfg. */ + && (!cfun->can_throw_non_call_exceptions + || (cfun->can_delete_dead_exceptions && can_alter_cfg) + || insn_nothrow_p (insn))) { if (RTX_FRAME_RELATED_P (insn)) turn_into_use @@ -627,12 +632,6 @@ delete_unmarked_insns (void) for the destination regs in order to avoid dangling notes. */ remove_reg_equal_equiv_notes_for_defs (insn); - /* If a pure or const call is deleted, this may make the cfg - have unreachable blocks. We rememeber this and call - delete_unreachable_blocks at the end. */ - if (CALL_P (insn)) - must_clean = true; - if (turn_into_use) { /* Don't remove frame related noop moves if they cary @@ -645,12 +644,15 @@ delete_unmarked_insns (void) } else /* Now delete the insn. */ - delete_insn_and_edges (insn); + must_clean |= delete_insn_and_edges (insn); } /* Deleted a pure or const call. */ if (must_clean) - delete_unreachable_blocks (); + { + gcc_assert (can_alter_cfg); + delete_unreachable_blocks (); + } } --- gcc/testsuite/g++.dg/opt/pr89188.C.jj 2019-02-04 14:20:57.714851393 +0100 +++ gcc/testsuite/g++.dg/opt/pr89188.C 2019-02-04 14:52:09.988782531 +0100 @@ -0,0 +1,5 @@ +// PR target/89188 +// { dg-do compile { target c++11 } } +// { dg-options "-Og -flive-range-shrinkage -fnon-call-exceptions" } + +#include "../torture/pr88861.C"