?? jump.c
字號:
register int idx; int ignore_loops;{ int changed = 0; register int i; for (i = XVECLEN (x, idx) - 1; i >= 0; i--) { register rtx olabel = XEXP (XVECEXP (x, idx, i), 0); register rtx nlabel = follow_jumps (olabel, ignore_loops); if (nlabel != olabel) { XEXP (XVECEXP (x, idx, i), 0) = nlabel; ++LABEL_NUSES (nlabel); if (--LABEL_NUSES (olabel) == 0) delete_insn (olabel); changed = 1; } } return changed;}/* Find all CODE_LABELs referred to in X, and increment their use counts. Also store one of them in JUMP_LABEL (INSN) if INSN is nonzero. Also, when there are consecutive labels, canonicalize on the last of them. Note that two labels separated by a loop-beginning note must be kept distinct if we have not yet done loop-optimization, because the gap between them is where loop-optimize will want to move invariant code to. CROSS_JUMP tells us that loop-optimization is done with. */static voidmark_jump_label (x, insn, cross_jump) register rtx x; rtx insn; int cross_jump;{ register RTX_CODE code = GET_CODE (x); register int i; register char *fmt; if (code == LABEL_REF) { register rtx label = XEXP (x, 0); register rtx next; if (GET_CODE (label) != CODE_LABEL) return; /* If there are other labels following this one, replace it with the last of the consecutive labels. */ for (next = NEXT_INSN (label); next; next = NEXT_INSN (next)) { if (GET_CODE (next) == CODE_LABEL) label = next; else if (GET_CODE (next) != NOTE || NOTE_LINE_NUMBER (next) == NOTE_INSN_LOOP_BEG || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END) break; } XEXP (x, 0) = label; ++LABEL_NUSES (label); if (insn) JUMP_LABEL (insn) = label; return; } /* Do walk the labels in a vector, but don't set its JUMP_LABEL. */ if (code == ADDR_VEC || code == ADDR_DIFF_VEC) insn = 0; fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code); i >= 0; i--) { if (fmt[i] == 'e') mark_jump_label (XEXP (x, i), insn, cross_jump); else if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) mark_jump_label (XVECEXP (x, i, j), insn, cross_jump); } }}/* If all INSN does is set the pc, delete it, and delete the insn that set the condition codes for it if that's what the previous thing was. */static voiddelete_jump (insn) rtx insn;{ register rtx x = PATTERN (insn); register rtx prev; if (GET_CODE (x) == SET && GET_CODE (SET_DEST (x)) == PC) { prev = PREV_INSN (insn); delete_insn (insn); /* We assume that at this stage CC's are always set explicitly and always immediately before the jump that will use them. So if the previous insn exists to set the CC's, delete it (unless it performs auto-increments, etc.). */ while (prev && GET_CODE (prev) == NOTE) prev = PREV_INSN (prev); if (prev && GET_CODE (prev) == INSN && sets_cc0_p (PATTERN (prev)) > 0 && !find_reg_note (prev, REG_INC, 0)) delete_insn (prev); }}/* Delete insn INSN from the chain of insns and update label ref counts. May delete some following insns as a consequence; may even delete a label elsewhere and insns that follow it. Returns the first insn after INSN that was not deleted. */rtxdelete_insn (insn) register rtx insn;{ register rtx next = NEXT_INSN (insn); register rtx prev = PREV_INSN (insn); while (next && INSN_DELETED_P (next)) next = NEXT_INSN (next); /* This insn is already deleted => return first following nondeleted. */ if (INSN_DELETED_P (insn)) return next; /* Mark this insn as deleted. */ INSN_DELETED_P (insn) = 1; /* If instruction is followed by a barrier, delete the barrier too. */ if (next != 0 && GET_CODE (next) == BARRIER) { INSN_DELETED_P (next) = 1; next = NEXT_INSN (next); } /* Patch out INSN (and the barrier if any) */ if (optimize) { if (prev) NEXT_INSN (prev) = next; if (next) PREV_INSN (next)= prev; if (prev && NEXT_INSN (prev) == 0) set_last_insn (prev); } /* If deleting a jump, decrement the count of the label, and delete the label if it is now unused. */ if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn)) if (--LABEL_NUSES (JUMP_LABEL (insn)) == 0) { /* This can delete NEXT or PREV, either directly if NEXT is JUMP_LABEL (INSN), or indirectly through more levels of jumps. */ delete_insn (JUMP_LABEL (insn)); /* I feel a little doubtful about this loop, but I see no clean and sure alternative way to find the first insn after INSN that is not now deleted. I hope this works. */ while (next && INSN_DELETED_P (next)) next = NEXT_INSN (next); return next; } while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE)) prev = PREV_INSN (prev); /* If INSN was a label and a dispatch table follows it, delete the dispatch table. The tablejump must have gone already. It isn't useful to fall through into a table. */ if (GET_CODE (insn) == CODE_LABEL && NEXT_INSN (insn) != 0 && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN && GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC) next = delete_insn (NEXT_INSN (insn)); /* If INSN was a label, delete insns following it if now unreachable. */ if (GET_CODE (insn) == CODE_LABEL && prev && GET_CODE (prev) == BARRIER) { register RTX_CODE code; while (next != 0 && ((code = GET_CODE (next)) == INSN || code == JUMP_INSN || code == CALL_INSN || code == NOTE)) { if (code == NOTE && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END) next = NEXT_INSN (next); else /* Note: if this deletes a jump, it can cause more deletion of unreachable code, after a different label. As long as the value from this recursive call is correct, this invocation functions correctly. */ next = delete_insn (next); } } return next;}/* Advance from INSN till reaching something not deleted then return that. May return INSN itself. */rtxnext_nondeleted_insn (insn) rtx insn;{ while (INSN_DELETED_P (insn)) insn = NEXT_INSN (insn); return insn;}/* Delete a range of insns from FROM to TO, inclusive. This is for the sake of peephole optimization, so assume that whatever these insns do will still be done by a new peephole insn that will replace them. */voiddelete_for_peephole (from, to) register rtx from, to;{ register rtx insn = from; while (1) { register rtx next = NEXT_INSN (insn); register rtx prev = PREV_INSN (insn); if (GET_CODE (insn) != NOTE) { INSN_DELETED_P (insn) = 1; /* Patch this insn out of the chain. */ /* We don't do this all at once, because we must preserve all NOTEs. */ if (prev) NEXT_INSN (prev) = next; if (next) PREV_INSN (next) = prev; } if (insn == to) break; insn = next; } /* Note that if TO is an unconditional jump we *do not* delete the BARRIER that follows, since the peephole that replaces this sequence is also an unconditional jump in that case. */}/* Invert the condition of the jump JUMP, and make it jump to label NLABEL instead of where it jumps now. */voidinvert_jump (jump, nlabel) rtx jump, nlabel;{ register rtx olabel = JUMP_LABEL (jump); invert_exp (PATTERN (jump), olabel, nlabel); JUMP_LABEL (jump) = nlabel; ++LABEL_NUSES (nlabel); INSN_CODE (jump) = -1; if (--LABEL_NUSES (olabel) == 0) delete_insn (olabel);}/* Invert the jump condition of rtx X, and replace OLABEL with NLABEL throughout. This is used in do_jump as well as in this file. */voidinvert_exp (x, olabel, nlabel) rtx x; rtx olabel, nlabel;{ register RTX_CODE code; register int i; register char *fmt; if (x == 0) return; code = GET_CODE (x); if (code == IF_THEN_ELSE) { /* Inverting the jump condition of an IF_THEN_ELSE means exchanging the THEN-part with the ELSE-part. */ register rtx tem = XEXP (x, 1); XEXP (x, 1) = XEXP (x, 2); XEXP (x, 2) = tem; } if (code == LABEL_REF) { if (XEXP (x, 0) == olabel) XEXP (x, 0) = nlabel; return; } fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') invert_exp (XEXP (x, i), olabel, nlabel); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) invert_exp (XVECEXP (x, i, j), olabel, nlabel); } }}/* Make jump JUMP jump to label NLABEL instead of where it jumps now. If the old jump target label is unused as a result, it and the code following it may be deleted. */voidredirect_jump (jump, nlabel) rtx jump, nlabel;{ register rtx olabel = JUMP_LABEL (jump); if (nlabel == olabel) return; redirect_exp (PATTERN (jump), olabel, nlabel); JUMP_LABEL (jump) = nlabel; ++LABEL_NUSES (nlabel); INSN_CODE (jump) = -1; if (--LABEL_NUSES (olabel) == 0) delete_insn (olabel);}/* Throughout the rtx X, alter (LABEL_REF OLABEL) to (LABEL_REF NLABEL). */static voidredirect_exp (x, olabel, nlabel) rtx x; rtx olabel, nlabel;{ register RTX_CODE code = GET_CODE (x); register int i; register char *fmt; if (code == LABEL_REF) { if (XEXP (x, 0) == olabel) XEXP (x, 0) = nlabel; return; } fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') redirect_exp (XEXP (x, i), olabel, nlabel); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) redirect_exp (XVECEXP (x, i, j), olabel, nlabel); } }}/* Like rtx_equal_p except that it considers two REGs as equal if they renumber to the same value. */intrtx_renumbered_equal_p (x, y) rtx x, y;{ register int i; register RTX_CODE code = GET_CODE (x); register char *fmt; if (x == y) return 1; if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG)) && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG && GET_CODE (SUBREG_REG (y)) == REG))) { register int j; if (GET_MODE (x) != GET_MODE (y)) return 0; if (code == SUBREG) { i = REGNO (SUBREG_REG (x)); if (reg_renumber[i] >= 0) i = reg_renumber[i]; i += SUBREG_WORD (x); } else { i = REGNO (x); if (reg_renumber[i] >= 0) i = reg_renumber[i]; } if (GET_CODE (y) == SUBREG) { j = REGNO (SUBREG_REG (y)); if (reg_renumber[j] >= 0) j = reg_renumber[j]; j += SUBREG_WORD (y); } else { j = REGNO (y); if (reg_renumber[j] >= 0) j = reg_renumber[j]; } return i == j; } /* Now we have disposed of all the cases in which different rtx codes can match. */ if (code != GET_CODE (y)) return 0; switch (code) { case PC: case CC0: case ADDR_VEC: case ADDR_DIFF_VEC: return 0; case CONST_INT: return XINT (x, 0) == XINT (y, 0); case LABEL_REF: /* Two label-refs are equivalent if they point at labels in the same position in the instruction stream. */ return (next_real_insn (XEXP (x, 0)) == next_real_insn (XEXP (y, 0))); case SYMBOL_REF: return XSTR (x, 0) == XSTR (y, 0); } /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */ if (GET_MODE (x) != GET_MODE (y)) 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--) { register int j; switch (fmt[i]) { case 'i': if (XINT (x, i) != XINT (y, i)) return 0; break; case 's': if (strcmp (XSTR (x, i), XSTR (y, i))) return 0; break; case 'e': if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i))) return 0; break; case '0': break; case 'E': if (XVECLEN (x, i) != XVECLEN (y, i)) return 0; for (j = XVECLEN (x, i) - 1; j >= 0; j--) if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j))) return 0; break; default: abort (); } } return 1;}/* If X is a hard register or equivalent to one or a subregister of one, return the hard register number. Otherwise, return -1. Any rtx is valid for X. */inttrue_regnum (x) rtx x;{ if (GET_CODE (x) == REG) { if (REGNO (x) >= FIRST_PSEUDO_REGISTER) return reg_renumber[REGNO (x)]; return REGNO (x); } if (GET_CODE (x) == SUBREG) { int base = true_regnum (SUBREG_REG (x)); if (base >= 0 && base < FIRST_PSEUDO_REGISTER) return SUBREG_WORD (x) + base; } return -1;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -