Commit 42aa5124 by Richard Henderson Committed by Richard Henderson

re PR debug/50132 (ICE: in maybe_record_trace_start, at dwarf2cfi.c:2234 with…

re PR debug/50132 (ICE: in maybe_record_trace_start, at dwarf2cfi.c:2234 with -fno-asynchronous-unwind-tables and long double)

PR 50132
PR 49864
        * cfgcleanup.c (old_insns_match_p): Don't allow cross-jump for
        non-constant stack adjutment.
        * expr.c (find_args_size_adjust): Break out from ...
        (fixup_args_size_notes): ... here.
        * rtl.h (find_args_size_adjust): Declare.

From-SVN: r178084
parent 0ab71f30
2011-08-25 Richard Henderson <rth@redhat.com>
PR 50132
PR 49864
* cfgcleanup.c (old_insns_match_p): Don't allow cross-jump for
non-constant stack adjutment.
* expr.c (find_args_size_adjust): Break out from ...
(fixup_args_size_notes): ... here.
* rtl.h (find_args_size_adjust): Declare.
2011-08-25 Uros Bizjak <ubizjak@gmail.com> 2011-08-25 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (isa): Add sse2, sse2_noavx, sse3, * config/i386/i386.md (isa): Add sse2, sse2_noavx, sse3,
......
...@@ -1081,13 +1081,22 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2) ...@@ -1081,13 +1081,22 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2)
/* ??? Do not allow cross-jumping between different stack levels. */ /* ??? Do not allow cross-jumping between different stack levels. */
p1 = find_reg_note (i1, REG_ARGS_SIZE, NULL); p1 = find_reg_note (i1, REG_ARGS_SIZE, NULL);
p2 = find_reg_note (i2, REG_ARGS_SIZE, NULL); p2 = find_reg_note (i2, REG_ARGS_SIZE, NULL);
if (p1) if (p1 && p2)
{
p1 = XEXP (p1, 0); p1 = XEXP (p1, 0);
if (p2)
p2 = XEXP (p2, 0); p2 = XEXP (p2, 0);
if (!rtx_equal_p (p1, p2)) if (!rtx_equal_p (p1, p2))
return dir_none; return dir_none;
/* ??? Worse, this adjustment had better be constant lest we
have differing incoming stack levels. */
if (!frame_pointer_needed
&& find_args_size_adjust (i1) == HOST_WIDE_INT_MIN)
return dir_none;
}
else if (p1 || p2)
return dir_none;
p1 = PATTERN (i1); p1 = PATTERN (i1);
p2 = PATTERN (i2); p2 = PATTERN (i2);
......
...@@ -3548,21 +3548,12 @@ mem_autoinc_base (rtx mem) ...@@ -3548,21 +3548,12 @@ mem_autoinc_base (rtx mem)
verified, via immediate operand or auto-inc. If the adjustment verified, via immediate operand or auto-inc. If the adjustment
cannot be trivially extracted, the return value is INT_MIN. */ cannot be trivially extracted, the return value is INT_MIN. */
int HOST_WIDE_INT
fixup_args_size_notes (rtx prev, rtx last, int end_args_size) find_args_size_adjust (rtx insn)
{ {
int args_size = end_args_size;
bool saw_unknown = false;
rtx insn;
for (insn = last; insn != prev; insn = PREV_INSN (insn))
{
rtx dest, set, pat; rtx dest, set, pat;
HOST_WIDE_INT this_delta = 0;
int i; int i;
if (!NONDEBUG_INSN_P (insn))
continue;
pat = PATTERN (insn); pat = PATTERN (insn);
set = NULL; set = NULL;
...@@ -3572,7 +3563,7 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size) ...@@ -3572,7 +3563,7 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
/* We have to allow non-call_pop patterns for the case /* We have to allow non-call_pop patterns for the case
of emit_single_push_insn of a TLS address. */ of emit_single_push_insn of a TLS address. */
if (GET_CODE (pat) != PARALLEL) if (GET_CODE (pat) != PARALLEL)
continue; return 0;
/* All call_pop have a stack pointer adjust in the parallel. /* All call_pop have a stack pointer adjust in the parallel.
The call itself is always first, and the stack adjust is The call itself is always first, and the stack adjust is
...@@ -3588,7 +3579,7 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size) ...@@ -3588,7 +3579,7 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
} }
/* We'd better have found the stack pointer adjust. */ /* We'd better have found the stack pointer adjust. */
if (i == 0) if (i == 0)
continue; return 0;
/* Fall through to process the extracted SET and DEST /* Fall through to process the extracted SET and DEST
as if it was a standalone insn. */ as if it was a standalone insn. */
} }
...@@ -3612,22 +3603,21 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size) ...@@ -3612,22 +3603,21 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
break; break;
/* We do not expect an auto-inc of the sp in the parallel. */ /* We do not expect an auto-inc of the sp in the parallel. */
gcc_checking_assert (mem_autoinc_base (dest) gcc_checking_assert (mem_autoinc_base (dest) != stack_pointer_rtx);
!= stack_pointer_rtx);
gcc_checking_assert (mem_autoinc_base (SET_SRC (set)) gcc_checking_assert (mem_autoinc_base (SET_SRC (set))
!= stack_pointer_rtx); != stack_pointer_rtx);
} }
if (i < 0) if (i < 0)
continue; return 0;
} }
else else
continue; return 0;
dest = SET_DEST (set); dest = SET_DEST (set);
/* Look for direct modifications of the stack pointer. */ /* Look for direct modifications of the stack pointer. */
if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM) if (REG_P (dest) && REGNO (dest) == STACK_POINTER_REGNUM)
{ {
gcc_assert (!saw_unknown);
/* Look for a trivial adjustment, otherwise assume nothing. */ /* Look for a trivial adjustment, otherwise assume nothing. */
/* Note that the SPU restore_stack_block pattern refers to /* Note that the SPU restore_stack_block pattern refers to
the stack pointer in V4SImode. Consider that non-trivial. */ the stack pointer in V4SImode. Consider that non-trivial. */
...@@ -3635,44 +3625,74 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size) ...@@ -3635,44 +3625,74 @@ fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
&& GET_CODE (SET_SRC (set)) == PLUS && GET_CODE (SET_SRC (set)) == PLUS
&& XEXP (SET_SRC (set), 0) == stack_pointer_rtx && XEXP (SET_SRC (set), 0) == stack_pointer_rtx
&& CONST_INT_P (XEXP (SET_SRC (set), 1))) && CONST_INT_P (XEXP (SET_SRC (set), 1)))
this_delta = INTVAL (XEXP (SET_SRC (set), 1)); return INTVAL (XEXP (SET_SRC (set), 1));
/* ??? Reload can generate no-op moves, which will be cleaned /* ??? Reload can generate no-op moves, which will be cleaned
up later. Recognize it and continue searching. */ up later. Recognize it and continue searching. */
else if (rtx_equal_p (dest, SET_SRC (set))) else if (rtx_equal_p (dest, SET_SRC (set)))
this_delta = 0; return 0;
else else
saw_unknown = true; return HOST_WIDE_INT_MIN;
} }
else
{
rtx mem, addr;
/* Otherwise only think about autoinc patterns. */ /* Otherwise only think about autoinc patterns. */
else if (mem_autoinc_base (dest) == stack_pointer_rtx) if (mem_autoinc_base (dest) == stack_pointer_rtx)
{ {
rtx addr = XEXP (dest, 0); mem = dest;
gcc_assert (!saw_unknown); gcc_checking_assert (mem_autoinc_base (SET_SRC (set))
!= stack_pointer_rtx);
}
else if (mem_autoinc_base (SET_SRC (set)) == stack_pointer_rtx)
mem = SET_SRC (set);
else
return 0;
addr = XEXP (mem, 0);
switch (GET_CODE (addr)) switch (GET_CODE (addr))
{ {
case PRE_INC: case PRE_INC:
case POST_INC: case POST_INC:
this_delta = GET_MODE_SIZE (GET_MODE (dest)); return GET_MODE_SIZE (GET_MODE (mem));
break;
case PRE_DEC: case PRE_DEC:
case POST_DEC: case POST_DEC:
this_delta = -GET_MODE_SIZE (GET_MODE (dest)); return -GET_MODE_SIZE (GET_MODE (mem));
break;
case PRE_MODIFY: case PRE_MODIFY:
case POST_MODIFY: case POST_MODIFY:
addr = XEXP (addr, 1); addr = XEXP (addr, 1);
gcc_assert (GET_CODE (addr) == PLUS); gcc_assert (GET_CODE (addr) == PLUS);
gcc_assert (XEXP (addr, 0) == stack_pointer_rtx); gcc_assert (XEXP (addr, 0) == stack_pointer_rtx);
gcc_assert (CONST_INT_P (XEXP (addr, 1))); gcc_assert (CONST_INT_P (XEXP (addr, 1)));
this_delta = INTVAL (XEXP (addr, 1)); return INTVAL (XEXP (addr, 1));
break;
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
} }
else }
int
fixup_args_size_notes (rtx prev, rtx last, int end_args_size)
{
int args_size = end_args_size;
bool saw_unknown = false;
rtx insn;
for (insn = last; insn != prev; insn = PREV_INSN (insn))
{
HOST_WIDE_INT this_delta;
if (!NONDEBUG_INSN_P (insn))
continue;
this_delta = find_args_size_adjust (insn);
if (this_delta == 0)
continue; continue;
gcc_assert (!saw_unknown);
if (this_delta == HOST_WIDE_INT_MIN)
saw_unknown = true;
add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size)); add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size));
#ifdef STACK_GROWS_DOWNWARD #ifdef STACK_GROWS_DOWNWARD
this_delta = -this_delta; this_delta = -this_delta;
......
...@@ -2508,6 +2508,7 @@ extern void emit_jump (rtx); ...@@ -2508,6 +2508,7 @@ extern void emit_jump (rtx);
/* In expr.c */ /* In expr.c */
extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT, extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
unsigned int, int); unsigned int, int);
extern HOST_WIDE_INT find_args_size_adjust (rtx);
extern int fixup_args_size_notes (rtx, rtx, int); extern int fixup_args_size_notes (rtx, rtx, int);
/* In cfgrtl.c */ /* In cfgrtl.c */
......
/* { dg-do compile } */
/* { dg-options "-Os -fno-asynchronous-unwind-tables -g" } */
void bar (long double n);
void foo (int c)
{
if (c)
bar (0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment