diff options
Diffstat (limited to 'contrib/gcc/recog.c')
-rw-r--r-- | contrib/gcc/recog.c | 138 |
1 files changed, 103 insertions, 35 deletions
diff --git a/contrib/gcc/recog.c b/contrib/gcc/recog.c index 745d628..ded35f7 100644 --- a/contrib/gcc/recog.c +++ b/contrib/gcc/recog.c @@ -1,5 +1,5 @@ /* Subroutines used by or related to instruction recognition. - Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 91-97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -20,8 +20,8 @@ Boston, MA 02111-1307, USA. */ #include "config.h" +#include "system.h" #include "rtl.h" -#include <stdio.h> #include "insn-config.h" #include "insn-attr.h" #include "insn-flags.h" @@ -43,8 +43,9 @@ Boston, MA 02111-1307, USA. */ /* Import from final.c: */ extern rtx alter_subreg (); -int strict_memory_address_p (); -int memory_address_p (); +static void validate_replace_rtx_1 PROTO((rtx *, rtx, rtx, rtx)); +static rtx *find_single_use_1 PROTO((rtx, rtx *)); +static rtx *find_constant_term_loc PROTO((rtx *)); /* Nonzero means allow operands to be volatile. This should be 0 if you are generating rtl, such as if you are calling @@ -260,8 +261,8 @@ apply_change_group () { int j; - newpat = gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (XVECLEN (pat, 0) - 1)); + newpat = gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (XVECLEN (pat, 0) - 1)); for (j = 0; j < XVECLEN (newpat, 0); j++) XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j); } @@ -365,24 +366,38 @@ validate_replace_rtx_1 (loc, from, to, object) if (prev_changes != num_changes && CONSTANT_P (XEXP (x, 0))) { validate_change (object, loc, - gen_rtx (GET_RTX_CLASS (code) == 'c' ? code - : swap_condition (code), - GET_MODE (x), XEXP (x, 1), XEXP (x, 0)), + gen_rtx_fmt_ee (GET_RTX_CLASS (code) == 'c' ? code + : swap_condition (code), + GET_MODE (x), XEXP (x, 1), + XEXP (x, 0)), 1); x = *loc; code = GET_CODE (x); } } + /* Note that if CODE's RTX_CLASS is "c" or "<" we will have already + done the substitution, otherwise we won't. */ + switch (code) { case PLUS: - /* If we have have a PLUS whose second operand is now a CONST_INT, use + /* If we have a PLUS whose second operand is now a CONST_INT, use plus_constant to try to simplify it. */ if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to) - validate_change (object, loc, - plus_constant (XEXP (x, 0), INTVAL (XEXP (x, 1))), 1); + validate_change (object, loc, plus_constant (XEXP (x, 0), INTVAL (to)), + 1); return; + + case MINUS: + if (GET_CODE (to) == CONST_INT && XEXP (x, 1) == from) + { + validate_change (object, loc, + plus_constant (XEXP (x, 0), - INTVAL (to)), + 1); + return; + } + break; case ZERO_EXTEND: case SIGN_EXTEND: @@ -400,7 +415,7 @@ validate_replace_rtx_1 (loc, from, to, object) rtx new = simplify_unary_operation (code, GET_MODE (x), to, GET_MODE (from)); if (new == 0) - new = gen_rtx (CLOBBER, GET_MODE (x), const0_rtx); + new = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx); validate_change (object, loc, new, 1); return; @@ -429,7 +444,7 @@ validate_replace_rtx_1 (loc, from, to, object) GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))); - new = gen_rtx (MEM, mode, plus_constant (XEXP (to, 0), offset)); + new = gen_rtx_MEM (mode, plus_constant (XEXP (to, 0), offset)); MEM_VOLATILE_P (new) = MEM_VOLATILE_P (to); RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (to); MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (to); @@ -453,7 +468,6 @@ validate_replace_rtx_1 (loc, from, to, object) { enum machine_mode wanted_mode = VOIDmode; enum machine_mode is_mode = GET_MODE (to); - int width = INTVAL (XEXP (x, 1)); int pos = INTVAL (XEXP (x, 2)); #ifdef HAVE_extzv @@ -480,8 +494,8 @@ validate_replace_rtx_1 (loc, from, to, object) pos %= GET_MODE_BITSIZE (wanted_mode); - newmem = gen_rtx (MEM, wanted_mode, - plus_constant (XEXP (to, 0), offset)); + newmem = gen_rtx_MEM (wanted_mode, + plus_constant (XEXP (to, 0), offset)); RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (to); MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (to); MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (to); @@ -492,16 +506,24 @@ validate_replace_rtx_1 (loc, from, to, object) } break; + + default: + break; } - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + /* For commutative or comparison operations we've already performed + replacements. Don't try to perform them again. */ + if (GET_RTX_CLASS (code) != '<' && GET_RTX_CLASS (code) != 'c') { - if (fmt[i] == 'e') - validate_replace_rtx_1 (&XEXP (x, i), from, to, object); - else if (fmt[i] == 'E') - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object); + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'e') + validate_replace_rtx_1 (&XEXP (x, i), from, to, object); + else if (fmt[i] == 'E') + for (j = XVECLEN (x, i) - 1; j >= 0; j--) + validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object); + } } } @@ -515,6 +537,25 @@ validate_replace_rtx (from, to, insn) validate_replace_rtx_1 (&PATTERN (insn), from, to, insn); return apply_change_group (); } + +/* 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. */ + +int +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); + return apply_change_group (); +} #ifdef HAVE_cc0 /* Return 1 if the insn using CC0 set by INSN does not contain @@ -614,6 +655,9 @@ find_single_use_1 (dest, loc) case MEM: case SUBREG: return find_single_use_1 (dest, &XEXP (x, 0)); + + default: + break; } /* If it wasn't one of the common cases above, check each expression and @@ -806,10 +850,18 @@ general_operand (op, mode) register rtx y = XEXP (op, 0); if (! volatile_ok && MEM_VOLATILE_P (op)) return 0; + if (GET_CODE (y) == ADDRESSOF) + return 1; /* Use the mem's mode, since it will be reloaded thus. */ mode = GET_MODE (op); GO_IF_LEGITIMATE_ADDRESS (mode, y, win); } + + /* Pretend this is an operand for now; we'll run force_operand + on its replacement in fixup_var_refs_1. */ + if (code == ADDRESSOF) + return 1; + return 0; win: @@ -871,7 +923,9 @@ register_operand (op, mode) && TEST_HARD_REG_BIT (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], REGNO (SUBREG_REG (op))) && (GET_MODE_SIZE (mode) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))) + != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) + && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT + && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT) return 0; #endif @@ -1043,6 +1097,9 @@ memory_address_p (mode, addr) enum machine_mode mode; register rtx addr; { + if (GET_CODE (addr) == ADDRESSOF) + return 1; + GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); return 0; @@ -1545,7 +1602,7 @@ adj_offsettable_operand (op, offset) if (CONSTANT_ADDRESS_P (y)) { - new = gen_rtx (MEM, GET_MODE (op), plus_constant_for_output (y, offset)); + new = gen_rtx_MEM (GET_MODE (op), plus_constant_for_output (y, offset)); RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op); return new; } @@ -1565,7 +1622,7 @@ adj_offsettable_operand (op, offset) } } - new = gen_rtx (MEM, GET_MODE (op), plus_constant_for_output (y, offset)); + new = gen_rtx_MEM (GET_MODE (op), plus_constant_for_output (y, offset)); RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op); return new; } @@ -1650,6 +1707,11 @@ constrain_operands (insn_code_num, strict) earlyclobber[opno] = 0; + /* A unary operator may be accepted by the predicate, but it + is irrelevant for matching constraints. */ + if (GET_RTX_CLASS (GET_CODE (op)) == '1') + op = XEXP (op, 0); + if (GET_CODE (op) == SUBREG) { if (GET_CODE (SUBREG_REG (op)) == REG @@ -1765,8 +1827,9 @@ constrain_operands (insn_code_num, strict) break; case 'X': - /* This is used for a MATCH_SCRATCH in the cases when we - don't actually need anything. So anything goes any time. */ + /* This is used for a MATCH_SCRATCH in the cases when + we don't actually need anything. So anything goes + any time. */ win = 1; break; @@ -1862,7 +1925,12 @@ constrain_operands (insn_code_num, strict) case 'V': if (GET_CODE (op) == MEM - && ! offsettable_memref_p (op)) + && ((strict > 0 && ! offsettable_memref_p (op)) + || (strict < 0 + && !(CONSTANT_P (op) || GET_CODE (op) == MEM)) + || (reload_in_progress + && !(GET_CODE (op) == REG + && REGNO (op) >= FIRST_PSEUDO_REGISTER)))) win = 1; break; @@ -1916,11 +1984,11 @@ constrain_operands (insn_code_num, strict) if ((GET_CODE (recog_operand[opno]) == MEM || op_types[opno] != OP_OUT) && opno != eopno - /* Ignore things like match_operator operands. */ - && *constraints[opno] != 0 + /* Ignore things like match_operator operands. */ + && *insn_operand_constraint[insn_code_num][opno] != 0 && ! (matching_operands[opno] == eopno - && rtx_equal_p (recog_operand[opno], - recog_operand[eopno])) + && operands_match_p (recog_operand[opno], + recog_operand[eopno])) && ! safe_from_earlyclobber (recog_operand[opno], recog_operand[eopno])) lose = 1; @@ -1949,7 +2017,7 @@ constrain_operands (insn_code_num, strict) } /* Return 1 iff OPERAND (assumed to be a REG rtx) - is a hard reg in class CLASS when its regno is offsetted by OFFSET + is a hard reg in class CLASS when its regno is offset by OFFSET and changed to mode MODE. If REG occupies multiple hard regs, all of them must be in CLASS. */ |