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  <ja...@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.

--- 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);
+}

        Jakub

Reply via email to