diff mbox series

Don't RTL DCE REG_CFA_RESTORE noop moves (PR debug/84875)

Message ID 20180315192013.GV8577@tucnak
State New
Headers show
Series Don't RTL DCE REG_CFA_RESTORE noop moves (PR debug/84875) | expand

Commit Message

Jakub Jelinek March 15, 2018, 7:20 p.m. UTC
Hi!

The following testcase ICEs on s390x-linux, because we have 2 registers
saved in prologue, but only one of them modified in one path and then
both restored there; cprop_hardreg propagates the saving register into the
REG_CFA_RESTORE insn, making it a noop move (we don't really need to restore
it), and then RTL DCE removes the noop move and we ICE during dwarf2 pass,
because of a CFI mismatch.

The following patch makes sure that such insns are not actually removed, but
turned into a USE still holding the note, which is all we need for CFI.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-03-15  Jakub Jelinek  <jakub@redhat.com>

	PR debug/84875
	* dce.c (delete_unmarked_insns): Don't remove frame related noop moves
	holding REG_CFA_RESTORE notes, instead turn them into a USE.

	* gcc.dg/pr84875.c: New test.


	Jakub

Comments

Jeff Law March 20, 2018, 8:43 p.m. UTC | #1
On 03/15/2018 01:20 PM, Jakub Jelinek wrote:
> Hi!
> 
> The following testcase ICEs on s390x-linux, because we have 2 registers
> saved in prologue, but only one of them modified in one path and then
> both restored there; cprop_hardreg propagates the saving register into the
> REG_CFA_RESTORE insn, making it a noop move (we don't really need to restore
> it), and then RTL DCE removes the noop move and we ICE during dwarf2 pass,
> because of a CFI mismatch.
> 
> The following patch makes sure that such insns are not actually removed, but
> turned into a USE still holding the note, which is all we need for CFI.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2018-03-15  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR debug/84875
> 	* dce.c (delete_unmarked_insns): Don't remove frame related noop moves
> 	holding REG_CFA_RESTORE notes, instead turn them into a USE.
> 
> 	* gcc.dg/pr84875.c: New test.
OK.
jeff
diff mbox series

Patch

--- gcc/dce.c.jj	2018-01-26 12:47:34.255931988 +0100
+++ gcc/dce.c	2018-03-15 14:23:11.553002165 +0100
@@ -569,9 +569,19 @@  delete_unmarked_insns (void)
     FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
       if (NONDEBUG_INSN_P (insn))
 	{
+	  rtx turn_into_use = NULL_RTX;
+
 	  /* Always delete no-op moves.  */
 	  if (noop_move_p (insn))
-	    ;
+	    {
+	      if (RTX_FRAME_RELATED_P (insn))
+		turn_into_use
+		  = find_reg_note (insn, REG_CFA_RESTORE, NULL);
+	      if (turn_into_use && REG_P (XEXP (turn_into_use, 0)))
+		turn_into_use = XEXP (turn_into_use, 0);
+	      else
+		turn_into_use = NULL_RTX;
+	    }
 
 	  /* Otherwise rely only on the DCE algorithm.  */
 	  else if (marked_insn_p (insn))
@@ -611,8 +621,19 @@  delete_unmarked_insns (void)
 	  if (CALL_P (insn))
 	    must_clean = true;
 
-	  /* Now delete the insn.  */
-	  delete_insn_and_edges (insn);
+	  if (turn_into_use)
+	    {
+	      /* Don't remove frame related noop moves if they cary
+		 REG_CFA_RESTORE note, while we don't need to emit any code,
+		 we need it to emit the CFI restore note.  */
+	      PATTERN (insn)
+		= gen_rtx_USE (GET_MODE (turn_into_use), turn_into_use);
+	      INSN_CODE (insn) = -1;
+	      df_insn_rescan (insn);
+	    }
+	  else
+	    /* Now delete the insn.  */
+	    delete_insn_and_edges (insn);
 	}
 
   /* Deleted a pure or const call.  */
--- gcc/testsuite/gcc.dg/pr84875.c.jj	2018-03-15 14:28:02.811159065 +0100
+++ gcc/testsuite/gcc.dg/pr84875.c	2018-03-15 14:27:35.473144347 +0100
@@ -0,0 +1,28 @@ 
+/* PR debug/84875 */
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+/* { dg-additional-options "-fpie" { target pie } } */
+/* { dg-additional-options "-march=z196" { target s390*-*-* } } */
+
+static long *a[100];
+static int b[100];
+long *c;
+int d;
+void foo (long *);
+
+void
+bar ()
+{
+  long *g = c;
+  g--;
+  d = *g;
+  if (d)
+    if (b[d] < 8)
+      {
+	*(void **)g = a[d];
+	a[d] = g;
+	b[d]++;
+	return;
+      }
+  foo (g);
+}