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

Reply via email to