[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