aboutsummaryrefslogtreecommitdiff
path: root/gcc/reg-stack.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2005-06-04 22:05:35 +0000
committerRoger Sayle <roger@eyesopen.com>2005-06-04 22:05:35 +0000
commit29e632da1f6eb84d3fbe955001408fddb574ac7a (patch)
tree8335f5fc6555b2980dc3a9d65b5fd1347670edd4 /gcc/reg-stack.c
parent5e41ef34d333517d52f9cee640f3906096839d39 (diff)
* 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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@100602 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r--gcc/reg-stack.c82
1 files changed, 34 insertions, 48 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 5e5fcc74744..7007fcb2bd6 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), &regstack, 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, &regstack, 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);