* recog.c (validate_replace_src_1): New.
(validate_replace_src_data): Likewise.
(validate_replace_src): Use note_uses.
* rtl.h (note_uses): Declare.
* rtlanal.c (note_uses): New.
Co-Authored-By: Jan Hubicka <jh@suse.cz>
From-SVN: r39804
+Sat Feb 17 14:48:30 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ Jan Hubicka <jh@suse.cz>
+
+ * recog.c (validate_replace_src_1): New.
+ (validate_replace_src_data): Likewise.
+ (validate_replace_src): Use note_uses.
+ * rtl.h (note_uses): Declare.
+ * rtlanal.c (note_uses): New.
+
Sat Feb 17 10:52:34 CET 2001 Jan Hubicka <jh@suse.cz>
* reg-stack.c (stack_def): Make field reg unsigned.
/* Subroutines used by or related to instruction recognition.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
static rtx *find_single_use_1 PARAMS ((rtx, rtx *));
static rtx *find_constant_term_loc PARAMS ((rtx *));
static int insn_invalid_p PARAMS ((rtx));
+static void validate_replace_src_1 PARAMS ((rtx *, void *));
/* Nonzero means allow operands to be volatile.
This should be 0 if you are generating rtl, such as if you are calling
validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
}
+/* Function called by note_uses to replace used subexpressions. */
+struct validate_replace_src_data
+ {
+ rtx from, to, insn;
+ };
+
+static void
+validate_replace_src_1 (x, data)
+ rtx *x;
+ void *data;
+{
+ struct validate_replace_src_data *d
+ = (struct validate_replace_src_data *) data;
+
+ validate_replace_rtx_1 (x, d->from, d->to, d->insn);
+}
+
/* Try replacing every occurrence of FROM in INSN with TO, avoiding
SET_DESTs. After all changes have been made, validate by seeing if
INSN is still valid. */
validate_replace_src (from, to, insn)
rtx from, to, insn;
{
- if ((GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
- || GET_CODE (PATTERN (insn)) != SET)
- abort ();
-
- validate_replace_rtx_1 (&SET_SRC (PATTERN (insn)), from, to, insn);
- if (GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
- validate_replace_rtx_1 (&XEXP (SET_DEST (PATTERN (insn)), 0),
- from, to, insn);
- else if (GET_CODE (SET_DEST (PATTERN (insn))) == ZERO_EXTRACT)
- {
- validate_replace_rtx_1 (&XEXP (SET_DEST (PATTERN (insn)), 1),
- from, to, insn);
- validate_replace_rtx_1 (&XEXP (SET_DEST (PATTERN (insn)), 2),
- from, to, insn);
- }
+ struct validate_replace_src_data d;
+ d.from = from;
+ d.to = to;
+ d.insn = insn;
+ note_uses (&PATTERN (insn), validate_replace_src_1, &d);
return apply_change_group ();
}
\f
extern void note_stores PARAMS ((rtx,
void (*) (rtx, rtx, void *),
void *));
+extern void note_uses PARAMS ((rtx *,
+ void (*) (rtx *, void *),
+ void *));
extern rtx reg_set_last PARAMS ((rtx, rtx));
extern int dead_or_set_p PARAMS ((rtx, rtx));
extern int dead_or_set_regno_p PARAMS ((rtx, unsigned int));
#include "toplev.h"
#include "rtl.h"
+/* Forward declarations */
static void set_of_1 PARAMS ((rtx, rtx, void *));
static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
-
-/* Forward declarations */
static int computed_jump_p_1 PARAMS ((rtx));
/* Bit flags that specify the machine subtype we are compiling for.
note_stores (XVECEXP (x, 0, i), fun, data);
}
\f
+/* Like notes_stores, but call FUN for each expression that is being
+ referenced in PBODY, a pointer to the PATTERN of an insn. We only call
+ FUN for each expression, not any interior subexpressions. FUN receives a
+ pointer to the expression and the DATA passed to this function.
+
+ Note that this is not quite the same test as that done in reg_referenced_p
+ since that considers something as being referenced if it is being
+ partially set, while we do not. */
+
+void
+note_uses (pbody, fun, data)
+ rtx *pbody;
+ void (*fun) PARAMS ((rtx *, void *));
+ void *data;
+{
+ rtx body = *pbody;
+ int i;
+
+ switch (GET_CODE (body))
+ {
+ case COND_EXEC:
+ (*fun) (&COND_EXEC_TEST (body), data);
+ note_uses (&COND_EXEC_CODE (body), fun, data);
+ return;
+
+ case PARALLEL:
+ for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
+ note_uses (&XVECEXP (body, 0, i), fun, data);
+ return;
+
+ case USE:
+ (*fun) (&XEXP (body, 0), data);
+ return;
+
+ case ASM_OPERANDS:
+ for (i = ASM_OPERANDS_INPUT_LENGTH (body) - 1; i >= 0; i--)
+ (*fun) (&ASM_OPERANDS_INPUT (body, i), data);
+ return;
+
+ case TRAP_IF:
+ (*fun) (&TRAP_CONDITION (body), data);
+ return;
+
+ case UNSPEC:
+ case UNSPEC_VOLATILE:
+ for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
+ (*fun) (&XVECEXP (body, 0, i), data);
+ return;
+
+ case CLOBBER:
+ if (GET_CODE (XEXP (body, 0)) == MEM)
+ (*fun) (&XEXP (XEXP (body, 0), 0), data);
+ return;
+
+ case SET:
+ {
+ rtx dest = SET_DEST (body);
+
+ /* For sets we replace everything in source plus registers in memory
+ expression in store and operands of a ZERO_EXTRACT. */
+ (*fun) (&SET_SRC (body), data);
+
+ if (GET_CODE (dest) == ZERO_EXTRACT)
+ {
+ (*fun) (&XEXP (dest, 1), data);
+ (*fun) (&XEXP (dest, 2), data);
+ }
+
+ while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+
+ if (GET_CODE (dest) == MEM)
+ (*fun) (&XEXP (dest, 0), data);
+ }
+ return;
+
+ default:
+ /* All the other possibilities never store. */
+ (*fun) (pbody, data);
+ return;
+ }
+}
+\f
/* Return nonzero if X's old contents don't survive after INSN.
This will be true if X is (cc0) or if X is a register and
X dies in INSN or because INSN entirely sets X.