cfgrtl.c (rtl_delete_block): Fix comment.

* cfgrtl.c (rtl_delete_block): Fix comment.
	* emit-rtl.c (remove_unnecessary_notes): Die if we see BLOCK_BEG
	or BLOCK_END insn notes.
	* jump.c (squeeze_notes): Likewise.
	* haifa-sched.c (reemit_notes): Don't "re-emit" EH_REGION_BEG and
	EH_REGION_END notes, we never have them to begin with.
	* sched-deps.c (sched_analyze_insn): When updating loop notes,
	verify that we have indeed only recorded loop notes.
	(sched_analyze): Die if we see EH_REGION_BEG or EH_REGION_END notes.
	Only record loop notes.

	* cfgexpand.c (tree_expand_cfg): Fix comment.

	* passes.c (rest_of_compilation): Don't do a second call to
	convert_from_eh_region_ranges from here, it's already called
	from cfgexpand.c.
	* except.c (resolve_fixup_regions): Remove.
	(remove_fixup_regions): Remove.
	(convert_from_eh_region_ranges_1): Remove.
	(convert_from_eh_region_ranges): Remove the case where EH is
	not already lowered at the tree level.  We always lower there.

From-SVN: r91148
This commit is contained in:
Steven Bosscher 2004-11-24 11:32:24 +00:00 committed by Steven Bosscher
parent b4345a57d8
commit f39e46bac1
9 changed files with 60 additions and 318 deletions

View File

@ -1,7 +1,30 @@
2004-11-24 Steven Bosscher <stevenb@suse.de>
* cfgrtl.c (rtl_delete_block): Fix comment.
* emit-rtl.c (remove_unnecessary_notes): Die if we see BLOCK_BEG
or BLOCK_END insn notes.
* jump.c (squeeze_notes): Likewise.
* haifa-sched.c (reemit_notes): Don't "re-emit" EH_REGION_BEG and
EH_REGION_END notes, we never have them to begin with.
* sched-deps.c (sched_analyze_insn): When updating loop notes,
verify that we have indeed only recorded loop notes.
(sched_analyze): Die if we see EH_REGION_BEG or EH_REGION_END notes.
Only record loop notes.
* cfgexpand.c (tree_expand_cfg): Fix comment.
* passes.c (rest_of_compilation): Don't do a second call to
convert_from_eh_region_ranges from here, it's already called
from cfgexpand.c.
* except.c (resolve_fixup_regions): Remove.
(remove_fixup_regions): Remove.
(convert_from_eh_region_ranges_1): Remove.
(convert_from_eh_region_ranges): Remove the case where EH is
not already lowered at the tree level. We always lower there.
2004-11-24 Paolo Bonzini <bonzini@gnu.org>
PR c++/16882
* tree.c (make_vector_type): Move qualifiers to the vector type,
use the inner type's main variant and build a main variant for
the vector type if necessary.

View File

@ -1310,8 +1310,8 @@ tree_expand_cfg (void)
/* We're done expanding trees to RTL. */
currently_expanding_to_rtl = 0;
/* Convert from NOTE_INSN_EH_REGION style notes, and do other
sorts of eh initialization. */
/* Convert tree EH labels to RTL EH labels, and clean out any unreachable
EH regions. */
convert_from_eh_region_ranges ();
rebuild_jump_labels (get_insns ());

View File

@ -368,14 +368,9 @@ rtl_delete_block (basic_block b)
rtx insn, end, tmp;
/* If the head of this block is a CODE_LABEL, then it might be the
label for an exception handler which can't be reached.
We need to remove the label from the exception_handler_label list
and remove the associated NOTE_INSN_EH_REGION_BEG and
NOTE_INSN_EH_REGION_END notes. */
label for an exception handler which can't be reached. We need
to remove the label from the exception_handler_label list. */
insn = BB_HEAD (b);
if (LABEL_P (insn))
maybe_remove_eh_handler (insn);

View File

