summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/rtlanal.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
committerobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
commit0bedf4fb30066e5e1d4342a1d3914dae7d37cba7 (patch)
tree68d8110b41afd0ebbf39167b1a4918eea667a7c5 /contrib/gcc/rtlanal.c
parentd4db5fb866b7ad5216abd5047774a3973b9901a9 (diff)
downloadFreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.zip
FreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.tar.gz
Virgin import of gcc from EGCS 1.1.2
Diffstat (limited to 'contrib/gcc/rtlanal.c')
-rw-r--r--contrib/gcc/rtlanal.c235
1 files changed, 206 insertions, 29 deletions
diff --git a/contrib/gcc/rtlanal.c b/contrib/gcc/rtlanal.c
index 17cfd36..221b3fa 100644
--- a/contrib/gcc/rtlanal.c
+++ b/contrib/gcc/rtlanal.c
@@ -1,5 +1,5 @@
/* Analyze RTL for C-Compiler
- Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,10 +20,16 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include "system.h"
#include "rtl.h"
-void note_stores ();
-int reg_set_p ();
+static int rtx_addr_can_trap_p PROTO((rtx));
+static void reg_set_p_1 PROTO((rtx, rtx));
+static void reg_set_last_1 PROTO((rtx, rtx));
+
+
+/* Forward declarations */
+static int jmp_uses_reg_or_mem PROTO((rtx));
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
@@ -99,12 +105,15 @@ rtx_varies_p (x)
eliminated the frame and/or arg pointer and are using it
for pseudos. */
return ! (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
- || x == arg_pointer_rtx);
+ || x == arg_pointer_rtx || x == pic_offset_table_rtx);
case LO_SUM:
/* The operand 0 of a LO_SUM is considered constant
(in fact is it related specifically to operand 1). */
return rtx_varies_p (XEXP (x, 1));
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -117,7 +126,7 @@ rtx_varies_p (x)
/* Return 0 if the use of X as an address in a MEM can cause a trap. */
-int
+static int
rtx_addr_can_trap_p (x)
register rtx x;
{
@@ -149,6 +158,9 @@ rtx_addr_can_trap_p (x)
case LO_SUM:
return rtx_addr_can_trap_p (XEXP (x, 1));
+
+ default:
+ break;
}
/* If it isn't one of the case above, it can cause a trap. */
@@ -177,8 +189,17 @@ rtx_addr_varies_p (x)
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e')
- if (rtx_addr_varies_p (XEXP (x, i)))
- return 1;
+ {
+ if (rtx_addr_varies_p (XEXP (x, i)))
+ return 1;
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (rtx_addr_varies_p (XVECEXP (x, i, j)))
+ return 1;
+ }
return 0;
}
@@ -265,6 +286,9 @@ reg_mentioned_p (reg, in)
case CONST_DOUBLE:
/* These are kept unique for a given value. */
return 0;
+
+ default:
+ break;
}
if (GET_CODE (reg) == code && rtx_equal_p (reg, in))
@@ -355,13 +379,13 @@ reg_referenced_p (x, body)
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
&& reg_overlap_mentioned_p (x, SET_DEST (body)))
return 1;
- break;
+ return 0;
case ASM_OPERANDS:
for (i = ASM_OPERANDS_INPUT_LENGTH (body) - 1; i >= 0; i--)
if (reg_overlap_mentioned_p (x, ASM_OPERANDS_INPUT (body, i)))
return 1;
- break;
+ return 0;
case CALL:
case USE:
@@ -376,15 +400,16 @@ reg_referenced_p (x, body)
for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
if (reg_referenced_p (x, XVECEXP (body, 0, i)))
return 1;
- break;
+ return 0;
+
+ default:
+ return 0;
}
-
- return 0;
}
/* Nonzero if register REG is referenced in an insn between
FROM_INSN and TO_INSN (exclusive of those two). Sets of REG do
- not count. */
+ not count. */
int
reg_referenced_between_p (reg, from_insn, to_insn)
@@ -431,6 +456,7 @@ static int reg_set_flag;
static void
reg_set_p_1 (x, pat)
rtx x;
+ rtx pat ATTRIBUTE_UNUSED;
{
/* We don't want to return 1 if X is a MEM that contains a register
within REG_SET_REG. */
@@ -508,6 +534,9 @@ modified_between_p (x, start, end)
case REG:
return reg_set_between_p (x, start, end);
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -560,6 +589,9 @@ modified_in_p (x, insn)
case REG:
return reg_set_p (x, insn);
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -740,6 +772,9 @@ refers_to_regno_p (regno, endregno, x, loc)
return 0;
x = SET_SRC (x);
goto repeat;
+
+ default:
+ break;
}
/* X does not match, so try its subexpressions. */
@@ -782,7 +817,14 @@ reg_overlap_mentioned_p (x, in)
{
int regno, endregno;
- if (GET_CODE (x) == SUBREG)
+ /* Overly conservative. */
+ if (GET_CODE (x) == STRICT_LOW_PART)
+ x = XEXP (x, 0);
+
+ /* If either argument is a constant, then modifying X can not affect IN. */
+ if (CONSTANT_P (x) || CONSTANT_P (in))
+ return 0;
+ else if (GET_CODE (x) == SUBREG)
{
regno = REGNO (SUBREG_REG (x));
if (regno < FIRST_PSEUDO_REGISTER)
@@ -790,8 +832,6 @@ reg_overlap_mentioned_p (x, in)
}
else if (GET_CODE (x) == REG)
regno = REGNO (x);
- else if (CONSTANT_P (x))
- return 0;
else if (GET_CODE (x) == MEM)
{
char *fmt;
@@ -915,7 +955,7 @@ reg_set_last (x, insn)
return 0;
}
-/* This is 1 until after reload pass. */
+/* This is 1 until after the rtl generation pass. */
int rtx_equal_function_value_matters;
/* Return 1 if X and Y are identical-looking rtx's.
@@ -1125,19 +1165,30 @@ dead_or_set_regno_p (insn, test_regno)
int regno, endregno;
rtx link;
- /* See if there is a death note for something that includes TEST_REGNO. */
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ /* REG_READ notes are not normally maintained after reload, so we
+ ignore them if the are invalid. */
+ if (! reload_completed
+#ifdef PRESERVE_DEATH_INFO_REGNO_P
+ || PRESERVE_DEATH_INFO_REGNO_P (test_regno)
+#endif
+ )
{
- if (REG_NOTE_KIND (link) != REG_DEAD || GET_CODE (XEXP (link, 0)) != REG)
- continue;
+ /* See if there is a death note for something that includes
+ TEST_REGNO. */
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ {
+ if (REG_NOTE_KIND (link) != REG_DEAD
+ || GET_CODE (XEXP (link, 0)) != REG)
+ continue;
- regno = REGNO (XEXP (link, 0));
- endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
- : regno + HARD_REGNO_NREGS (regno,
- GET_MODE (XEXP (link, 0))));
+ regno = REGNO (XEXP (link, 0));
+ endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
+ : regno + HARD_REGNO_NREGS (regno,
+ GET_MODE (XEXP (link, 0))));
- if (test_regno >= regno && test_regno < endregno)
- return 1;
+ if (test_regno >= regno && test_regno < endregno)
+ return 1;
+ }
}
if (GET_CODE (insn) == CALL_INSN
@@ -1213,6 +1264,10 @@ find_reg_note (insn, kind, datum)
{
register rtx link;
+ /* Ignore anything that is not an INSN, JUMP_INSN or CALL_INSN. */
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return 0;
+
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == kind
&& (datum == 0 || datum == XEXP (link, 0)))
@@ -1233,6 +1288,10 @@ find_regno_note (insn, kind, regno)
{
register rtx link;
+ /* Ignore anything that is not an INSN, JUMP_INSN or CALL_INSN. */
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ return 0;
+
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == kind
/* Verify that it is a register, so that scratch and MEM won't cause a
@@ -1395,6 +1454,9 @@ volatile_insn_p (x)
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
+
+ default:
+ break;
}
/* Recursively scan the operands of this expression. */
@@ -1458,6 +1520,9 @@ volatile_refs_p (x)
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
+
+ default:
+ break;
}
/* Recursively scan the operands of this expression. */
@@ -1530,6 +1595,9 @@ side_effects_p (x)
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
+
+ default:
+ break;
}
/* Recursively scan the operands of this expression. */
@@ -1598,16 +1666,20 @@ may_trap_p (x)
case MOD:
case UDIV:
case UMOD:
- if (! CONSTANT_P (XEXP (x, 1)))
+ if (! CONSTANT_P (XEXP (x, 1))
+ || GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
return 1;
/* This was const0_rtx, but by not using that,
we can link this file into other programs. */
if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0)
return 1;
+ break;
+
case EXPR_LIST:
/* An EXPR_LIST is used to represent a function call. This
certainly may trap. */
return 1;
+
default:
/* Any floating arithmetic may trap. */
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
@@ -1666,6 +1738,9 @@ inequality_comparisons_p (x)
case GE:
case GEU:
return 1;
+
+ default:
+ break;
}
len = GET_RTX_LENGTH (code);
@@ -1690,7 +1765,8 @@ inequality_comparisons_p (x)
return 0;
}
-/* Replace any occurrence of FROM in X with TO.
+/* Replace any occurrence of FROM in X with TO. The function does
+ not enter into CONST_DOUBLE for the replace.
Note that copying is not done so X must not be shared unless all copies
are to be modified. */
@@ -1702,6 +1778,11 @@ replace_rtx (x, from, to)
register int i, j;
register char *fmt;
+ /* The following prevents loops occurrence when we change MEM in
+ CONST_DOUBLE onto the same CONST_DOUBLE. */
+ if (x != 0 && GET_CODE (x) == CONST_DOUBLE)
+ return x;
+
if (x == from)
return to;
@@ -1821,6 +1902,9 @@ replace_regs (x, reg_map, nregs, replace_dest)
SET_SRC (x) = replace_regs (SET_SRC (x), reg_map, nregs, 0);
return x;
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -1838,3 +1922,96 @@ replace_regs (x, reg_map, nregs, replace_dest)
}
return x;
}
+
+/* Return 1 if X, the SRC_SRC of SET of (pc) contain a REG or MEM that is
+ not in the constant pool and not in the condition of an IF_THEN_ELSE. */
+
+static int
+jmp_uses_reg_or_mem (x)
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+ int i, j;
+ char *fmt;
+
+ switch (code)
+ {
+ case CONST:
+ case LABEL_REF:
+ case PC:
+ return 0;
+
+ case REG:
+ return 1;
+
+ case MEM:
+ return ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));
+
+ case IF_THEN_ELSE:
+ return (jmp_uses_reg_or_mem (XEXP (x, 1))
+ || jmp_uses_reg_or_mem (XEXP (x, 2)));
+
+ case PLUS: case MINUS: case MULT:
+ return (jmp_uses_reg_or_mem (XEXP (x, 0))
+ || jmp_uses_reg_or_mem (XEXP (x, 1)));
+
+ default:
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e'
+ && jmp_uses_reg_or_mem (XEXP (x, i)))
+ return 1;
+
+ if (fmt[i] == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return nonzero if INSN is an indirect jump (aka computed jump).
+
+ Tablejumps and casesi insns are not considered indirect jumps;
+ we can recognize them by a (use (lael_ref)). */
+
+int
+computed_jump_p (insn)
+ rtx insn;
+{
+ int i;
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ rtx pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ int len = XVECLEN (pat, 0);
+ int has_use_labelref = 0;
+
+ for (i = len - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == USE
+ && (GET_CODE (XEXP (XVECEXP (pat, 0, i), 0))
+ == LABEL_REF))
+ has_use_labelref = 1;
+
+ if (! has_use_labelref)
+ for (i = len - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET
+ && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
+ && jmp_uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
+ return 1;
+ }
+ else if (GET_CODE (pat) == SET
+ && SET_DEST (pat) == pc_rtx
+ && jmp_uses_reg_or_mem (SET_SRC (pat)))
+ return 1;
+ }
+ return 0;
+}
OpenPOWER on IntegriCloud