Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
- This file is part of GNU CC.
+ This file is part of GCC.
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* This pass converts stack-like registers from the "flat register
file" model that gcc uses, to a stack convention that the 387 uses.
static void remove_regno_note PARAMS ((rtx, enum reg_note,
unsigned int));
static int get_hard_regnum PARAMS ((stack, rtx));
-static void delete_insn_for_stacker PARAMS ((rtx));
static rtx emit_pop_insn PARAMS ((rtx, stack, rtx,
enum emit_where));
static void emit_swap_insn PARAMS ((rtx, stack, rtx));
stack_regs_mentioned_p (pat)
rtx pat;
{
- register const char *fmt;
- register int i;
+ const char *fmt;
+ int i;
if (STACK_REG_P (pat))
return 1;
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
if (stack_regs_mentioned_p (XVECEXP (pat, i, j)))
{
int i;
int max_uid;
- block_info bi;
/* Clean up previous run. */
if (stack_regs_mentioned_data)
mark_dfs_back_edges ();
/* Set up block info for each basic block. */
- bi = (block_info) xcalloc ((n_basic_blocks + 1), sizeof (*bi));
+ alloc_aux_for_blocks (sizeof (struct block_info_def));
for (i = n_basic_blocks - 1; i >= 0; --i)
{
edge e;
basic_block bb = BASIC_BLOCK (i);
- bb->aux = bi + i;
for (e = bb->pred; e; e=e->pred_next)
if (!(e->flags & EDGE_DFS_BACK)
&& e->src != ENTRY_BLOCK_PTR)
BLOCK_INFO (bb)->predecesors++;
}
- EXIT_BLOCK_PTR->aux = bi + n_basic_blocks;
/* Create the replacement registers up front. */
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
convert_regs (file);
- free (bi);
+ free_aux_for_blocks ();
}
\f
/* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the
record_label_references (insn, pat)
rtx insn, pat;
{
- register enum rtx_code code = GET_CODE (pat);
- register int i;
- register const char *fmt;
+ enum rtx_code code = GET_CODE (pat);
+ int i;
+ const char *fmt;
if (code == LABEL_REF)
{
- register rtx label = XEXP (pat, 0);
- register rtx ref;
+ rtx label = XEXP (pat, 0);
+ rtx ref;
if (GET_CODE (label) != CODE_LABEL)
abort ();
record_label_references (insn, XEXP (pat, i));
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = 0; j < XVECLEN (pat, i); j++)
record_label_references (insn, XVECEXP (pat, i, j));
}
enum reg_note note;
unsigned int regno;
{
- register rtx *note_link, this;
+ rtx *note_link, this;
note_link = ®_NOTES(insn);
for (this = *note_link; this; this = XEXP (this, 1))
return i >= 0 ? (FIRST_STACK_REG + regstack->top - i) : -1;
}
-
-/* Delete INSN from the RTL. Mark the insn, but don't remove it from
- the chain of insns. Doing so could confuse block_begin and block_end
- if this were the only insn in the block. */
-
-static void
-delete_insn_for_stacker (insn)
- rtx insn;
-{
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
-}
\f
/* Emit an insn to pop virtual register REG before or after INSN.
REGSTACK is the stack state after INSN and is updated to reflect this
FP_MODE_REG (FIRST_STACK_REG, DFmode));
if (where == EMIT_AFTER)
- pop_insn = emit_block_insn_after (pop_rtx, insn, current_block);
+ pop_insn = emit_insn_after (pop_rtx, insn);
else
- pop_insn = emit_block_insn_before (pop_rtx, insn, current_block);
+ pop_insn = emit_insn_before (pop_rtx, insn);
REG_NOTES (pop_insn)
= gen_rtx_EXPR_LIST (REG_DEAD, FP_MODE_REG (FIRST_STACK_REG, DFmode),
FP_MODE_REG (FIRST_STACK_REG, XFmode));
if (i1)
- emit_block_insn_after (swap_rtx, i1, current_block);
+ emit_insn_after (swap_rtx, i1);
else if (current_block)
- emit_block_insn_before (swap_rtx, current_block->head, current_block);
+ emit_insn_before (swap_rtx, current_block->head);
else
emit_insn_before (swap_rtx, insn);
}
{
emit_pop_insn (insn, regstack, src, EMIT_AFTER);
- delete_insn_for_stacker (insn);
+ delete_insn (insn);
return;
}
SET_HARD_REG_BIT (regstack->reg_set, REGNO (dest));
CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
- delete_insn_for_stacker (insn);
+ delete_insn (insn);
return;
}
if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
emit_pop_insn (insn, regstack, dest, EMIT_AFTER);
- delete_insn_for_stacker (insn);
+ delete_insn (insn);
return;
}
\f
/* Swap the condition on a branch, if there is one. Return true if we
found a condition to swap. False if the condition was not used as
- such. */
+ such. */
static int
swap_rtx_condition_1 (pat)
rtx pat;
{
- register const char *fmt;
- register int i, r = 0;
+ const char *fmt;
+ int i, r = 0;
if (GET_RTX_CLASS (GET_CODE (pat)) == '<')
{
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (pat, i) - 1; j >= 0; j--)
r |= swap_rtx_condition_1 (XVECEXP (pat, i, j));
break;
case IF_THEN_ELSE:
- /* This insn requires the top of stack to be the destination. */
+ /* This insn requires the top of stack to be the destination. */
+
+ src1 = get_true_reg (&XEXP (pat_src, 1));
+ src2 = get_true_reg (&XEXP (pat_src, 2));
+
+ src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+ src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
/* If the comparison operator is an FP comparison operator,
it is handled correctly by compare_for_stack_reg () who
will move the destination to the top of stack. But if the
comparison operator is not an FP comparison operator, we
- have to handle it here. */
+ have to handle it here. */
if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
&& REGNO (*dest) != regstack->reg[regstack->top])
- emit_swap_insn (insn, regstack, *dest);
-
- src1 = get_true_reg (&XEXP (pat_src, 1));
- src2 = get_true_reg (&XEXP (pat_src, 2));
-
- src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
- src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+ {
+ /* In case one of operands is the top of stack and the operands
+ dies, it is safe to make it the destination operand by reversing
+ the direction of cmove and avoid fxch. */
+ if ((REGNO (*src1) == regstack->reg[regstack->top]
+ && src1_note)
+ || (REGNO (*src2) == regstack->reg[regstack->top]
+ && src2_note))
+ {
+ int idx1 = (get_hard_regnum (regstack, *src1)
+ - FIRST_STACK_REG);
+ int idx2 = (get_hard_regnum (regstack, *src2)
+ - FIRST_STACK_REG);
+
+ /* Make reg-stack believe that the operands are already
+ swapped on the stack */
+ regstack->reg[regstack->top - idx1] = REGNO (*src2);
+ regstack->reg[regstack->top - idx2] = REGNO (*src1);
+
+ /* Reverse condition to compensate the operand swap.
+ i386 do have comparison always reversible. */
+ PUT_CODE (XEXP (pat_src, 0),
+ reversed_comparison_code (XEXP (pat_src, 0), insn));
+ }
+ else
+ emit_swap_insn (insn, regstack, *dest);
+ }
{
rtx src_note [3];
EMIT_AFTER);
}
else
- {
- CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
- replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG);
- regstack->top--;
- }
+ /* Top of stack never dies, as it is the
+ destination. */
+ abort ();
}
}
/* Make dest the top of stack. Add dest to regstack if
- not present. */
+ not present. */
if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG)
regstack->reg[++regstack->top] = REGNO (*dest);
SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
rtx insn;
stack regstack;
{
- register rtx *note_link, note;
- register int i;
+ rtx *note_link, note;
+ int i;
if (GET_CODE (insn) == CALL_INSN)
{
beste = e;
else if (beste->count > e->count)
;
- else if ((e->flags & EDGE_CRITICAL) != (beste->flags & EDGE_CRITICAL))
+ else if ((EDGE_CRITICAL_P (e) != 0)
+ != (EDGE_CRITICAL_P (beste) != 0))
{
- if (e->flags & EDGE_CRITICAL)
+ if (EDGE_CRITICAL_P (e))
beste = e;
}
else if (e->src->index < beste->src->index)
set = gen_rtx_SET (VOIDmode, FP_MODE_REG (reg, SFmode),
nan);
- insn = emit_block_insn_after (set, insn, block);
+ insn = emit_insn_after (set, insn);
subst_stack_regs (insn, ®stack);
}
}