@ -3728,7 +3728,6 @@ find_line_note (rtx insn)
void
remove_unnecessary_notes (void)
{
rtx block_stack = NULL_RTX;
rtx eh_stack = NULL_RTX;
rtx insn;
rtx next;
@ -3767,66 +3766,17 @@ remove_unnecessary_notes (void)
break;
case NOTE_INSN_BLOCK_BEG:
/* By now, all notes indicating lexical blocks should have
NOTE_BLOCK filled in. */
gcc_assert (NOTE_BLOCK (insn));
block_stack = alloc_INSN_LIST (insn, block_stack);
break;
case NOTE_INSN_BLOCK_END:
/* Too many end notes. */
gcc_assert (block_stack);
/* Mismatched nesting. */
gcc_assert (NOTE_BLOCK (XEXP (block_stack, 0)) == NOTE_BLOCK (insn));
tmp = block_stack;
block_stack = XEXP (block_stack, 1);
free_INSN_LIST_node (tmp);
/* BLOCK_END and BLOCK_BEG notes only exist in the `final' pass. */
gcc_unreachable ();
/* Scan back to see if there are any non-note instructions
between INSN and the beginning of this block. If not,
then there is no PC range in the generated code that will
actually be in this block, so there's no point in
remembering the existence of the block. */
for (tmp = PREV_INSN (insn); tmp; tmp = PREV_INSN (tmp))
{
/* This block contains a real instruction. Note that we
don't include labels; if the only thing in the block
is a label, then there are still no PC values that
lie within the block. */
if (INSN_P (tmp))
break;
/* We're only interested in NOTEs. */
if (!NOTE_P (tmp))
continue;
if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_BEG)
{
/* We just verified that this BLOCK matches us with
the block_stack check above. Never delete the
BLOCK for the outermost scope of the function; we
can refer to names from that scope even if the
block notes are messed up. */
if (! is_body_block (NOTE_BLOCK (insn))
&& (*debug_hooks->ignore_block) (NOTE_BLOCK (insn)))
{
remove_insn (tmp);
remove_insn (insn);
}
break;
}
else if (NOTE_LINE_NUMBER (tmp) == NOTE_INSN_BLOCK_END)
/* There's a nested block. We need to leave the
current block in place since otherwise the debugger
wouldn't be able to show symbols from our block in
the nested block. */
break;
}
default:
break;
}
}
/* Too many begin notes. */
gcc_assert (!block_stack && !eh_stack);
/* Too many EH_REGION_BEG notes. */
gcc_assert (!eh_stack);
}

View File

