diff options
author | Jan Hubicka <jh@suse.cz> | 2001-07-29 23:28:42 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2001-07-29 21:28:42 +0000 |
commit | 833366d6c90ddcb12ec0b7d63b6e57fd3b0f5793 (patch) | |
tree | 3c01d1ea251b427b8df8b3e9d0756203c265d556 /gcc/rtlanal.c | |
parent | b5832b43726d2d44b202c7a5669b3e97a2bc60c2 (diff) | |
download | gcc-833366d6c90ddcb12ec0b7d63b6e57fd3b0f5793.zip gcc-833366d6c90ddcb12ec0b7d63b6e57fd3b0f5793.tar.gz gcc-833366d6c90ddcb12ec0b7d63b6e57fd3b0f5793.tar.bz2 |
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
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r-- | gcc/rtlanal.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 92220f6..9762f9e 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.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; +} |