rtlanal.c
来自「GCC编译器源代码」· C语言 代码 · 共 1,983 行 · 第 1/4 页
C
1,983 行
else if (code == SYMBOL_REF) return XSTR (x, 0) == XSTR (y, 0); else if (code == SCRATCH || code == CONST_DOUBLE) return 0; /* Compare the elements. If any pair of corresponding elements fail to match, return 0 for the whole things. */ fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { switch (fmt[i]) { case 'w': if (XWINT (x, i) != XWINT (y, i)) return 0; break; case 'n': case 'i': if (XINT (x, i) != XINT (y, i)) return 0; break; case 'V': case 'E': /* Two vectors must have the same length. */ if (XVECLEN (x, i) != XVECLEN (y, i)) return 0; /* And the corresponding elements must match. */ for (j = 0; j < XVECLEN (x, i); j++) if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) return 0; break; case 'e': if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) return 0; break; case 'S': case 's': if (strcmp (XSTR (x, i), XSTR (y, i))) return 0; break; case 'u': /* These are just backpointers, so they don't matter. */ break; case '0': break; /* It is believed that rtx's at this level will never contain anything but integers and other rtx's, except for within LABEL_REFs and SYMBOL_REFs. */ default: abort (); } } return 1;}/* Call FUN on each register or MEM that is stored into or clobbered by X. (X would be the pattern of an insn). FUN receives two arguments: the REG, MEM, CC0 or PC being stored in or clobbered, the SET or CLOBBER rtx that does the store. If the item being stored in or clobbered is a SUBREG of a hard register, the SUBREG will be passed. */ voidnote_stores (x, fun) register rtx x; void (*fun) ();{ if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)) { register rtx dest = SET_DEST (x); while ((GET_CODE (dest) == SUBREG && (GET_CODE (SUBREG_REG (dest)) != REG || REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER)) || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART) dest = XEXP (dest, 0); (*fun) (dest, x); } else if (GET_CODE (x) == PARALLEL) { register int i; for (i = XVECLEN (x, 0) - 1; i >= 0; i--) { register rtx y = XVECEXP (x, 0, i); if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER) { register rtx dest = SET_DEST (y); while ((GET_CODE (dest) == SUBREG && (GET_CODE (SUBREG_REG (dest)) != REG || (REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER))) || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART) dest = XEXP (dest, 0); (*fun) (dest, y); } } }}/* Return nonzero if X's old contents don't survive after INSN. This will be true if X is (cc0) or if X is a register and X dies in INSN or because INSN entirely sets X. "Entirely set" means set directly and not through a SUBREG, ZERO_EXTRACT or SIGN_EXTRACT, so no trace of the old contents remains. Likewise, REG_INC does not count. REG may be a hard or pseudo reg. Renumbering is not taken into account, but for this use that makes no difference, since regs don't overlap during their lifetimes. Therefore, this function may be used at any time after deaths have been computed (in flow.c). If REG is a hard reg that occupies multiple machine registers, this function will only return 1 if each of those registers will be replaced by INSN. */intdead_or_set_p (insn, x) rtx insn; rtx x;{ register int regno, last_regno; register int i; /* Can't use cc0_rtx below since this file is used by genattrtab.c. */ if (GET_CODE (x) == CC0) return 1; if (GET_CODE (x) != REG) abort (); regno = REGNO (x); last_regno = (regno >= FIRST_PSEUDO_REGISTER ? regno : regno + HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1); for (i = regno; i <= last_regno; i++) if (! dead_or_set_regno_p (insn, i)) return 0; return 1;}/* Utility function for dead_or_set_p to check an individual register. Also called from flow.c. */intdead_or_set_regno_p (insn, test_regno) rtx insn; int 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)) { 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)))); if (test_regno >= regno && test_regno < endregno) return 1; } if (GET_CODE (insn) == CALL_INSN && find_regno_fusage (insn, CLOBBER, test_regno)) return 1; if (GET_CODE (PATTERN (insn)) == SET) { rtx dest = SET_DEST (PATTERN (insn)); /* A value is totally replaced if it is the destination or the destination is a SUBREG of REGNO that does not change the number of words in it. */ if (GET_CODE (dest) == SUBREG && (((GET_MODE_SIZE (GET_MODE (dest)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))) dest = SUBREG_REG (dest); if (GET_CODE (dest) != REG) return 0; regno = REGNO (dest); endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1 : regno + HARD_REGNO_NREGS (regno, GET_MODE (dest))); return (test_regno >= regno && test_regno < endregno); } else if (GET_CODE (PATTERN (insn)) == PARALLEL) { register int i; for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) { rtx body = XVECEXP (PATTERN (insn), 0, i); if (GET_CODE (body) == SET || GET_CODE (body) == CLOBBER) { rtx dest = SET_DEST (body); if (GET_CODE (dest) == SUBREG && (((GET_MODE_SIZE (GET_MODE (dest)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))) dest = SUBREG_REG (dest); if (GET_CODE (dest) != REG) continue; regno = REGNO (dest); endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1 : regno + HARD_REGNO_NREGS (regno, GET_MODE (dest))); if (test_regno >= regno && test_regno < endregno) return 1; } } } return 0;}/* Return the reg-note of kind KIND in insn INSN, if there is one. If DATUM is nonzero, look for one whose datum is DATUM. */rtxfind_reg_note (insn, kind, datum) rtx insn; enum reg_note kind; rtx datum;{ register rtx link; for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == kind && (datum == 0 || datum == XEXP (link, 0))) return link; return 0;}/* Return the reg-note of kind KIND in insn INSN which applies to register number REGNO, if any. Return 0 if there is no such reg-note. Note that the REGNO of this NOTE need not be REGNO if REGNO is a hard register; it might be the case that the note overlaps REGNO. */rtxfind_regno_note (insn, kind, regno) rtx insn; enum reg_note kind; int regno;{ register rtx link; 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 problem here. */ && GET_CODE (XEXP (link, 0)) == REG && REGNO (XEXP (link, 0)) <= regno && ((REGNO (XEXP (link, 0)) + (REGNO (XEXP (link, 0)) >= FIRST_PSEUDO_REGISTER ? 1 : HARD_REGNO_NREGS (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0))))) > regno)) return link; return 0;}/* Return true if DATUM, or any overlap of DATUM, of kind CODE is found in the CALL_INSN_FUNCTION_USAGE information of INSN. */intfind_reg_fusage (insn, code, datum) rtx insn; enum rtx_code code; rtx datum;{ /* If it's not a CALL_INSN, it can't possibly have a CALL_INSN_FUNCTION_USAGE field, so don't bother checking. */ if (GET_CODE (insn) != CALL_INSN) return 0; if (! datum) abort(); if (GET_CODE (datum) != REG) { register rtx link; for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) if (GET_CODE (XEXP (link, 0)) == code && rtx_equal_p (datum, SET_DEST (XEXP (link, 0)))) return 1; } else { register int regno = REGNO (datum); /* CALL_INSN_FUNCTION_USAGE information cannot contain references to pseudo registers, so don't bother checking. */ if (regno < FIRST_PSEUDO_REGISTER) { int end_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (datum)); int i; for (i = regno; i < end_regno; i++) if (find_regno_fusage (insn, code, i)) return 1; } } return 0;}/* Return true if REGNO, or any overlap of REGNO, of kind CODE is found in the CALL_INSN_FUNCTION_USAGE information of INSN. */intfind_regno_fusage (insn, code, regno) rtx insn; enum rtx_code code; int regno;{ register rtx link; /* CALL_INSN_FUNCTION_USAGE information cannot contain references to pseudo registers, so don't bother checking. */ if (regno >= FIRST_PSEUDO_REGISTER || GET_CODE (insn) != CALL_INSN ) return 0; for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) { register int regnote; register rtx op; if (GET_CODE (op = XEXP (link, 0)) == code && GET_CODE (SET_DEST (op)) == REG && (regnote = REGNO (SET_DEST (op))) <= regno && regnote + HARD_REGNO_NREGS (regnote, GET_MODE (SET_DEST (op))) > regno) return 1; } return 0;}/* Remove register note NOTE from the REG_NOTES of INSN. */voidremove_note (insn, note) register rtx note; register rtx insn;{ register rtx link; if (REG_NOTES (insn) == note) { REG_NOTES (insn) = XEXP (note, 1); return; } for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (XEXP (link, 1) == note) { XEXP (link, 1) = XEXP (note, 1); return; } abort ();}/* Nonzero if X contains any volatile instructions. These are instructions which may cause unpredictable machine state instructions, and thus no instructions should be moved or combined across them. This includes only volatile asms and UNSPEC_VOLATILE instructions. */intvolatile_insn_p (x) rtx x;{ register RTX_CODE code; code = GET_CODE (x); switch (code) { case LABEL_REF: case SYMBOL_REF: case CONST_INT: case CONST: case CONST_DOUBLE: case CC0: case PC: case REG: case SCRATCH: case CLOBBER: case ASM_INPUT: case ADDR_VEC: case ADDR_DIFF_VEC: case CALL: case MEM: return 0; case UNSPEC_VOLATILE: /* case TRAP_IF: This isn't clear yet. */ return 1; case ASM_OPERANDS: if (MEM_VOLATILE_P (x)) return 1; default: break; } /* Recursively scan the operands of this expression. */ { register char *fmt = GET_RTX_FORMAT (code); register int i; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') { if (volatile_insn_p (XEXP (x, i))) return 1; } if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) if (volatile_insn_p (XVECEXP (x, i, j))) return 1; } } } return 0;}/* Nonzero if X contains any volatile memory references UNSPEC_VOLATILE operations or volatile ASM_OPERANDS expressions. */intvolatile_refs_p (x) rtx x;{ register RTX_CODE code; code = GET_CODE (x); switch (code) { case LABEL_REF: case SYMBOL_REF: case CONST_INT: case CONST: case CONST_DOUBLE: case CC0: case PC: case REG: case SCRATCH: case CLOBBER: case ASM_INPUT: case ADDR_VEC: case ADDR_DIFF_VEC: return 0; case CALL: case UNSPEC_VOLATILE:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?