@ -260,10 +260,7 @@ static hashval_t t2r_hash (const void *);
static void add_type_for_runtime (tree);
static tree lookup_type_for_runtime (tree);
static void resolve_fixup_regions (void);
static void remove_fixup_regions (void);
static void remove_unreachable_regions (rtx);
static void convert_from_eh_region_ranges_1 (rtx *, int *, int);
static int ttypes_filter_eq (const void *, const void *);
static hashval_t ttypes_filter_hash (const void *);
@ -668,123 +665,6 @@ collect_eh_region_array (void)
}
}
static void
resolve_one_fixup_region (struct eh_region *fixup)
{
struct eh_region *cleanup, *real;
int j, n;
n = cfun->eh->last_region_number;
cleanup = 0;
for (j = 1; j <= n; ++j)
{
cleanup = cfun->eh->region_array[j];
if (cleanup && cleanup->type == ERT_CLEANUP
&& cleanup->u.cleanup.exp == fixup->u.fixup.cleanup_exp)
break;
}
gcc_assert (j <= n);
real = cleanup->outer;
if (real && real->type == ERT_FIXUP)
{
if (!real->u.fixup.resolved)
resolve_one_fixup_region (real);
real = real->u.fixup.real_region;
}
fixup->u.fixup.real_region = real;
fixup->u.fixup.resolved = true;
}
static void
resolve_fixup_regions (void)
{
int i, n = cfun->eh->last_region_number;
for (i = 1; i <= n; ++i)
{
struct eh_region *fixup = cfun->eh->region_array[i];
if (!fixup || fixup->type != ERT_FIXUP || fixup->u.fixup.resolved)
continue;
resolve_one_fixup_region (fixup);
}
}
/* Now that we've discovered what region actually encloses a fixup,
we can shuffle pointers and remove them from the tree. */
static void
remove_fixup_regions (void)
{
int i;
rtx insn, note;
struct eh_region *fixup;
/* Walk the insn chain and adjust the REG_EH_REGION numbers
for instructions referencing fixup regions. This is only
strictly necessary for fixup regions with no parent, but
doesn't hurt to do it for all regions. */
for (insn = get_insns(); insn ; insn = NEXT_INSN (insn))
if (INSN_P (insn)
&& (note = find_reg_note (insn, REG_EH_REGION, NULL))
&& INTVAL (XEXP (note, 0)) > 0
&& (fixup = cfun->eh->region_array[INTVAL (XEXP (note, 0))])
&& fixup->type == ERT_FIXUP)
{
if (fixup->u.fixup.real_region)
XEXP (note, 0) = GEN_INT (fixup->u.fixup.real_region->region_number);
else
remove_note (insn, note);
}
/* Remove the fixup regions from the tree. */
for (i = cfun->eh->last_region_number; i > 0; --i)
{
fixup = cfun->eh->region_array[i];
if (! fixup)
continue;
/* Allow GC to maybe free some memory. */
if (fixup->type == ERT_CLEANUP)
fixup->u.cleanup.exp = NULL_TREE;
if (fixup->type != ERT_FIXUP)
continue;
if (fixup->inner)
{
struct eh_region *parent, *p, **pp;
parent = fixup->u.fixup.real_region;
/* Fix up the children's parent pointers; find the end of
the list. */
for (p = fixup->inner; ; p = p->next_peer)
{
p->outer = parent;
if (! p->next_peer)
break;
}
/* In the tree of cleanups, only outer-inner ordering matters.
So link the children back in anywhere at the correct level. */
if (parent)
pp = &parent->inner;
else
pp = &cfun->eh->region_tree;
p->next_peer = *pp;
*pp = fixup->inner;
fixup->inner = NULL;
}
remove_eh_handler (fixup);
}
}
/* Remove all regions whose labels are not reachable from insns. */
static void
@ -868,113 +748,23 @@ remove_unreachable_regions (rtx insns)
free (uid_region_num);
}
/* Turn NOTE_INSN_EH_REGION notes into REG_EH_REGION notes for each
can_throw instruction in the region. */
static void
convert_from_eh_region_ranges_1 (rtx *pinsns, int *orig_sp, int cur)
{
int *sp = orig_sp;
rtx insn, next;
for (insn = *pinsns; insn ; insn = next)
{
next = NEXT_INSN (insn);
if (NOTE_P (insn))
{
int kind = NOTE_LINE_NUMBER (insn);
if (kind == NOTE_INSN_EH_REGION_BEG
|| kind == NOTE_INSN_EH_REGION_END)
{
if (kind == NOTE_INSN_EH_REGION_BEG)
{
struct eh_region *r;
*sp++ = cur;
cur = NOTE_EH_HANDLER (insn);
r = cfun->eh->region_array[cur];
if (r->type == ERT_FIXUP)
{
r = r->u.fixup.real_region;
cur = r ? r->region_number : 0;
}
else if (r->type == ERT_CATCH)
{
r = r->outer;
cur = r ? r->region_number : 0;
}
}
else
cur = *--sp;
if (insn == *pinsns)
*pinsns = next;
remove_insn (insn);
continue;
}
}
else if (INSN_P (insn))
{
if (cur > 0
&& ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
/* Calls can always potentially throw exceptions, unless
they have a REG_EH_REGION note with a value of 0 or less.
Which should be the only possible kind so far. */
&& (CALL_P (insn)
/* If we wanted exceptions for non-call insns, then
any may_trap_p instruction could throw. */
|| (flag_non_call_exceptions
&& GET_CODE (PATTERN (insn)) != CLOBBER
&& GET_CODE (PATTERN (insn)) != USE
&& may_trap_p (PATTERN (insn)))))
{
REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (cur),
REG_NOTES (insn));
}
}
}
gcc_assert (sp == orig_sp);
}
static void
collect_rtl_labels_from_trees (void)
{
int i, n = cfun->eh->last_region_number;
for (i = 1; i <= n; ++i)
{
struct eh_region *reg = cfun->eh->region_array[i];
if (reg && reg->tree_label)
reg->label = DECL_RTL_IF_SET (reg->tree_label);
}
}
/* Set up EH labels for RTL. */
void
convert_from_eh_region_ranges (void)
{
rtx insns = get_insns ();
int i, n = cfun->eh->last_region_number;
if (cfun->eh->region_array)
/* Most of the work is already done at the tree level. All we need to
do is collect the rtl labels that correspond to the tree labels that
collect the rtl labels that correspond to the tree labels
we allocated earlier. */
for (i = 1; i <= n; ++i)
{
/* If the region array already exists, assume we're coming from
optimize_function_tree. In this case all we need to do is
collect the rtl labels that correspond to the tree labels
that we allocated earlier. */
collect_rtl_labels_from_trees ();
}
else
{
int *stack;
collect_eh_region_array ();
resolve_fixup_regions ();
stack = xmalloc (sizeof (int) * (cfun->eh->last_region_number + 1));
convert_from_eh_region_ranges_1 (&insns, stack, 0);
free (stack);
remove_fixup_regions ();
struct eh_region *region = cfun->eh->region_array[i];
if (region && region->tree_label)
region->label = DECL_RTL_IF_SET (region->tree_label);
}
remove_unreachable_regions (insns);

View File

@ -1648,11 +1648,6 @@ reemit_notes (rtx insn, rtx last)
last = emit_note_before (note_type, last);
remove_note (insn, note);
note = XEXP (note, 1);
if (note_type == NOTE_INSN_EH_REGION_BEG
|| note_type == NOTE_INSN_EH_REGION_END)
NOTE_EH_HANDLER (last) = INTVAL (XEXP (note, 0));
remove_note (insn, note);
}
}
return retval;

