summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-03-28 06:22:23 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2001-03-28 06:22:23 +0000
commit022208375a3750f0b792adcfa8176d7e85e5ef6d (patch)
tree6a3f4acb3012550610fc130ba3daec51f92064a8
parent98ad18c5b45f0e24a22a159bbb925a96a4064fe3 (diff)
downloadgcc-022208375a3750f0b792adcfa8176d7e85e5ef6d.tar.gz
* flow.c (tidy_fallthru_edges): Don't combine complex edges.
(calculate_global_regs_live): Kill call-clobbered registers across exception edges. * reg-stack.c (convert_regs_1): Kill the entire target stack across non-call exception edges. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40909 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/flow.c25
-rw-r--r--gcc/reg-stack.c13
3 files changed, 37 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 15a9dd295ad..de13830884d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -28,6 +28,12 @@
* final.c: Don't check it.
* except.c: Provide stub definition.
+ * flow.c (tidy_fallthru_edges): Don't combine complex edges.
+ (calculate_global_regs_live): Kill call-clobbered registers
+ across exception edges.
+ * reg-stack.c (convert_regs_1): Kill the entire target stack
+ across non-call exception edges.
+
2001-03-27 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* configure.in: Don't check for bcopy.
diff --git a/gcc/flow.c b/gcc/flow.c
index bf5043a5e7b..e8bf0400262 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -2995,6 +2995,7 @@ tidy_fallthru_edges ()
merge the flags for the duplicate edges. So we do not want to
check that the edge is not a FALLTHRU edge. */
if ((s = b->succ) != NULL
+ && ! (s->flags & EDGE_COMPLEX)
&& s->succ_next == NULL
&& s->dest == c
/* If the jump insn has side effects, we can't tidy the edge. */
@@ -3542,13 +3543,19 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
int flags;
{
basic_block *queue, *qhead, *qtail, *qend;
- regset tmp, new_live_at_end;
- regset_head tmp_head;
+ regset tmp, new_live_at_end, call_used;
+ regset_head tmp_head, call_used_head;
regset_head new_live_at_end_head;
int i;
tmp = INITIALIZE_REG_SET (tmp_head);
new_live_at_end = INITIALIZE_REG_SET (new_live_at_end_head);
+ call_used = INITIALIZE_REG_SET (call_used_head);
+
+ /* Inconveniently, this is only redily available in hard reg set form. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (call_used_regs[i])
+ SET_REGNO_REG_SET (call_used, i);
/* Create a worklist. Allocate an extra slot for ENTRY_BLOCK, and one
because the `head == tail' style test for an empty queue doesn't
@@ -3602,7 +3609,18 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
for (e = bb->succ; e; e = e->succ_next)
{
basic_block sb = e->dest;
- IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
+
+ /* Call-clobbered registers die across exception and call edges. */
+ /* ??? Abnormal call edges ignored for the moment, as this gets
+ confused by sibling call edges, which crashes reg-stack. */
+ if (e->flags & EDGE_EH)
+ {
+ bitmap_operation (tmp, sb->global_live_at_start,
+ call_used, BITMAP_AND_COMPL);
+ IOR_REG_SET (new_live_at_end, tmp);
+ }
+ else
+ IOR_REG_SET (new_live_at_end, sb->global_live_at_start);
}
/* The all-important stack pointer must always be live. */
@@ -3750,6 +3768,7 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
FREE_REG_SET (tmp);
FREE_REG_SET (new_live_at_end);
+ FREE_REG_SET (call_used);
if (blocks_out)
{
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 0e85a5ab922..54c3f086a48 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -2553,10 +2553,15 @@ convert_regs_1 (file, block)
}
}
- /* Care for EH edges specially. The normal return path may return
- a value in st(0), but the EH path will not, and there's no need
- to add popping code to the edge. */
- if (e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
+ /* Care for non-call EH edges specially. The normal return path have
+ values in registers. These will be popped en masse by the unwind
+ library. */
+ if ((e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) == EDGE_EH)
+ target_stack->top = -1;
+
+ /* Other calls may appear to have values live in st(0), but the
+ abnormal return path will not have actually loaded the values. */
+ else if (e->flags & EDGE_ABNORMAL_CALL)
{
/* Assert that the lifetimes are as we expect -- one value
live at st(0) on the end of the source block, and no