re PR rtl-optimization/36419 (Wrong unwind info with -Os -fasynchronous-unwind-tables)

PR rtl-optimization/36419
	* combine-stack-adj.c (adjust_frame_related_expr): New function.
	(combine_stack_adjustments_for_block): Call it if needed.  Delete
	correct insn.
	* dwarf2out.c (dwarf2out_frame_debug_expr): Adjust
	DW_CFA_GNU_args_size if CSA pass merged some adjustments into
	prologue sp adjustment.

	* g++.dg/eh/async-unwind1.C: New test.

From-SVN: r137689
This commit is contained in:
Jakub Jelinek 2008-07-10 09:39:54 +02:00
parent b1caaefc1c
commit a182fb6bfe
5 changed files with 182 additions and 7 deletions

View File

@ -1,12 +1,20 @@
2008-07-10 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/36419
* combine-stack-adj.c (adjust_frame_related_expr): New function.
(combine_stack_adjustments_for_block): Call it if needed. Delete
correct insn.
* dwarf2out.c (dwarf2out_frame_debug_expr): Adjust
DW_CFA_GNU_args_size if CSA pass merged some adjustments into
prologue sp adjustment.
2008-07-10 Peter Maydell <pmaydell@chiark.greenend.org.uk>
PR other/28322
* opts.c (print_ignored_options): report postponed diagnostics for
* opts.c (print_ignored_options): Report postponed diagnostics for
unknown -Wno-* options as warnings, not errors.
(postpone_unknown_option_error): renamed to
postpone_unknown_option_warning.
* gcc.dg/pr28322-2.c: check that emitted diagnostic for -Wno-foobar
is a warning and not an error.
(postpone_unknown_option_error): Renamed to...
(postpone_unknown_option_warning): ... this.
2008-07-09 Doug Kwan <dougkwan@google.com>

View File