View File

@ -248,6 +248,10 @@ squeeze_notes (rtx* startp, rtx* endp)
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
{
/* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass. */
gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END);
if (insn == start)
start = next;
else

View File

@ -1538,10 +1538,6 @@ rest_of_clean_state (void)
static void
rest_of_compilation (void)
{
/* Convert from NOTE_INSN_EH_REGION style notes, and do other
sorts of eh initialization. */
convert_from_eh_region_ranges ();
/* If we're emitting a nested function, make sure its parent gets
emitted as well. Doing otherwise confuses debug info. */
{

View File

@ -976,18 +976,14 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes)
{
rtx link;
/* Update loop_notes with any notes from this insn. Also determine
if any of the notes on the list correspond to instruction scheduling
barriers (loop, eh & setjmp notes, but not range notes). */
/* Update loop_notes with any notes from this insn. */
link = loop_notes;
while (XEXP (link, 1))
{
if (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_BEG
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_EH_REGION_END)
reg_pending_barrier = MOVE_BARRIER;
gcc_assert (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
|| INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END);
reg_pending_barrier = MOVE_BARRIER;
link = XEXP (link, 1);
}
XEXP (link, 1) = REG_NOTES (insn);
@ -1323,26 +1319,19 @@ sched_analyze (struct deps *deps, rtx head, rtx tail)
deps->in_post_call_group_p = post_call;
}
/* EH_REGION insn notes can not appear until well after we complete
scheduling. */
if (NOTE_P (insn))
gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END);
/* See comments on reemit_notes as to why we do this.
??? Actually, the reemit_notes just say what is done, not why. */
if (NOTE_P (insn)
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
{
rtx rtx_region;
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
rtx_region = GEN_INT (NOTE_EH_HANDLER (insn));
else
rtx_region = const0_rtx;
loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE,
rtx_region,
loop_notes);
loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE,
GEN_INT (NOTE_LINE_NUMBER (insn)),
loop_notes);