summaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1993-09-06 17:27:22 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1993-09-06 17:27:22 +0000
commit2c18b47c7ca72ecf66a0c1495c966337f406b1c1 (patch)
tree7cf17357ba91b8735d3dfb33067ac90aa301c828 /gcc/rtlanal.c
parentd21e4486fe476c46a2e6b996a1c371ede1626941 (diff)
downloadgcc-2c18b47c7ca72ecf66a0c1495c966337f406b1c1.tar.gz
(modified_between_p): Handle vectors.
(modified_in_p): New function. (refers_to_regno_p): If setting AP, FP, or SP, we clobber the virtual registers. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@5267 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r--gcc/rtlanal.c78
1 files changed, 74 insertions, 4 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 549f9054f6e..82ac3afd3df 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1,5 +1,5 @@
/* Analyze RTL for C-Compiler
- Copyright (C) 1987, 1988, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1992, 1993 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -472,7 +472,7 @@ modified_between_p (x, start, end)
{
enum rtx_code code = GET_CODE (x);
char *fmt;
- int i;
+ int i, j;
switch (code)
{
@@ -500,10 +500,68 @@ modified_between_p (x, start, end)
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e'
- && modified_between_p (XEXP (x, i), start, end))
+ {
+ if (fmt[i] == 'e' && modified_between_p (XEXP (x, i), start, end))
+ return 1;
+
+ if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (modified_between_p (XVECEXP (x, i, j), start, end))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Similar to reg_set_p, but check all registers in X. Return 0 only if none
+ of them are modified in INSN. Return 1 if X contains a MEM; this routine
+ does not perform any memory aliasing. */
+
+int
+modified_in_p (x, insn)
+ rtx x;
+ rtx insn;
+{
+ enum rtx_code code = GET_CODE (x);
+ char *fmt;
+ int i, j;
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 0;
+
+ case PC:
+ case CC0:
return 1;
+ case MEM:
+ /* If the memory is not constant, assume it is modified. If it is
+ constant, we still have to check the address. */
+ if (! RTX_UNCHANGING_P (x))
+ return 1;
+ break;
+
+ case REG:
+ return reg_set_p (x, insn);
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e' && modified_in_p (XEXP (x, i), insn))
+ return 1;
+
+ if (fmt[i] == 'E')
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (modified_in_p (XVECEXP (x, i, j), insn))
+ return 1;
+ }
+
return 0;
}
@@ -618,6 +676,18 @@ refers_to_regno_p (regno, endregno, x, loc)
{
case REG:
i = REGNO (x);
+
+ /* If we modifying the stack, frame, or argument pointer, it will
+ clobber a virtual register. In fact, we could be more precise,
+ but it isn't worth it. */
+ if ((i == STACK_POINTER_REGNUM
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ || i == ARG_POINTER_REGNUM
+#endif
+ || i == FRAME_POINTER_REGNUM)
+ && regno >= FIRST_VIRTUAL_REGISTER && regno <= LAST_VIRTUAL_REGISTER)
+ return 1;
+
return (endregno > i
&& regno < i + (i < FIRST_PSEUDO_REGISTER
? HARD_REGNO_NREGS (i, GET_MODE (x))