@ -1,6 +1,6 @@
/* Combine stack adjustments.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
@ -272,6 +272,72 @@ record_stack_memrefs (rtx *xp, void *data)
return 0;
}
/* Adjust or create REG_FRAME_RELATED_EXPR note when merging a stack
adjustment into a frame related insn. */
static void
adjust_frame_related_expr (rtx last_sp_set, rtx insn,
HOST_WIDE_INT this_adjust)
{
rtx note = find_reg_note (last_sp_set, REG_FRAME_RELATED_EXPR, NULL_RTX);
rtx new_expr = NULL_RTX;
if (note == NULL_RTX && RTX_FRAME_RELATED_P (insn))
return;
if (note
&& GET_CODE (XEXP (note, 0)) == SEQUENCE
&& XVECLEN (XEXP (note, 0), 0) >= 2)
{
rtx expr = XEXP (note, 0);
rtx last = XVECEXP (expr, 0, XVECLEN (expr, 0) - 1);
int i;
if (GET_CODE (last) == SET
&& RTX_FRAME_RELATED_P (last) == RTX_FRAME_RELATED_P (insn)
&& SET_DEST (last) == stack_pointer_rtx
&& GET_CODE (SET_SRC (last)) == PLUS
&& XEXP (SET_SRC (last), 0) == stack_pointer_rtx
&& GET_CODE (XEXP (SET_SRC (last), 1)) == CONST_INT)
{
XEXP (SET_SRC (last), 1)
= GEN_INT (INTVAL (XEXP (SET_SRC (last), 1)) + this_adjust);
return;
}
new_expr = gen_rtx_SEQUENCE (VOIDmode,
rtvec_alloc (XVECLEN (expr, 0) + 1));
for (i = 0; i < XVECLEN (expr, 0); i++)
XVECEXP (new_expr, 0, i) = XVECEXP (expr, 0, i);
}
else
{
new_expr = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (2));
if (note)
XVECEXP (new_expr, 0, 0) = XEXP (note, 0);
else
{
rtx expr = copy_rtx (single_set_for_csa (last_sp_set));
XEXP (SET_SRC (expr), 1)
= GEN_INT (INTVAL (XEXP (SET_SRC (expr), 1)) - this_adjust);
RTX_FRAME_RELATED_P (expr) = 1;
XVECEXP (new_expr, 0, 0) = expr;
}
}
XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1)
= copy_rtx (single_set_for_csa (insn));
RTX_FRAME_RELATED_P (XVECEXP (new_expr, 0, XVECLEN (new_expr, 0) - 1))
= RTX_FRAME_RELATED_P (insn);
if (note)
XEXP (note, 0) = new_expr;
else
REG_NOTES (last_sp_set)
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, new_expr,
REG_NOTES (last_sp_set));
}
/* Subroutine of combine_stack_adjustments, called for each basic block. */
static void
@ -343,6 +409,9 @@ combine_stack_adjustments_for_block (basic_block bb)
last_sp_adjust + this_adjust,
this_adjust))
{
if (RTX_FRAME_RELATED_P (last_sp_set))
adjust_frame_related_expr (last_sp_set, insn,
this_adjust);
/* It worked! */
delete_insn (insn);
last_sp_adjust += this_adjust;
@ -373,7 +442,7 @@ combine_stack_adjustments_for_block (basic_block bb)
deallocation+allocation conspired to cancel, we can
delete the old deallocation insn. */
if (last_sp_set && last_sp_adjust == 0)
delete_insn (insn);
delete_insn (last_sp_set);
free_csa_memlist (memlist);
memlist = NULL;
last_sp_set = insn;

View File

@ -1579,6 +1579,32 @@ dwarf2out_frame_debug_expr (rtx expr, const char *label)
&& (!MEM_P (SET_DEST (elem)) || GET_CODE (expr) == SEQUENCE)
&& (RTX_FRAME_RELATED_P (elem) || par_index == 0))
dwarf2out_frame_debug_expr (elem, label);
else if (GET_CODE (elem) == SET
&& par_index != 0
&& !RTX_FRAME_RELATED_P (elem))
{
/* Stack adjustment combining might combine some post-prologue
stack adjustment into a prologue stack adjustment. */
HOST_WIDE_INT offset = stack_adjust_offset (elem);
if (offset != 0)
{
if (cfa.reg == STACK_POINTER_REGNUM)
cfa.offset += offset;
#ifndef STACK_GROWS_DOWNWARD
offset = -offset;
#endif
args_size += offset;
if (args_size < 0)
args_size = 0;
def_cfa_1 (label, &cfa);
if (flag_asynchronous_unwind_tables)
dwarf2out_args_size (label, args_size);
}
}
}
return;
}

View File

@ -1,3 +1,14 @@
2008-07-10 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/36419
* g++.dg/eh/async-unwind1.C: New test.
2008-07-10 Peter Maydell <pmaydell@chiark.greenend.org.uk>
PR other/28322
* gcc.dg/pr28322-2.c: Check that emitted diagnostic for -Wno-foobar
is a warning and not an error.
2008-07-09 Ian Lance Taylor <iant@google.com>
* gcc.dg/no-asm-1.c: New test.

View File

@ -0,0 +1,61 @@
// PR rtl-optimization/36419
// { dg-do run { target { { i?86-*-* x86_64-*-* } && ilp32 } } }
// { dg-options "-Os -fasynchronous-unwind-tables -mpreferred-stack-boundary=4" }
extern "C" void abort ();
int v = -1;
unsigned int n;
__attribute__((noinline, used))
void foo (int a, int)
{
if (v < 0)
v = ((unsigned long) &a) & 15;
else if ((((unsigned long) &a) & 15) != v)
abort ();
if (n++ == 0)
throw 1;
}
__attribute__((noinline, used))
void baz (int a, int, int, int, int, int, int)
{
if (v < 0)
v = ((unsigned long) &a) & 15;
else if ((((unsigned long) &a) & 15) != v)
abort ();
if (n++ == 0)
throw 1;
}
struct A { A () { }; ~A (); char c[24]; };
__attribute__((noinline))
A::~A ()
{
asm volatile ("" : : : "memory");
}
__attribute__((noinline))
void bar ()
{
A a;
try
{
foo (1, 2);
baz (3, 4, 5, 6, 7, 8, 9);
}
catch (...)
{
}
foo (1, 2);
baz (3, 4, 5, 6, 7, 8, 9);
}
int
main ()
{
bar ();
return 0;
}