From ad73b558320545ee96736ae3f3373c48d3622504 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 27 Mar 2001 22:22:23 -0800 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 ++++++ gcc/flow.c | 25 ++++++++++++++++++++++--- gcc/reg-stack.c | 13 +++++++++---- 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 * 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