aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-07-29 23:28:42 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2001-07-29 21:28:42 +0000
commit833366d6c90ddcb12ec0b7d63b6e57fd3b0f5793 (patch)
tree3c01d1ea251b427b8df8b3e9d0756203c265d556 /gcc/rtlanal.c
parentb5832b43726d2d44b202c7a5669b3e97a2bc60c2 (diff)
downloadgcc-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.c74
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;
+}