aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog25
-rw-r--r--gcc/cfgexpand.c4
-rw-r--r--gcc/cfgrtl.c9
-rw-r--r--gcc/emit-rtl.c62
-rw-r--r--gcc/except.c230
-rw-r--r--gcc/haifa-sched.c5
-rw-r--r--gcc/jump.c4
-rw-r--r--gcc/passes.c4
-rw-r--r--gcc/sched-deps.c35
9 files changed, 60 insertions, 318 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0e96f07..e9e7ebc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index df0c695..f710aed 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -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 ());
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 0bb181a..3c2dc96 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -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);
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 98dec5f..fba2412 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -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);
}
diff --git a/gcc/except.c b/gcc/except.c
index c399eb1..b906cf0 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -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)
- {
- /* 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
+ /* 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)
{
- 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);
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index d413137..9b3ed5e 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -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;
diff --git a/gcc/jump.c b/gcc/jump.c
index 0378cf7..85c1f6b2 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -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
diff --git a/gcc/passes.c b/gcc/passes.c
index 36b13d1..37e84c8 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -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. */
{
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index 5e23a93..32d0fdb 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -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);