[Bug debug/59575] [4.9 regression] ICE in maybe_record_trace_start, at dwarf2cfi.c:2239

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Jan 29 14:36:00 GMT 2014


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59575

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #31943|0                           |1
        is obsolete|                            |

--- Comment #26 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Comment on attachment 31943
  --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=31943
gcc49-pr59575.patch

>2014-01-23  Jakub Jelinek  <jakub@redhat.com>
>
>	PR target/59575
>	* config/arm/arm.c (emit_multi_reg_push): Add dwarf_regs_mask argument,
>	don't record in REG_FRAME_RELATED_EXPR registers not set in that
>	bitmask.
>	(arm_expand_prologue): Adjust all callers.
>	(arm_unwind_emit_sequence): Allow saved, but not important for unwind
>	info, registers also at the lowest numbered registers side.  Use
>	gcc_assert instead of abort, and SET_SRC/SET_DEST macros instead of
>	XEXP.
>
>	* gcc.target/arm/pr59575.c: New test.
>
>--- gcc/config/arm/arm.c.jj	2014-01-17 15:16:14.000000000 +0100
>+++ gcc/config/arm/arm.c	2014-01-24 09:16:41.949843665 +0100
>@@ -177,7 +177,7 @@ static rtx arm_expand_builtin (tree, rtx
> static tree arm_builtin_decl (unsigned, bool);
> static void emit_constant_insn (rtx cond, rtx pattern);
> static rtx emit_set_insn (rtx, rtx);
>-static rtx emit_multi_reg_push (unsigned long);
>+static rtx emit_multi_reg_push (unsigned long, unsigned long);
> static int arm_arg_partial_bytes (cumulative_args_t, enum machine_mode,
> 				  tree, bool);
> static rtx arm_function_arg (cumulative_args_t, enum machine_mode,
>@@ -19574,9 +19574,11 @@ arm_emit_strd_push (unsigned long saved_
> /* Generate and emit an insn that we will recognize as a push_multi.
>    Unfortunately, since this insn does not reflect very well the actual
>    semantics of the operation, we need to annotate the insn for the benefit
>-   of DWARF2 frame unwind information.  */
>+   of DWARF2 frame unwind information.  DWARF_REGS_MASK is a subset of
>+   MASK for registers that should be annotated for DWARF2 frame unwind
>+   information.  */
> static rtx
>-emit_multi_reg_push (unsigned long mask)
>+emit_multi_reg_push (unsigned long mask, unsigned long dwarf_regs_mask)
> {
>   int num_regs = 0;
>   int num_dwarf_regs;
>@@ -19586,16 +19588,19 @@ emit_multi_reg_push (unsigned long mask)
>   int dwarf_par_index;
>   rtx tmp, reg;
> 
>+  /* We don't record the PC in the dwarf frame information.  */
>+  dwarf_regs_mask &= ~(1 << PC_REGNUM);
>+
>   for (i = 0; i <= LAST_ARM_REGNUM; i++)
>-    if (mask & (1 << i))
>-      num_regs++;
>+    {
>+      if (mask & (1 << i))
>+	num_regs++;
>+      if (dwarf_regs_mask & (1 << i))
>+	num_dwarf_regs++;
>+    }
> 
>   gcc_assert (num_regs && num_regs <= 16);
>-
>-  /* We don't record the PC in the dwarf frame information.  */
>-  num_dwarf_regs = num_regs;
>-  if (mask & (1 << PC_REGNUM))
>-    num_dwarf_regs--;
>+  gcc_assert ((dwarf_regs_mask & ~mask) == 0);
> 
>   /* For the body of the insn we are going to generate an UNSPEC in
>      parallel with several USEs.  This allows the insn to be recognized
>@@ -19661,14 +19666,13 @@ emit_multi_reg_push (unsigned long mask)
> 					   gen_rtvec (1, reg),
> 					   UNSPEC_PUSH_MULT));
> 
>-	  if (i != PC_REGNUM)
>+	  if (dwarf_regs_mask & (1 << i))
> 	    {
> 	      tmp = gen_rtx_SET (VOIDmode,
> 				 gen_frame_mem (SImode, stack_pointer_rtx),
> 				 reg);
> 	      RTX_FRAME_RELATED_P (tmp) = 1;
>-	      XVECEXP (dwarf, 0, dwarf_par_index) = tmp;
>-	      dwarf_par_index++;
>+	      XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
> 	    }
> 
> 	  break;
>@@ -19683,7 +19687,7 @@ emit_multi_reg_push (unsigned long mask)
> 
> 	  XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
> 
>-	  if (i != PC_REGNUM)
>+	  if (dwarf_regs_mask & (1 << i))
> 	    {
> 	      tmp
> 		= gen_rtx_SET (VOIDmode,
>@@ -20690,7 +20694,7 @@ arm_expand_prologue (void)
> 	  /* Interrupt functions must not corrupt any registers.
> 	     Creating a frame pointer however, corrupts the IP
> 	     register, so we must push it first.  */
>-	  emit_multi_reg_push (1 << IP_REGNUM);
>+	  emit_multi_reg_push (1 << IP_REGNUM, 1 << IP_REGNUM);
> 
> 	  /* Do not set RTX_FRAME_RELATED_P on this insn.
> 	     The dwarf stack unwinding code only wants to see one
>@@ -20751,7 +20755,8 @@ arm_expand_prologue (void)
> 	      if (cfun->machine->uses_anonymous_args)
> 		{
> 		  insn
>-		    = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf);
>+		    = emit_multi_reg_push ((0xf0 >> (args_to_push / 4)) & 0xf,
>+					   (0xf0 >> (args_to_push / 4)) & 0xf);
> 		  emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
> 		  saved_pretend_args = 1;
> 		}
>@@ -20795,7 +20800,8 @@ arm_expand_prologue (void)
>       /* Push the argument registers, or reserve space for them.  */
>       if (cfun->machine->uses_anonymous_args)
> 	insn = emit_multi_reg_push
>-	  ((0xf0 >> (args_to_push / 4)) & 0xf);
>+	  ((0xf0 >> (args_to_push / 4)) & 0xf,
>+	   (0xf0 >> (args_to_push / 4)) & 0xf);
>       else
> 	insn = emit_insn
> 	  (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
>@@ -20820,6 +20826,8 @@ arm_expand_prologue (void)
> 
>   if (live_regs_mask)
>     {
>+      unsigned long dwarf_regs_mask = live_regs_mask;
>+
>       saved_regs += bit_count (live_regs_mask) * 4;
>       if (optimize_size && !frame_pointer_needed
> 	  && saved_regs == offsets->saved_regs - offsets->saved_args)
>@@ -20846,25 +20854,22 @@ arm_expand_prologue (void)
> 	  && current_tune->prefer_ldrd_strd
>           && !optimize_function_for_size_p (cfun))
>         {
>+	  gcc_checking_assert (live_regs_mask == dwarf_regs_mask);
>           if (TARGET_THUMB2)
>-            {
>-              thumb2_emit_strd_push (live_regs_mask);
>-            }
>+	    thumb2_emit_strd_push (live_regs_mask);
>           else if (TARGET_ARM
>                    && !TARGET_APCS_FRAME
>                    && !IS_INTERRUPT (func_type))
>-            {
>-              arm_emit_strd_push (live_regs_mask);
>-            }
>+	    arm_emit_strd_push (live_regs_mask);
>           else
>             {
>-              insn = emit_multi_reg_push (live_regs_mask);
>+	      insn = emit_multi_reg_push (live_regs_mask, live_regs_mask);
>               RTX_FRAME_RELATED_P (insn) = 1;
>             }
>         }
>       else
>         {
>-          insn = emit_multi_reg_push (live_regs_mask);
>+	  insn = emit_multi_reg_push (live_regs_mask, dwarf_regs_mask);
>           RTX_FRAME_RELATED_P (insn) = 1;
>         }
>     }
>@@ -28692,32 +28697,43 @@ arm_unwind_emit_sequence (FILE * asm_out
>   int reg_size;
>   unsigned reg;
>   unsigned lastreg;
>+  unsigned padfirst = 0, padlast = 0;
>   rtx e;
> 
>   e = XVECEXP (p, 0, 0);
>-  if (GET_CODE (e) != SET)
>-    abort ();
>+  gcc_assert (GET_CODE (e) == SET);
> 
>   /* First insn will adjust the stack pointer.  */
>-  if (GET_CODE (e) != SET
>-      || !REG_P (XEXP (e, 0))
>-      || REGNO (XEXP (e, 0)) != SP_REGNUM
>-      || GET_CODE (XEXP (e, 1)) != PLUS)
>-    abort ();
>+  gcc_assert (GET_CODE (e) == SET
>+	      && REG_P (SET_DEST (e))
>+	      && REGNO (SET_DEST (e)) == SP_REGNUM
>+	      && GET_CODE (SET_SRC (e)) == PLUS);
> 
>-  offset = -INTVAL (XEXP (XEXP (e, 1), 1));
>+  offset = -INTVAL (XEXP (SET_SRC (e), 1));
>   nregs = XVECLEN (p, 0) - 1;
>+  gcc_assert (nregs);
> 
>-  reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1));
>+  reg = REGNO (SET_SRC (XVECEXP (p, 0, 1)));
>   if (reg < 16)
>     {
>+      /* For -Os dummy registers can be pushed at the beginning to
>+	 avoid separate stack pointer adjustment.  */
>+      e = XVECEXP (p, 0, 1);
>+      e = XEXP (SET_DEST (e), 0);
>+      if (GET_CODE (e) == PLUS)
>+	padfirst = INTVAL (XEXP (e, 1));
>+      gcc_assert (padfirst == 0 || optimize_size);
>       /* The function prologue may also push pc, but not annotate it as it is
> 	 never restored.  We turn this into a stack pointer adjustment.  */
>-      if (nregs * 4 == offset - 4)
>-	{
>-	  fprintf (asm_out_file, "\t.pad #4\n");
>-	  offset -= 4;
>-	}
>+      e = XVECEXP (p, 0, nregs);
>+      e = XEXP (SET_DEST (e), 0);
>+      if (GET_CODE (e) == PLUS)
>+	padlast = offset - INTVAL (XEXP (e, 1)) - 4;
>+      else
>+	padlast = offset - 4;
>+      gcc_assert (padlast == 0 || padlast == 4);
>+      if (padlast == 4)
>+	fprintf (asm_out_file, "\t.pad #4\n");
>       reg_size = 4;
>       fprintf (asm_out_file, "\t.save {");
>     }
>@@ -28728,14 +28744,13 @@ arm_unwind_emit_sequence (FILE * asm_out
>     }
>   else
>     /* Unknown register type.  */
>-    abort ();
>+    gcc_unreachable ();
> 
>   /* If the stack increment doesn't match the size of the saved registers,
>      something has gone horribly wrong.  */
>-  if (offset != nregs * reg_size)
>-    abort ();
>+  gcc_assert (offset == padfirst + nregs * reg_size + padlast);
> 
>-  offset = 0;
>+  offset = padfirst;
>   lastreg = 0;
>   /* The remaining insns will describe the stores.  */
>   for (i = 1; i <= nregs; i++)
>@@ -28743,14 +28758,12 @@ arm_unwind_emit_sequence (FILE * asm_out
>       /* Expect (set (mem <addr>) (reg)).
>          Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)).  */
>       e = XVECEXP (p, 0, i);
>-      if (GET_CODE (e) != SET
>-	  || !MEM_P (XEXP (e, 0))
>-	  || !REG_P (XEXP (e, 1)))
>-	abort ();
>-
>-      reg = REGNO (XEXP (e, 1));
>-      if (reg < lastreg)
>-	abort ();
>+      gcc_assert (GET_CODE (e) == SET
>+		  && MEM_P (SET_DEST (e))
>+		  && REG_P (SET_SRC (e)));
>+
>+      reg = REGNO (SET_SRC (e));
>+      gcc_assert (reg >= lastreg);
> 
>       if (i != 1)
> 	fprintf (asm_out_file, ", ");
>@@ -28763,23 +28776,22 @@ arm_unwind_emit_sequence (FILE * asm_out
> 
> #ifdef ENABLE_CHECKING
>       /* Check that the addresses are consecutive.  */
>-      e = XEXP (XEXP (e, 0), 0);
>+      e = XEXP (SET_DEST (e), 0);
>       if (GET_CODE (e) == PLUS)
>-	{
>-	  offset += reg_size;
>-	  if (!REG_P (XEXP (e, 0))
>-	      || REGNO (XEXP (e, 0)) != SP_REGNUM
>-	      || !CONST_INT_P (XEXP (e, 1))
>-	      || offset != INTVAL (XEXP (e, 1)))
>-	    abort ();
>-	}
>-      else if (i != 1
>-	       || !REG_P (e)
>-	       || REGNO (e) != SP_REGNUM)
>-	abort ();
>+	gcc_assert (REG_P (XEXP (e, 0))
>+		    && REGNO (XEXP (e, 0)) == SP_REGNUM
>+		    && CONST_INT_P (XEXP (e, 1))
>+		    && offset == INTVAL (XEXP (e, 1)));
>+      else
>+	gcc_assert (i == 1
>+		    && REG_P (e)
>+		    && REGNO (e) == SP_REGNUM);
>+      offset += reg_size;
> #endif
>     }
>   fprintf (asm_out_file, "}\n");
>+  if (padfirst)
>+    fprintf (asm_out_file, "\t.pad #%d\n", padfirst);
> }
> 
> /*  Emit unwind directives for a SET.  */
>--- gcc/testsuite/gcc.target/arm/pr59575.c.jj	2014-01-23 15:54:25.959922593 +0100
>+++ gcc/testsuite/gcc.target/arm/pr59575.c	2014-01-23 15:54:12.000000000 +0100
>@@ -0,0 +1,15 @@
>+/* PR target/59575 */
>+/* { dg-do compile } */
>+/* { dg-options "-Os -g -march=armv7-a" } */
>+
>+void foo (int *);
>+int *bar (int, long long, int);
>+
>+void
>+test (int *p)
>+{
>+  if (p)
>+    foo (p);
>+  else if (p = bar (0, 1, 2))
>+    foo (p);
>+}


More information about the Gcc-bugs mailing list