diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 1999-08-26 09:30:50 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 1999-08-26 09:30:50 +0000 |
commit | 2a266d02ba4304af542da2cc521ecc0edc1c9706 (patch) | |
tree | 68d8110b41afd0ebbf39167b1a4918eea667a7c5 /contrib/gcc/rtlanal.c | |
parent | 3b82b5b7f77cb6aa00fbc3f7e544459b1213e88b (diff) | |
download | src-2a266d02ba4304af542da2cc521ecc0edc1c9706.tar.gz src-2a266d02ba4304af542da2cc521ecc0edc1c9706.zip |
Virgin import of gcc from EGCS 1.1.2
Notes
Notes:
svn path=/vendor/gcc/dist/; revision=50397
Diffstat (limited to 'contrib/gcc/rtlanal.c')
-rw-r--r-- | contrib/gcc/rtlanal.c | 235 |
1 files changed, 206 insertions, 29 deletions
diff --git a/contrib/gcc/rtlanal.c b/contrib/gcc/rtlanal.c index 17cfd36201f0..221b3fae4c13 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; +} |