diff options
author | Richard Henderson <rth@redhat.com> | 2001-03-27 22:22:23 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-03-27 22:22:23 -0800 |
commit | ad73b558320545ee96736ae3f3373c48d3622504 (patch) | |
tree | 6a3f4acb3012550610fc130ba3daec51f92064a8 /gcc | |
parent | 461fc4de6a0434d7fc8c3ef53b25a4e51db69829 (diff) | |
download | gcc-ad73b558320545ee96736ae3f3373c48d3622504.zip gcc-ad73b558320545ee96736ae3f3373c48d3622504.tar.gz gcc-ad73b558320545ee96736ae3f3373c48d3622504.tar.bz2 |
flow.c (tidy_fallthru_edges): Don't combine complex edges.
* 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.
From-SVN: r40909
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/flow.c | 25 | ||||
-rw-r--r-- | gcc/reg-stack.c | 13 |
3 files changed, 37 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 15a9dd2..de13830 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. @@ -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 0e85a5a..54c3f08 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 |