diff mbox series

Fix RTL DCE (PR target/89188)

Message ID 20190205153229.GT2135@tucnak
State New
Headers show
Series Fix RTL DCE (PR target/89188) | expand

Commit Message

Jakub Jelinek Feb. 5, 2019, 3:32 p.m. UTC
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?

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.


	Jakub

Comments

Richard Biener Feb. 5, 2019, 4:16 p.m. UTC | #1
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
diff mbox series

Patch

--- 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"