diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/reg-stack.c | 82 |
2 files changed, 44 insertions, 48 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c628c7..df16d2a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2005-06-04 Roger Sayle <roger@eyesopen.com> + + * reg-stack.c (struct block_info_def): Correct grammar typo. + (compensate_edge): Clean-up. Perform as little work as possible + when src and dest stacks match. Avoid modifying block_info. + Reorder and simplify assertion checks. Avoid unnecessary copying + of regstack structure. + (convert_regs_1): Set the done flag here... + (convert_regs_2): ... instead of here. + 2005-06-04 Dale Johannesen <dalej@apple.com> * config/rs6000/rs6000.c (no_global_regs_above): New. diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 5e5fcc7..7007fcb 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -208,7 +208,7 @@ typedef struct block_info_def struct stack_def stack_out; /* Output stack configuration. */ HARD_REG_SET out_reg_set; /* Stack regs live on output. */ int done; /* True if block already converted. */ - int predecessors; /* Number of predecessors that needs + int predecessors; /* Number of predecessors that need to be visited. */ } *block_info; @@ -2629,24 +2629,22 @@ propagate_stack (edge e) static bool compensate_edge (edge e, FILE *file) { - basic_block block = e->src, target = e->dest; - block_info bi = BLOCK_INFO (block); - struct stack_def regstack, tmpstack; + basic_block source = e->src, target = e->dest; stack target_stack = &BLOCK_INFO (target)->stack_in; + stack source_stack = &BLOCK_INFO (source)->stack_out; + struct stack_def regstack; int reg; - current_block = block; - regstack = bi->stack_out; if (file) - fprintf (file, "Edge %d->%d: ", block->index, target->index); + fprintf (file, "Edge %d->%d: ", source->index, target->index); gcc_assert (target_stack->top != -2); /* Check whether stacks are identical. */ - if (target_stack->top == regstack.top) + if (target_stack->top == source_stack->top) { for (reg = target_stack->top; reg >= 0; --reg) - if (target_stack->reg[reg] != regstack.reg[reg]) + if (target_stack->reg[reg] != source_stack->reg[reg]) break; if (reg == -1) @@ -2663,68 +2661,56 @@ compensate_edge (edge e, FILE *file) print_stack (file, target_stack); } - /* 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 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) + 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 values live at the beginning of the destination block. */ - HARD_REG_SET tmp; - - CLEAR_HARD_REG_SET (tmp); - GO_IF_HARD_REG_EQUAL (target_stack->reg_set, tmp, eh1); - gcc_unreachable (); - eh1: - - /* We are sure that there is st(0) live, otherwise we won't compensate. - For complex return values, we may have st(1) live as well. */ - SET_HARD_REG_BIT (tmp, FIRST_STACK_REG); - if (TEST_HARD_REG_BIT (regstack.reg_set, FIRST_STACK_REG + 1)) - SET_HARD_REG_BIT (tmp, FIRST_STACK_REG + 1); - GO_IF_HARD_REG_EQUAL (regstack.reg_set, tmp, eh2); - gcc_unreachable (); - eh2: + gcc_assert (source_stack->top == 0); + gcc_assert (target_stack->top == -1); + return false; + } - target_stack->top = -1; + /* Handle 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) + { + gcc_assert (target_stack->top == -1); + return false; } + /* We don't support abnormal edges. Global takes care to + avoid any live register across them, so we should never + have to insert instructions on such edges. */ + gcc_assert (! (e->flags & EDGE_ABNORMAL)); + + /* Make a copy of source_stack as change_stack is destructive. */ + regstack = *source_stack; + /* It is better to output directly to the end of the block instead of to the edge, because emit_swap can do minimal insn scheduling. We can do this when there is only one edge out, and it is not abnormal. */ - else if (EDGE_COUNT (block->succs) == 1 && !(e->flags & EDGE_ABNORMAL)) + if (EDGE_COUNT (source->succs) == 1) { - /* change_stack kills values in regstack. */ - tmpstack = regstack; - - change_stack (BB_END (block), &tmpstack, target_stack, - (JUMP_P (BB_END (block)) - ? EMIT_BEFORE : EMIT_AFTER)); + current_block = source; + change_stack (BB_END (source), ®stack, target_stack, + (JUMP_P (BB_END (source)) ? EMIT_BEFORE : EMIT_AFTER)); } else { rtx seq, after; - /* We don't support abnormal edges. Global takes care to - avoid any live register across them, so we should never - have to insert instructions on such edges. */ - gcc_assert (!(e->flags & EDGE_ABNORMAL)); - current_block = NULL; start_sequence (); /* ??? change_stack needs some point to emit insns after. */ after = emit_note (NOTE_INSN_DELETED); - tmpstack = regstack; - change_stack (after, &tmpstack, target_stack, EMIT_BEFORE); + change_stack (after, ®stack, target_stack, EMIT_BEFORE); seq = get_insns (); end_sequence (); @@ -2928,6 +2914,7 @@ convert_regs_1 (FILE *file, basic_block block) gcc_assert (any_malformed_asm); win: bi->stack_out = regstack; + bi->done = true; } /* Convert registers in all blocks reachable from BLOCK. */ @@ -2975,7 +2962,6 @@ convert_regs_2 (FILE *file, basic_block block) } convert_regs_1 (file, block); - BLOCK_INFO (block)->done = 1; } while (sp != stack); |