Commit fe08a886 by Bernd Schmidt Committed by Bernd Schmidt

Renamer improvements.

From-SVN: r38463
parent e6fe680d
2000-12-22 Bernd Schmidt <bernds@redhat.com>
* regrename.c (struct du_chain): New field "earlyclobber".
(enum scan_actions): Remove unused entry "note_reference".
(enum scan_actions_name): Likewise.
(note_sets, clear_dead_regs, merge_overlapping_regs): New static
functions.
(regrename_optimize): Use them to compute unavailable regs; get
rid of the more simpleminded code we used to have here.
Use a tick array to ensure registers are allocated in a more
round-robin way. Disable code that only optimizes registers
that were seen more than once.
(referenced_regs): Remove variable.
(scan_rtx_reg): New arg "earlyclobber". All callers changed.
Store its value in newly generated du_chain structures.
Add new du_chains at the end, not the start, of the list.
Don't handle the "note_reference" action.
(scan_rtx): New arg "earlyclobber". All callers changed.
(build_def_use): Lose code to keep track of referenced regs.
2000-12-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2000-12-22 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* Makefile.in (sched-deps.o, sched-rgn.o): Fix dependency typo. * Makefile.in (sched-deps.o, sched-rgn.o): Fix dependency typo.
......
...@@ -57,11 +57,11 @@ struct du_chain ...@@ -57,11 +57,11 @@ struct du_chain
rtx *loc; rtx *loc;
enum reg_class class; enum reg_class class;
unsigned int need_caller_save_reg:1; unsigned int need_caller_save_reg:1;
unsigned int earlyclobber:1;
}; };
enum scan_actions enum scan_actions
{ {
note_reference,
terminate_all_read, terminate_all_read,
terminate_overlapping_read, terminate_overlapping_read,
terminate_write, terminate_write,
...@@ -72,7 +72,6 @@ enum scan_actions ...@@ -72,7 +72,6 @@ enum scan_actions
static const char * const scan_actions_name[] = static const char * const scan_actions_name[] =
{ {
"note_reference",
"terminate_all_read", "terminate_all_read",
"terminate_overlapping_read", "terminate_overlapping_read",
"terminate_write", "terminate_write",
...@@ -85,20 +84,117 @@ static struct obstack rename_obstack; ...@@ -85,20 +84,117 @@ static struct obstack rename_obstack;
static void do_replace PARAMS ((struct du_chain *, int)); static void do_replace PARAMS ((struct du_chain *, int));
static void scan_rtx_reg PARAMS ((rtx, rtx *, enum reg_class, static void scan_rtx_reg PARAMS ((rtx, rtx *, enum reg_class,
enum scan_actions, enum op_type)); enum scan_actions, enum op_type, int));
static void scan_rtx_address PARAMS ((rtx, rtx *, enum reg_class, static void scan_rtx_address PARAMS ((rtx, rtx *, enum reg_class,
enum scan_actions, enum machine_mode)); enum scan_actions, enum machine_mode));
static void scan_rtx PARAMS ((rtx, rtx *, enum reg_class, static void scan_rtx PARAMS ((rtx, rtx *, enum reg_class,
enum scan_actions, enum op_type)); enum scan_actions, enum op_type, int));
static struct du_chain *build_def_use PARAMS ((basic_block, HARD_REG_SET *)); static struct du_chain *build_def_use PARAMS ((basic_block));
static void dump_def_use_chain PARAMS ((struct du_chain *)); static void dump_def_use_chain PARAMS ((struct du_chain *));
static void note_sets PARAMS ((rtx, rtx, void *));
static void clear_dead_regs PARAMS ((HARD_REG_SET *, enum machine_mode, rtx));
static void merge_overlapping_regs PARAMS ((basic_block, HARD_REG_SET *,
struct du_chain *));
/* Called through note_stores from update_life. Find sets of registers, and
record them in *DATA (which is actually a HARD_REG_SET *). */
static void
note_sets (x, set, data)
rtx x;
rtx set ATTRIBUTE_UNUSED;
void *data;
{
HARD_REG_SET *pset = (HARD_REG_SET *) data;
unsigned int regno;
int nregs;
if (GET_CODE (x) != REG)
return;
regno = REGNO (x);
nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (nregs-- > 0)
SET_HARD_REG_BIT (*pset, regno + nregs);
}
/* Clear all registers from *PSET for which a note of kind KIND can be found
in the list NOTES. */
static void
clear_dead_regs (pset, kind, notes)
HARD_REG_SET *pset;
enum machine_mode kind;
rtx notes;
{
rtx note;
for (note = notes; note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == kind && REG_P (XEXP (note, 0)))
{
rtx reg = XEXP (note, 0);
unsigned int regno = REGNO (reg);
int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (nregs-- > 0)
CLEAR_HARD_REG_BIT (*pset, regno + nregs);
}
}
/* For a def-use chain CHAIN in basic block B, find which registers overlap
its lifetime and set the corresponding bits in *PSET. */
static void
merge_overlapping_regs (b, pset, chain)
basic_block b;
HARD_REG_SET *pset;
struct du_chain *chain;
{
struct du_chain *t = chain;
rtx insn;
HARD_REG_SET live;
REG_SET_TO_HARD_REG_SET (live, b->global_live_at_start);
insn = b->head;
while (t)
{
/* Search forward until the next reference to the register to be
renamed. */
while (insn != t->insn)
{
if (INSN_P (insn))
{
clear_dead_regs (&live, REG_DEAD, REG_NOTES (insn));
note_stores (PATTERN (insn), note_sets, (void *) &live);
/* Only record currently live regs if we are inside the
reg's live range. */
if (t != chain)
IOR_HARD_REG_SET (*pset, live);
clear_dead_regs (&live, REG_UNUSED, REG_NOTES (insn));
}
insn = NEXT_INSN (insn);
}
IOR_HARD_REG_SET (*pset, live);
/* For the last reference, also merge in all registers set in the
same insn.
@@@ We only have take earlyclobbered sets into account. */
if (! t->next_use)
note_stores (PATTERN (insn), note_sets, (void *) pset);
t = t->next_use;
}
}
/* Perform register renaming on the current function. */
void void
regrename_optimize () regrename_optimize ()
{ {
int tick[FIRST_PSEUDO_REGISTER];
int this_tick = 0;
int b; int b;
char *first_obj; char *first_obj;
memset (tick, 0, sizeof tick);
gcc_obstack_init (&rename_obstack); gcc_obstack_init (&rename_obstack);
first_obj = (char *) obstack_alloc (&rename_obstack, 0); first_obj = (char *) obstack_alloc (&rename_obstack, 0);
...@@ -106,28 +202,20 @@ regrename_optimize () ...@@ -106,28 +202,20 @@ regrename_optimize ()
{ {
basic_block bb = BASIC_BLOCK (b); basic_block bb = BASIC_BLOCK (b);
struct du_chain *all_chains = 0; struct du_chain *all_chains = 0;
HARD_REG_SET regs_used;
HARD_REG_SET unavailable; HARD_REG_SET unavailable;
HARD_REG_SET regs_seen; HARD_REG_SET regs_seen;
CLEAR_HARD_REG_SET (regs_used);
CLEAR_HARD_REG_SET (unavailable); CLEAR_HARD_REG_SET (unavailable);
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "\nBasic block %d:\n", b); fprintf (rtl_dump_file, "\nBasic block %d:\n", b);
all_chains = build_def_use (bb, &regs_used); all_chains = build_def_use (bb);
if (rtl_dump_file) if (rtl_dump_file)
dump_def_use_chain (all_chains); dump_def_use_chain (all_chains);
/* Available registers are not: used in the block, live at the start CLEAR_HARD_REG_SET (unavailable);
live at the end, a register we've renamed to. */
REG_SET_TO_HARD_REG_SET (unavailable, bb->global_live_at_start);
REG_SET_TO_HARD_REG_SET (regs_seen, bb->global_live_at_end);
IOR_HARD_REG_SET (unavailable, regs_seen);
IOR_HARD_REG_SET (unavailable, regs_used);
/* Don't clobber traceback for noreturn functions. */ /* Don't clobber traceback for noreturn functions. */
if (frame_pointer_needed) if (frame_pointer_needed)
{ {
...@@ -140,6 +228,7 @@ regrename_optimize () ...@@ -140,6 +228,7 @@ regrename_optimize ()
CLEAR_HARD_REG_SET (regs_seen); CLEAR_HARD_REG_SET (regs_seen);
while (all_chains) while (all_chains)
{ {
int new_reg, best_new_reg = -1;
int n_uses; int n_uses;
struct du_chain *this = all_chains; struct du_chain *this = all_chains;
struct du_chain *tmp, *last; struct du_chain *tmp, *last;
...@@ -149,13 +238,15 @@ regrename_optimize () ...@@ -149,13 +238,15 @@ regrename_optimize ()
int i; int i;
all_chains = this->next_chain; all_chains = this->next_chain;
#if 0 /* This just disables optimization opportunities. */
/* Only rename once we've seen the reg more than once. */ /* Only rename once we've seen the reg more than once. */
if (! TEST_HARD_REG_BIT (regs_seen, reg)) if (! TEST_HARD_REG_BIT (regs_seen, reg))
{ {
SET_HARD_REG_BIT (regs_seen, reg); SET_HARD_REG_BIT (regs_seen, reg);
continue; continue;
} }
#endif
if (fixed_regs[reg] || global_regs[reg]) if (fixed_regs[reg] || global_regs[reg])
continue; continue;
...@@ -178,21 +269,25 @@ regrename_optimize () ...@@ -178,21 +269,25 @@ regrename_optimize ()
IOR_COMPL_HARD_REG_SET (this_unavailable, IOR_COMPL_HARD_REG_SET (this_unavailable,
reg_class_contents[last->class]); reg_class_contents[last->class]);
if (last->need_caller_save_reg) if (this->need_caller_save_reg)
IOR_HARD_REG_SET (this_unavailable, call_used_reg_set); IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
merge_overlapping_regs (bb, &this_unavailable, this);
/* Now potential_regs is a reasonable approximation, let's /* Now potential_regs is a reasonable approximation, let's
have a closer look at each register still in there. */ have a closer look at each register still in there. */
for (treg = 0; treg < FIRST_PSEUDO_REGISTER; treg++) for (treg = 0; treg < FIRST_PSEUDO_REGISTER; treg++)
{ {
new_reg = treg;
for (i = nregs - 1; i >= 0; --i) for (i = nregs - 1; i >= 0; --i)
if (TEST_HARD_REG_BIT (this_unavailable, treg+i) if (TEST_HARD_REG_BIT (this_unavailable, new_reg + i)
|| fixed_regs[treg+i] || fixed_regs[new_reg + i]
|| global_regs[treg+i] || global_regs[new_reg + i]
/* Can't use regs which aren't saved by the prologue. */ /* Can't use regs which aren't saved by the prologue. */
|| (! regs_ever_live[treg+i] && ! call_used_regs[treg+i]) || (! regs_ever_live[new_reg + i]
&& ! call_used_regs[new_reg + i])
#ifdef HARD_REGNO_RENAME_OK #ifdef HARD_REGNO_RENAME_OK
|| ! HARD_REGNO_RENAME_OK (reg+i, treg+i) || ! HARD_REGNO_RENAME_OK (reg + i, new_reg + i)
#endif #endif
) )
break; break;
...@@ -202,10 +297,14 @@ regrename_optimize () ...@@ -202,10 +297,14 @@ regrename_optimize ()
/* See whether it accepts all modes that occur in /* See whether it accepts all modes that occur in
definition and uses. */ definition and uses. */
for (tmp = this; tmp; tmp = tmp->next_use) for (tmp = this; tmp; tmp = tmp->next_use)
if (! HARD_REGNO_MODE_OK (treg, GET_MODE (*tmp->loc))) if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc)))
break; break;
if (! tmp) if (! tmp)
break; {
if (best_new_reg == -1
|| tick[best_new_reg] > tick[new_reg])
best_new_reg = new_reg;
}
} }
if (rtl_dump_file) if (rtl_dump_file)
...@@ -216,20 +315,18 @@ regrename_optimize () ...@@ -216,20 +315,18 @@ regrename_optimize ()
fprintf (rtl_dump_file, " crosses a call"); fprintf (rtl_dump_file, " crosses a call");
} }
if (treg == FIRST_PSEUDO_REGISTER) if (best_new_reg == -1)
{ {
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, "; no available registers\n"); fprintf (rtl_dump_file, "; no available registers\n");
continue; continue;
} }
do_replace (this, best_new_reg);
for (i = nregs - 1; i >= 0; --i) tick[best_new_reg] = this_tick++;
SET_HARD_REG_BIT (unavailable, treg+i);
do_replace (this, treg);
if (rtl_dump_file) if (rtl_dump_file)
fprintf (rtl_dump_file, ", renamed as %s\n", reg_names[treg]); fprintf (rtl_dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
} }
obstack_free (&rename_obstack, first_obj); obstack_free (&rename_obstack, first_obj);
...@@ -258,17 +355,17 @@ do_replace (chain, reg) ...@@ -258,17 +355,17 @@ do_replace (chain, reg)
} }
static HARD_REG_SET *referenced_regs;
static struct du_chain *open_chains; static struct du_chain *open_chains;
static struct du_chain *closed_chains; static struct du_chain *closed_chains;
static void static void
scan_rtx_reg (insn, loc, class, action, type) scan_rtx_reg (insn, loc, class, action, type, earlyclobber)
rtx insn; rtx insn;
rtx *loc; rtx *loc;
enum reg_class class; enum reg_class class;
enum scan_actions action; enum scan_actions action;
enum op_type type; enum op_type type;
int earlyclobber;
{ {
struct du_chain **p; struct du_chain **p;
rtx x = *loc; rtx x = *loc;
...@@ -276,13 +373,6 @@ scan_rtx_reg (insn, loc, class, action, type) ...@@ -276,13 +373,6 @@ scan_rtx_reg (insn, loc, class, action, type)
int this_regno = REGNO (x); int this_regno = REGNO (x);
int this_nregs = HARD_REGNO_NREGS (this_regno, mode); int this_nregs = HARD_REGNO_NREGS (this_regno, mode);
if (action == note_reference)
{
while (this_nregs-- > 0)
SET_HARD_REG_BIT (*referenced_regs, this_regno + this_nregs);
return;
}
if (action == mark_write) if (action == mark_write)
{ {
if (type == OP_OUT) if (type == OP_OUT)
...@@ -295,6 +385,7 @@ scan_rtx_reg (insn, loc, class, action, type) ...@@ -295,6 +385,7 @@ scan_rtx_reg (insn, loc, class, action, type)
this->insn = insn; this->insn = insn;
this->class = class; this->class = class;
this->need_caller_save_reg = 0; this->need_caller_save_reg = 0;
this->earlyclobber = earlyclobber;
open_chains = this; open_chains = this;
} }
return; return;
...@@ -343,12 +434,14 @@ scan_rtx_reg (insn, loc, class, action, type) ...@@ -343,12 +434,14 @@ scan_rtx_reg (insn, loc, class, action, type)
{ {
this = (struct du_chain *) this = (struct du_chain *)
obstack_alloc (&rename_obstack, sizeof (struct du_chain)); obstack_alloc (&rename_obstack, sizeof (struct du_chain));
this->next_use = *p; this->next_use = 0;
this->next_chain = (*p)->next_chain; this->next_chain = (*p)->next_chain;
this->loc = loc; this->loc = loc;
this->insn = insn; this->insn = insn;
this->class = class; this->class = class;
this->need_caller_save_reg = 0; this->need_caller_save_reg = 0;
while (*p)
p = &(*p)->next_use;
*p = this; *p = this;
return; return;
} }
...@@ -510,7 +603,7 @@ scan_rtx_address (insn, loc, class, action, mode) ...@@ -510,7 +603,7 @@ scan_rtx_address (insn, loc, class, action, mode)
return; return;
case REG: case REG:
scan_rtx_reg (insn, loc, class, action, OP_IN); scan_rtx_reg (insn, loc, class, action, OP_IN, 0);
return; return;
default: default:
...@@ -529,12 +622,13 @@ scan_rtx_address (insn, loc, class, action, mode) ...@@ -529,12 +622,13 @@ scan_rtx_address (insn, loc, class, action, mode)
} }
static void static void
scan_rtx (insn, loc, class, action, type) scan_rtx (insn, loc, class, action, type, earlyclobber)
rtx insn; rtx insn;
rtx *loc; rtx *loc;
enum reg_class class; enum reg_class class;
enum scan_actions action; enum scan_actions action;
enum op_type type; enum op_type type;
int earlyclobber;
{ {
const char *fmt; const char *fmt;
rtx x = *loc; rtx x = *loc;
...@@ -554,7 +648,7 @@ scan_rtx (insn, loc, class, action, type) ...@@ -554,7 +648,7 @@ scan_rtx (insn, loc, class, action, type)
return; return;
case REG: case REG:
scan_rtx_reg (insn, loc, class, action, type); scan_rtx_reg (insn, loc, class, action, type, earlyclobber);
return; return;
case MEM: case MEM:
...@@ -563,20 +657,20 @@ scan_rtx (insn, loc, class, action, type) ...@@ -563,20 +657,20 @@ scan_rtx (insn, loc, class, action, type)
return; return;
case SET: case SET:
scan_rtx (insn, &SET_SRC (x), class, action, OP_IN); scan_rtx (insn, &SET_SRC (x), class, action, OP_IN, 0);
scan_rtx (insn, &SET_DEST (x), class, action, OP_OUT); scan_rtx (insn, &SET_DEST (x), class, action, OP_OUT, 0);
return; return;
case STRICT_LOW_PART: case STRICT_LOW_PART:
scan_rtx (insn, &XEXP (x, 0), class, action, OP_INOUT); scan_rtx (insn, &XEXP (x, 0), class, action, OP_INOUT, earlyclobber);
return; return;
case ZERO_EXTRACT: case ZERO_EXTRACT:
case SIGN_EXTRACT: case SIGN_EXTRACT:
scan_rtx (insn, &XEXP (x, 0), class, action, scan_rtx (insn, &XEXP (x, 0), class, action,
type == OP_IN ? OP_IN : OP_INOUT); type == OP_IN ? OP_IN : OP_INOUT, earlyclobber);
scan_rtx (insn, &XEXP (x, 1), class, action, OP_IN); scan_rtx (insn, &XEXP (x, 1), class, action, OP_IN, 0);
scan_rtx (insn, &XEXP (x, 2), class, action, OP_IN); scan_rtx (insn, &XEXP (x, 2), class, action, OP_IN, 0);
return; return;
case POST_INC: case POST_INC:
...@@ -589,13 +683,13 @@ scan_rtx (insn, loc, class, action, type) ...@@ -589,13 +683,13 @@ scan_rtx (insn, loc, class, action, type)
abort (); abort ();
case CLOBBER: case CLOBBER:
scan_rtx (insn, &SET_DEST (x), class, action, OP_OUT); scan_rtx (insn, &SET_DEST (x), class, action, OP_OUT, 1);
return; return;
case EXPR_LIST: case EXPR_LIST:
scan_rtx (insn, &XEXP (x, 0), class, action, type); scan_rtx (insn, &XEXP (x, 0), class, action, type, 0);
if (XEXP (x, 1)) if (XEXP (x, 1))
scan_rtx (insn, &XEXP (x, 1), class, action, type); scan_rtx (insn, &XEXP (x, 1), class, action, type, 0);
return; return;
default: default:
...@@ -606,24 +700,22 @@ scan_rtx (insn, loc, class, action, type) ...@@ -606,24 +700,22 @@ scan_rtx (insn, loc, class, action, type)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
scan_rtx (insn, &XEXP (x, i), class, action, type); scan_rtx (insn, &XEXP (x, i), class, action, type, 0);
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--) for (j = XVECLEN (x, i) - 1; j >= 0; j--)
scan_rtx (insn, &XVECEXP (x, i, j), class, action, type); scan_rtx (insn, &XVECEXP (x, i, j), class, action, type, 0);
} }
} }
/* Build def/use chain */ /* Build def/use chain */
static struct du_chain * static struct du_chain *
build_def_use (bb, regs_used) build_def_use (bb)
basic_block bb; basic_block bb;
HARD_REG_SET *regs_used;
{ {
rtx insn; rtx insn;
open_chains = closed_chains = NULL; open_chains = closed_chains = NULL;
referenced_regs = regs_used;
for (insn = bb->head; ; insn = NEXT_INSN (insn)) for (insn = bb->head; ; insn = NEXT_INSN (insn))
{ {
...@@ -637,9 +729,6 @@ build_def_use (bb, regs_used) ...@@ -637,9 +729,6 @@ build_def_use (bb, regs_used)
int alt; int alt;
int predicated; int predicated;
/* Record all mentioned registers in regs_used. */
scan_rtx (insn, &PATTERN (insn), NO_REGS, note_reference, OP_IN);
/* Process the insn, determining its effect on the def-use /* Process the insn, determining its effect on the def-use
chains. We perform the following steps with the register chains. We perform the following steps with the register
references in the insn: references in the insn:
...@@ -681,7 +770,7 @@ build_def_use (bb, regs_used) ...@@ -681,7 +770,7 @@ build_def_use (bb, regs_used)
for (i = 0; i < n_ops; i++) for (i = 0; i < n_ops; i++)
scan_rtx (insn, recog_data.operand_loc[i], scan_rtx (insn, recog_data.operand_loc[i],
NO_REGS, terminate_overlapping_read, NO_REGS, terminate_overlapping_read,
recog_data.operand_type[i]); recog_data.operand_type[i], 0);
/* Step 2: Close chains for which we have reads outside operands. /* Step 2: Close chains for which we have reads outside operands.
We do this by munging all operands into CC0, and closing We do this by munging all operands into CC0, and closing
...@@ -703,7 +792,8 @@ build_def_use (bb, regs_used) ...@@ -703,7 +792,8 @@ build_def_use (bb, regs_used)
*recog_data.dup_loc[i] = cc0_rtx; *recog_data.dup_loc[i] = cc0_rtx;
} }
scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read, OP_IN); scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
OP_IN, 0);
for (i = 0; i < recog_data.n_dups; i++) for (i = 0; i < recog_data.n_dups; i++)
*recog_data.dup_loc[i] = old_dups[i]; *recog_data.dup_loc[i] = old_dups[i];
...@@ -713,7 +803,7 @@ build_def_use (bb, regs_used) ...@@ -713,7 +803,7 @@ build_def_use (bb, regs_used)
/* Step 2B: Can't rename function call argument registers. */ /* Step 2B: Can't rename function call argument registers. */
if (GET_CODE (insn) == CALL_INSN && CALL_INSN_FUNCTION_USAGE (insn)) if (GET_CODE (insn) == CALL_INSN && CALL_INSN_FUNCTION_USAGE (insn))
scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn), scan_rtx (insn, &CALL_INSN_FUNCTION_USAGE (insn),
NO_REGS, terminate_all_read, OP_IN); NO_REGS, terminate_all_read, OP_IN, 0);
/* Step 3: Append to chains for reads inside operands. */ /* Step 3: Append to chains for reads inside operands. */
for (i = 0; i < n_ops + recog_data.n_dups; i++) for (i = 0; i < n_ops + recog_data.n_dups; i++)
...@@ -734,7 +824,7 @@ build_def_use (bb, regs_used) ...@@ -734,7 +824,7 @@ build_def_use (bb, regs_used)
if (recog_op_alt[opn][alt].is_address) if (recog_op_alt[opn][alt].is_address)
scan_rtx_address (insn, loc, class, mark_read, VOIDmode); scan_rtx_address (insn, loc, class, mark_read, VOIDmode);
else else
scan_rtx (insn, loc, class, mark_read, type); scan_rtx (insn, loc, class, mark_read, type, 0);
} }
/* Step 4: Close chains for registers that die here. /* Step 4: Close chains for registers that die here.
...@@ -742,9 +832,11 @@ build_def_use (bb, regs_used) ...@@ -742,9 +832,11 @@ build_def_use (bb, regs_used)
for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
{ {
if (REG_NOTE_KIND (note) == REG_DEAD) if (REG_NOTE_KIND (note) == REG_DEAD)
scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead, OP_IN); scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
OP_IN, 0);
else if (REG_NOTE_KIND (note) == REG_INC) else if (REG_NOTE_KIND (note) == REG_INC)
scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read, OP_INOUT); scan_rtx (insn, &XEXP (note, 0), ALL_REGS, mark_read,
OP_INOUT, 0);
} }
/* Step 4B: If this is a call, any chain live at this point /* Step 4B: If this is a call, any chain live at this point
...@@ -753,12 +845,7 @@ build_def_use (bb, regs_used) ...@@ -753,12 +845,7 @@ build_def_use (bb, regs_used)
{ {
struct du_chain *p; struct du_chain *p;
for (p = open_chains; p; p = p->next_chain) for (p = open_chains; p; p = p->next_chain)
{ p->need_caller_save_reg = 1;
struct du_chain *p2;
for (p2 = p; p2->next_use; p2 = p2->next_use)
/* nothing */;
p2->need_caller_save_reg = 1;
}
} }
/* Step 5: Close open chains that overlap writes. Similar to /* Step 5: Close open chains that overlap writes. Similar to
...@@ -779,7 +866,7 @@ build_def_use (bb, regs_used) ...@@ -779,7 +866,7 @@ build_def_use (bb, regs_used)
*recog_data.dup_loc[i] = cc0_rtx; *recog_data.dup_loc[i] = cc0_rtx;
} }
scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN); scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN, 0);
for (i = 0; i < recog_data.n_dups; i++) for (i = 0; i < recog_data.n_dups; i++)
*recog_data.dup_loc[i] = old_dups[i]; *recog_data.dup_loc[i] = old_dups[i];
...@@ -800,14 +887,16 @@ build_def_use (bb, regs_used) ...@@ -800,14 +887,16 @@ build_def_use (bb, regs_used)
enum reg_class class = recog_op_alt[opn][alt].class; enum reg_class class = recog_op_alt[opn][alt].class;
if (recog_data.operand_type[opn] == OP_OUT) if (recog_data.operand_type[opn] == OP_OUT)
scan_rtx (insn, loc, class, mark_write, OP_OUT); scan_rtx (insn, loc, class, mark_write, OP_OUT,
recog_op_alt[opn][alt].earlyclobber);
} }
/* Step 7: Close chains for registers that were never /* Step 7: Close chains for registers that were never
really used here. */ really used here. */
for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_UNUSED) if (REG_NOTE_KIND (note) == REG_UNUSED)
scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead, OP_IN); scan_rtx (insn, &XEXP (note, 0), NO_REGS, terminate_dead,
OP_IN, 0);
} }
if (insn == bb->end) if (insn == bb->end)
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment