On February 5, 2019 4:32:29 PM GMT+01:00, Jakub Jelinek <ja...@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 <ja...@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