rtlanal.c (parms_set, [...]): Break out from...; handle multiple sets.
* rtlanal.c (parms_set, find_first_parameter_load): Break out from...; handle multiple sets. * except.c (sjlj_mark_call_sites): .... here. * gcse.c (insert_insn_end_bb): Use find_first_parameter_load. From-SVN: r44465
This commit is contained in:
parent
b5832b4372
commit
833366d6c9
5 changed files with 84 additions and 76 deletions
|
@ -1,3 +1,10 @@
|
|||
Sun Jul 29 23:26:50 CEST 2001 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* rtlanal.c (parms_set, find_first_parameter_load): Break out from...;
|
||||
handle multiple sets.
|
||||
* except.c (sjlj_mark_call_sites): .... here.
|
||||
* gcse.c (insert_insn_end_bb): Use find_first_parameter_load.
|
||||
|
||||
Sun Jul 29 21:38:45 CEST 2001 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
Suggested by Richard Henderson and Richard Kenner:
|
||||
|
|
46
gcc/except.c
46
gcc/except.c
|
@ -2083,51 +2083,7 @@ sjlj_mark_call_sites (lp_info)
|
|||
/* Don't separate a call from it's argument loads. */
|
||||
before = insn;
|
||||
if (GET_CODE (insn) == CALL_INSN)
|
||||
{
|
||||
HARD_REG_SET parm_regs;
|
||||
int nparm_regs;
|
||||
|
||||
/* Since different machines initialize their parameter registers
|
||||
in different orders, assume nothing. Collect the set of all
|
||||
parameter registers. */
|
||||
CLEAR_HARD_REG_SET (parm_regs);
|
||||
nparm_regs = 0;
|
||||
for (p = CALL_INSN_FUNCTION_USAGE (insn); p ; p = XEXP (p, 1))
|
||||
if (GET_CODE (XEXP (p, 0)) == USE
|
||||
&& GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
|
||||
{
|
||||
if (REGNO (XEXP (XEXP (p, 0), 0)) >= FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
|
||||
/* We only care about registers which can hold function
|
||||
arguments. */
|
||||
if (! FUNCTION_ARG_REGNO_P (REGNO (XEXP (XEXP (p, 0), 0))))
|
||||
continue;
|
||||
|
||||
SET_HARD_REG_BIT (parm_regs, REGNO (XEXP (XEXP (p, 0), 0)));
|
||||
nparm_regs++;
|
||||
}
|
||||
|
||||
/* Search backward for the first set of a register in this set. */
|
||||
while (nparm_regs)
|
||||
{
|
||||
before = PREV_INSN (before);
|
||||
|
||||
/* Given that we've done no other optimizations yet,
|
||||
the arguments should be immediately available. */
|
||||
if (GET_CODE (before) == CODE_LABEL)
|
||||
abort ();
|
||||
|
||||
p = single_set (before);
|
||||
if (p && GET_CODE (SET_DEST (p)) == REG
|
||||
&& REGNO (SET_DEST (p)) < FIRST_PSEUDO_REGISTER
|
||||
&& TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))))
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)));
|
||||
nparm_regs--;
|
||||
}
|
||||
}
|
||||
}
|
||||
before = find_first_parameter_load (insn, NULL_RTX);
|
||||
|
||||
start_sequence ();
|
||||
emit_move_insn (mem, GEN_INT (this_call_site));
|
||||
|
|
32
gcc/gcse.c
32
gcc/gcse.c
|
@ -4649,38 +4649,8 @@ insert_insn_end_bb (expr, bb, pre)
|
|||
/* Since different machines initialize their parameter registers
|
||||
in different orders, assume nothing. Collect the set of all
|
||||
parameter registers. */
|
||||
CLEAR_HARD_REG_SET (parm_regs);
|
||||
nparm_regs = 0;
|
||||
for (p = CALL_INSN_FUNCTION_USAGE (insn); p ; p = XEXP (p, 1))
|
||||
if (GET_CODE (XEXP (p, 0)) == USE
|
||||
&& GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
|
||||
{
|
||||
if (REGNO (XEXP (XEXP (p, 0), 0)) >= FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
insn = find_first_parameter_load (insn, bb->head);
|
||||
|
||||
/* We only care about registers which can hold function
|
||||
arguments. */
|
||||
if (! FUNCTION_ARG_REGNO_P (REGNO (XEXP (XEXP (p, 0), 0))))
|
||||
continue;
|
||||
|
||||
SET_HARD_REG_BIT (parm_regs, REGNO (XEXP (XEXP (p, 0), 0)));
|
||||
nparm_regs++;
|
||||
}
|
||||
|
||||
/* Search backward for the first set of a register in this set. */
|
||||
while (nparm_regs && bb->head != insn)
|
||||
{
|
||||
insn = PREV_INSN (insn);
|
||||
p = single_set (insn);
|
||||
if (p && GET_CODE (SET_DEST (p)) == REG
|
||||
&& REGNO (SET_DEST (p)) < FIRST_PSEUDO_REGISTER
|
||||
&& TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))))
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)));
|
||||
nparm_regs--;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we found all the parameter loads, then we want to insert
|
||||
before the first parameter load.
|
||||
|
||||
|
|
|
@ -1432,6 +1432,7 @@ extern int auto_inc_p PARAMS ((rtx));
|
|||
extern void remove_node_from_expr_list PARAMS ((rtx, rtx *));
|
||||
extern int insns_safe_to_move_p PARAMS ((rtx, rtx, rtx *));
|
||||
extern int loc_mentioned_in_p PARAMS ((rtx *, rtx));
|
||||
extern rtx find_first_parameter_load PARAMS ((rtx, rtx));
|
||||
|
||||
/* flow.c */
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ static void set_of_1 PARAMS ((rtx, rtx, void *));
|
|||
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
|
||||
static int computed_jump_p_1 PARAMS ((rtx));
|
||||
static int operand_preference PARAMS ((rtx));
|
||||
static void parms_set PARAMS ((rtx, rtx, void *));
|
||||
|
||||
/* Bit flags that specify the machine subtype we are compiling for.
|
||||
Bits are tested using macros TARGET_... defined in the tm.h file
|
||||
|
@ -2788,3 +2789,76 @@ subreg_regno (x)
|
|||
return ret;
|
||||
|
||||
}
|
||||
struct parms_set_data
|
||||
{
|
||||
int nregs;
|
||||
HARD_REG_SET regs;
|
||||
};
|
||||
|
||||
/* Helper function for noticing stores to parameter registers. */
|
||||
static void
|
||||
parms_set (x, pat, data)
|
||||
rtx x, pat ATTRIBUTE_UNUSED;
|
||||
void *data;
|
||||
{
|
||||
struct parms_set_data *d = data;
|
||||
if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER
|
||||
&& TEST_HARD_REG_BIT (d->regs, REGNO (x)))
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (d->regs, REGNO (x));
|
||||
d->nregs--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look backward for first parameter to be loaded.
|
||||
Do not skip BOUNDARY. */
|
||||
rtx
|
||||
find_first_parameter_load (call_insn, boundary)
|
||||
rtx call_insn, boundary;
|
||||
{
|
||||
struct parms_set_data parm;
|
||||
rtx p, before;
|
||||
|
||||
/* Since different machines initialize their parameter registers
|
||||
in different orders, assume nothing. Collect the set of all
|
||||
parameter registers. */
|
||||
CLEAR_HARD_REG_SET (parm.regs);
|
||||
parm.nregs = 0;
|
||||
for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1))
|
||||
if (GET_CODE (XEXP (p, 0)) == USE
|
||||
&& GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
|
||||
{
|
||||
if (REGNO (XEXP (XEXP (p, 0), 0)) >= FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
|
||||
/* We only care about registers which can hold function
|
||||
arguments. */
|
||||
if (!FUNCTION_ARG_REGNO_P (REGNO (XEXP (XEXP (p, 0), 0))))
|
||||
continue;
|
||||
|
||||
SET_HARD_REG_BIT (parm.regs, REGNO (XEXP (XEXP (p, 0), 0)));
|
||||
parm.nregs++;
|
||||
}
|
||||
before = call_insn;
|
||||
|
||||
/* Search backward for the first set of a register in this set. */
|
||||
while (parm.nregs && before != boundary)
|
||||
{
|
||||
before = PREV_INSN (before);
|
||||
|
||||
/* It is possible that some loads got CSEed from one call to
|
||||
another. Stop in that case. */
|
||||
if (GET_CODE (before) == CALL_INSN)
|
||||
break;
|
||||
|
||||
/* Our caller needs eighter ensure, that we will find all sets
|
||||
(in case code has not been optimized yet), or take care
|
||||
for possible labels in a way by setting boundary to preceeding
|
||||
CODE_LABEL. */
|
||||
if (GET_CODE (before) == CODE_LABEL && before != boundary)
|
||||
abort ();
|
||||
|
||||
note_stores (PATTERN (before), parms_set, &parm);
|
||||
}
|
||||
return before;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue