📄 recog.c
字号:
validate_change (object, &XEXP (x, 0), newmem, 1); } } break; } 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); }}/* Try replacing every occurrence of FROM in INSN with TO. After all changes have been made, validate by seeing if INSN is still valid. */intvalidate_replace_rtx (from, to, insn) rtx from, to, insn;{ validate_replace_rtx_1 (&PATTERN (insn), from, to, insn); return apply_change_group ();}#ifdef HAVE_cc0/* Return 1 if the insn using CC0 set by INSN does not contain any ordered tests applied to the condition codes. EQ and NE tests do not count. */intnext_insn_tests_no_inequality (insn) rtx insn;{ register rtx next = next_cc0_user (insn); /* If there is no next insn, we have to take the conservative choice. */ if (next == 0) return 0; return ((GET_CODE (next) == JUMP_INSN || GET_CODE (next) == INSN || GET_CODE (next) == CALL_INSN) && ! inequality_comparisons_p (PATTERN (next)));}#if 0 /* This is useless since the insn that sets the cc's must be followed immediately by the use of them. *//* Return 1 if the CC value set up by INSN is not used. */intnext_insns_test_no_inequality (insn) rtx insn;{ register rtx next = NEXT_INSN (insn); for (; next != 0; next = NEXT_INSN (next)) { if (GET_CODE (next) == CODE_LABEL || GET_CODE (next) == BARRIER) return 1; if (GET_CODE (next) == NOTE) continue; if (inequality_comparisons_p (PATTERN (next))) return 0; if (sets_cc0_p (PATTERN (next)) == 1) return 1; if (! reg_mentioned_p (cc0_rtx, PATTERN (next))) return 1; } return 1;}#endif#endif/* This is used by find_single_use to locate an rtx that contains exactly one use of DEST, which is typically either a REG or CC0. It returns a pointer to the innermost rtx expression containing DEST. Appearances of DEST that are being used to totally replace it are not counted. */static rtx *find_single_use_1 (dest, loc) rtx dest; rtx *loc;{ rtx x = *loc; enum rtx_code code = GET_CODE (x); rtx *result = 0; rtx *this_result; int i; char *fmt; switch (code) { case CONST_INT: case CONST: case LABEL_REF: case SYMBOL_REF: case CONST_DOUBLE: case CLOBBER: return 0; case SET: /* If the destination is anything other than CC0, PC, a REG or a SUBREG of a REG that occupies all of the REG, the insn uses DEST if it is mentioned in the destination or the source. Otherwise, we need just check the source. */ if (GET_CODE (SET_DEST (x)) != CC0 && GET_CODE (SET_DEST (x)) != PC && GET_CODE (SET_DEST (x)) != REG && ! (GET_CODE (SET_DEST (x)) == SUBREG && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x)))) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x))) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))) break; return find_single_use_1 (dest, &SET_SRC (x)); case MEM: case SUBREG: return find_single_use_1 (dest, &XEXP (x, 0)); } /* If it wasn't one of the common cases above, check each expression and vector of this code. Look for a unique usage of DEST. */ fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') { if (dest == XEXP (x, i) || (GET_CODE (dest) == REG && GET_CODE (XEXP (x, i)) == REG && REGNO (dest) == REGNO (XEXP (x, i)))) this_result = loc; else this_result = find_single_use_1 (dest, &XEXP (x, i)); if (result == 0) result = this_result; else if (this_result) /* Duplicate usage. */ return 0; } else if (fmt[i] == 'E') { int j; for (j = XVECLEN (x, i) - 1; j >= 0; j--) { if (XVECEXP (x, i, j) == dest || (GET_CODE (dest) == REG && GET_CODE (XVECEXP (x, i, j)) == REG && REGNO (XVECEXP (x, i, j)) == REGNO (dest))) this_result = loc; else this_result = find_single_use_1 (dest, &XVECEXP (x, i, j)); if (result == 0) result = this_result; else if (this_result) return 0; } } } return result;}/* See if DEST, produced in INSN, is used only a single time in the sequel. If so, return a pointer to the innermost rtx expression in which it is used. If PLOC is non-zero, *PLOC is set to the insn containing the single use. This routine will return usually zero either before flow is called (because there will be no LOG_LINKS notes) or after reload (because the REG_DEAD note can't be trusted). If DEST is cc0_rtx, we look only at the next insn. In that case, we don't care about REG_DEAD notes or LOG_LINKS. Otherwise, we find the single use by finding an insn that has a LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is only referenced once in that insn, we know that it must be the first and last insn referencing DEST. */rtx *find_single_use (dest, insn, ploc) rtx dest; rtx insn; rtx *ploc;{ rtx next; rtx *result; rtx link;#ifdef HAVE_cc0 if (dest == cc0_rtx) { next = NEXT_INSN (insn); if (next == 0 || (GET_CODE (next) != INSN && GET_CODE (next) != JUMP_INSN)) return 0; result = find_single_use_1 (dest, &PATTERN (next)); if (result && ploc) *ploc = next; return result; }#endif if (reload_completed || reload_in_progress || GET_CODE (dest) != REG) return 0; for (next = next_nonnote_insn (insn); next != 0 && GET_CODE (next) != CODE_LABEL; next = next_nonnote_insn (next)) if (GET_RTX_CLASS (GET_CODE (next)) == 'i' && dead_or_set_p (next, dest)) { for (link = LOG_LINKS (next); link; link = XEXP (link, 1)) if (XEXP (link, 0) == insn) break; if (link) { result = find_single_use_1 (dest, &PATTERN (next)); if (ploc) *ploc = next; return result; } } return 0;}/* Return 1 if OP is a valid general operand for machine mode MODE. This is either a register reference, a memory reference, or a constant. In the case of a memory reference, the address is checked for general validity for the target machine. Register and memory references must have mode MODE in order to be valid, but some constants have no machine mode and are valid for any mode. If MODE is VOIDmode, OP is checked for validity for whatever mode it has. The main use of this function is as a predicate in match_operand expressions in the machine description. For an explanation of this function's behavior for registers of class NO_REGS, see the comment for `register_operand'. */intgeneral_operand (op, mode) register rtx op; enum machine_mode mode;{ register enum rtx_code code = GET_CODE (op); int mode_altering_drug = 0; if (mode == VOIDmode) mode = GET_MODE (op); /* Don't accept CONST_INT or anything similar if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; if (CONSTANT_P (op)) return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)#ifdef LEGITIMATE_PIC_OPERAND_P && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif && LEGITIMATE_CONSTANT_P (op)); /* Except for certain constants with VOIDmode, already checked for, OP's mode must match MODE if MODE specifies a mode. */ if (GET_MODE (op) != mode) return 0; if (code == SUBREG) {#ifdef INSN_SCHEDULING /* On machines that have insn scheduling, we want all memory reference to be explicit, so outlaw paradoxical SUBREGs. */ if (GET_CODE (SUBREG_REG (op)) == MEM && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) return 0;#endif op = SUBREG_REG (op); code = GET_CODE (op);#if 0 /* No longer needed, since (SUBREG (MEM...)) will load the MEM into a reload reg in the MEM's own mode. */ mode_altering_drug = 1;#endif } if (code == REG) /* A register whose class is NO_REGS is not a general operand. */ return (REGNO (op) >= FIRST_PSEUDO_REGISTER || REGNO_REG_CLASS (REGNO (op)) != NO_REGS); if (code == MEM) { register rtx y = XEXP (op, 0); if (! volatile_ok && MEM_VOLATILE_P (op)) return 0; /* Use the mem's mode, since it will be reloaded thus. */ mode = GET_MODE (op); GO_IF_LEGITIMATE_ADDRESS (mode, y, win); } return 0; win: if (mode_altering_drug) return ! mode_dependent_address_p (XEXP (op, 0)); return 1;}/* Return 1 if OP is a valid memory address for a memory reference of mode MODE. The main use of this function is as a predicate in match_operand expressions in the machine description. */intaddress_operand (op, mode) register rtx op; enum machine_mode mode;{ return memory_address_p (mode, op);}/* Return 1 if OP is a register reference of mode MODE. If MODE is VOIDmode, accept a register in any mode. The main use of this function is as a predicate in match_operand expressions in the machine description. As a special exception, registers whose class is NO_REGS are not accepted by `register_operand'. The reason for this change is to allow the representation of special architecture artifacts (such as a condition code register) without extending the rtl definitions. Since registers of class NO_REGS cannot be used as registers in any case where register classes are examined, it is most consistent to keep this function from accepting them. */intregister_operand (op, mode) register rtx op; enum machine_mode mode;{ if (GET_MODE (op) != mode && mode != VOIDmode) return 0; if (GET_CODE (op) == SUBREG) { /* Before reload, we can allow (SUBREG (MEM...)) as a register operand because it is guaranteed to be reloaded into one. Just make sure the MEM is valid in itself. (Ideally, (SUBREG (MEM)...) should not exist after reload, but currently it does result from (SUBREG (REG)...) where the reg went on the stack.) */ if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM) return general_operand (op, mode); op = SUBREG_REG (op); } /* We don't consider registers whose class is NO_REGS to be a register operand. */ return (GET_CODE (op) == REG && (REGNO (op) >= FIRST_PSEUDO_REGISTER || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));}/* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH or a hard register. */intscratch_operand (op, mode) register rtx op; enum machine_mode mode;{ return (GET_MODE (op) == mode && (GET_CODE (op) == SCRATCH || (GET_CODE (op) == REG && REGNO (op) < FIRST_PSEUDO_REGISTER)));}/* Return 1 if OP is a valid immediate operand for mode MODE. The main use of this function is as a predicate in match_operand expressions in the machine description. */intimmediate_operand (op, mode) register rtx op; enum machine_mode mode;{ /* Don't accept CONST_INT or anything similar if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; return (CONSTANT_P (op) && (GET_MODE (op) == mode || mode == VOIDmode || GET_MODE (op) == VOIDmode)#ifdef LEGITIMATE_PIC_OPERAND_P && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif && LEGITIMATE_CONSTANT_P (op));}/* Returns 1 if OP is an operand that is a CONST_INT. */intconst_int_operand (op, mode) register rtx op; enum machine_mode mode;{ return GET_CODE (op) == CONST_INT;}/* Returns 1 if OP is an operand that is a constant integer or constant floating-point number. */intconst_double_operand (op, mode) register rtx op; enum machine_mode mode;{ /* Don't accept CONST_INT or anything similar if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT) && (mode == VOIDmode || GET_MODE (op) == mode || GET_MODE (op) == VOIDmode));}/* Return 1 if OP is a general operand that is not an immediate operand. */intnonimmediate_operand (op, mode) register rtx op; enum machine_mode mode;{ return (general_operand (op, mode) && ! CONSTANT_P (op));}/* Return 1 if OP is a register reference or immediate value of mode MODE. */intnonmemory_operand (op, mode) register rtx op; enum machine_mode mode;{ if (CONSTANT_P (op)) { /* Don't accept CONST_INT or anything similar if the caller wants something floating. */ if (GET_MODE (op) == VOIDmode && mode != VOIDmode && GET_MODE_CLASS (mode) != MODE_INT && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) return 0; return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)#ifdef LEGITIMATE_PIC_OPERAND_P && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))#endif && LEGITIMATE_CONSTANT_P (op)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -