?? jump.c
字號:
newjpos = 0; /* TARGET is nonzero if it is ok to cross jump to code before TARGET. If so, see if matches. */ find_cross_jump (insn, JUMP_LABEL (insn), 1, &newjpos, &newlpos); /* If cannot cross jump to code before the label, see if we can cross jump to another jump to the same label. */ /* Try each other jump to this label. */ if (INSN_UID (JUMP_LABEL (insn)) < max_uid) for (target = jump_chain[INSN_UID (JUMP_LABEL (insn))]; target != 0 && newjpos == 0; target = jump_chain[INSN_UID (target)]) if (target != insn && JUMP_LABEL (target) == JUMP_LABEL (insn) /* Ignore TARGET if it's deleted. */ && ! INSN_DELETED_P (target)) find_cross_jump (insn, target, 2, &newjpos, &newlpos); if (newjpos != 0) { do_cross_jump (insn, newjpos, newlpos); changed = 1; next = insn; } } } } else if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == RETURN) { /* Return insns all "jump to the same place" so we can cross-jump between any two of them. */ if (cross_jump) { rtx newjpos, newlpos, target; newjpos = 0; /* If cannot cross jump to code before the label, see if we can cross jump to another jump to the same label. */ /* Try each other jump to this label. */ for (target = jump_chain[0]; target != 0 && newjpos == 0; target = jump_chain[INSN_UID (target)]) if (target != insn && ! INSN_DELETED_P (target) && GET_CODE (PATTERN (target)) == RETURN) find_cross_jump (insn, target, 2, &newjpos, &newlpos); if (newjpos != 0) { do_cross_jump (insn, newjpos, newlpos); changed = 1; next = insn; } } } } first = 0; } /* See if there is still a NOTE_INSN_FUNCTION_END in this function. If so, delete it, and record that this function can drop off the end. */ insn = last_insn; { int n_labels = 1; while (insn /* One label can follow the end-note: the return label. */ && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0) /* Ordinary insns can follow it if returning a structure. */ || GET_CODE (insn) == INSN /* If machine uses explicit RETURN insns, no epilogue, then one of them follows the note. */ || (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == RETURN) /* Other kinds of notes can follow also. */ || (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END))) insn = PREV_INSN (insn); } if (insn && GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END) { extern int current_function_returns_null; current_function_returns_null = 1; delete_insn (insn); }}/* Compare the instructions before insn E1 with those before E2. Assume E1 is a jump that jumps to label E2 (that is not always true but it might as well be). Find the longest possible equivalent sequences and store the first insns of those sequences into *F1 and *F2. Store zero there if no equivalent preceding instructions are found. We give up if we find a label in stream 1. Actually we could transfer that label into stream 2. */static voidfind_cross_jump (e1, e2, minimum, f1, f2) rtx e1, e2; int minimum; rtx *f1, *f2;{ register rtx i1 = e1, i2 = e2; register rtx p1, p2; rtx last1 = 0, last2 = 0; rtx afterlast1 = 0, afterlast2 = 0; *f1 = 0; *f2 = 0; while (1) { i1 = PREV_INSN (i1); while (i1 && GET_CODE (i1) == NOTE) i1 = PREV_INSN (i1); i2 = PREV_INSN (i2); while (i2 && (GET_CODE (i2) == NOTE || GET_CODE (i2) == CODE_LABEL)) i2 = PREV_INSN (i2); if (i1 == 0) break; /* Don't allow the range of insns preceding E1 or E2 to include the other (E2 or E1). */ if (i2 == e1 || i1 == e2) break; /* If we will get to this code by jumping, those jumps will be tensioned to go directly to the new label (before I2), so this cross-jumping won't cost extra. So reduce the minimum. */ if (GET_CODE (i1) == CODE_LABEL) { --minimum; break; } if (i2 == 0 || GET_CODE (i1) != GET_CODE (i2)) break; p1 = PATTERN (i1); p2 = PATTERN (i2); if (GET_CODE (p1) != GET_CODE (p2) || !rtx_renumbered_equal_p (p1, p2)) { /* Insns fail to match; cross jumping is limited to the following insns. */ /* Don't allow the insn after a compare to be shared by cross-jumping unless the compare is also shared. Here, if either of these non-matching insns is a compare, exclude the following insn from possible cross-jumping. */ if (sets_cc0_p (p1) || sets_cc0_p (p2)) last1 = afterlast1, last2 = afterlast2, ++minimum; /* If cross-jumping here will feed a jump-around-jump optimization, this jump won't cost extra, so reduce the minimum. */ if (GET_CODE (i1) == JUMP_INSN && JUMP_LABEL (i1) && prev_real_insn (JUMP_LABEL (i1)) == e1) --minimum; break; } if (GET_CODE (p1) != USE && GET_CODE (p1) != CLOBBER) { /* Ok, this insn is potentially includable in a cross-jump here. */ afterlast1 = last1, afterlast2 = last2; last1 = i1, last2 = i2, --minimum; } } if (minimum <= 0 && last1 != 0) *f1 = last1, *f2 = last2;}static voiddo_cross_jump (insn, newjpos, newlpos) rtx insn, newjpos, newlpos;{ register rtx label; /* Find an existing label at this point or make a new one if there is none. */ label = PREV_INSN (newlpos); while (label && GET_CODE (label) == NOTE) label = PREV_INSN (label); if (label == 0 || GET_CODE (label) != CODE_LABEL) { label = gen_label_rtx (); emit_label_after (label, PREV_INSN (newlpos)); LABEL_NUSES (label) = 0; } /* Make the same jump insn jump to the new point. */ if (GET_CODE (PATTERN (insn)) == RETURN) { extern rtx gen_jump (); PATTERN (insn) = gen_jump (label); INSN_CODE (insn) = -1; JUMP_LABEL (insn) = label; LABEL_NUSES (label)++; } else redirect_jump (insn, label); /* Delete the matching insns before the jump. */ newjpos = PREV_INSN (newjpos); while (NEXT_INSN (newjpos) != insn) /* Don't delete line numbers. */ if (GET_CODE (NEXT_INSN (newjpos)) != NOTE) delete_insn (NEXT_INSN (newjpos)); else newjpos = NEXT_INSN (newjpos);}/* Move all block-beg and block-end notes between START and END out before START. Assume neither START nor END is such a note. */static voidsqueeze_block_notes (start, end) rtx start, end;{ rtx insn; rtx next; for (insn = start; insn != end; insn = next) { next = NEXT_INSN (insn); if (GET_CODE (insn) == NOTE && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)) { rtx prev = PREV_INSN (insn); PREV_INSN (insn) = PREV_INSN (start); NEXT_INSN (insn) = start; NEXT_INSN (PREV_INSN (insn)) = insn; PREV_INSN (NEXT_INSN (insn)) = insn; NEXT_INSN (prev) = next; PREV_INSN (next) = prev; } }}/* Return 1 if INSN is a jump that jumps to right after TARGET only on the condition that TARGET itself would drop through. Assumes that TARGET is a conditional jump. */static intjump_back_p (insn, target) rtx insn, target;{ rtx cinsn, ctarget, prev; enum rtx_code codei, codet; if (simplejump_p (insn) || ! condjump_p (insn) || simplejump_p (target)) return 0; if (target != prev_real_insn (JUMP_LABEL (insn))) return 0; /* Verify that the condition code was based on a fixed-point computation. Using reverse_condition is invalid for IEEE floating point with nans. */ prev = prev_real_insn (insn); if (! (prev != 0 && GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SET && SET_DEST (PATTERN (prev)) == cc0_rtx && (GET_MODE_CLASS (GET_MODE (SET_SRC (PATTERN (prev)))) == MODE_INT || (GET_CODE (SET_SRC (PATTERN (prev))) == COMPARE && (GET_MODE_CLASS (GET_MODE (XEXP (SET_SRC (PATTERN (prev)), 0))) == MODE_INT))))) return 0; cinsn = XEXP (SET_SRC (PATTERN (insn)), 0); ctarget = XEXP (SET_SRC (PATTERN (target)), 0); codei = GET_CODE (cinsn); codet = GET_CODE (ctarget); if (XEXP (SET_SRC (PATTERN (insn)), 1) == pc_rtx) codei = reverse_condition (codei); if (XEXP (SET_SRC (PATTERN (target)), 2) == pc_rtx) codet = reverse_condition (codet); return (codei == codet && rtx_renumbered_equal_p (XEXP (cinsn, 0), XEXP (ctarget, 0)) && rtx_renumbered_equal_p (XEXP (cinsn, 1), XEXP (ctarget, 1)));}/* Given an rtx-code for a comparison, return the code for the negated comparison. WATCH OUT! reverse_condition is not safe to use on a jump that might be acting on the results of an IEEE floating point comparison, because of the special treatment of non-signaling nans in comparisons. */static enum rtx_codereverse_condition (code) enum rtx_code code;{ switch (code) { case EQ: return NE; case NE: return EQ; case GT: return LE; case GE: return LT; case LT: return GE; case LE: return GT; case GTU: return LEU; case GEU: return LTU; case LTU: return GEU; case LEU: return GTU; default: abort (); return UNKNOWN; }}/* Return 1 if INSN is an unconditional jump and nothing else. */intsimplejump_p (insn) rtx insn;{ register rtx x = PATTERN (insn); if (GET_CODE (x) != SET) return 0; if (GET_CODE (SET_DEST (x)) != PC) return 0; if (GET_CODE (SET_SRC (x)) != LABEL_REF) return 0; return 1;}/* Return nonzero if INSN is a (possibly) conditional jump and nothing more. */intcondjump_p (insn) rtx insn;{ register rtx x = PATTERN (insn); if (GET_CODE (x) != SET) return 0; if (GET_CODE (SET_DEST (x)) != PC) return 0; if (GET_CODE (SET_SRC (x)) == LABEL_REF) return 1; if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE) return 0; if (XEXP (SET_SRC (x), 2) == pc_rtx && GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF) return 1; if (XEXP (SET_SRC (x), 1) == pc_rtx && GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF) return 1; return 0;}/* Return 1 if X is an RTX that does nothing but set the condition codes and CLOBBER or USE registers. Return -1 if X does explicitly set the condition codes, but also does other things. */intsets_cc0_p (x) rtx x;{ if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx) return 1; if (GET_CODE (x) == PARALLEL) { int i; int sets_cc0 = 0; int other_things = 0; for (i = XVECLEN (x, 0) - 1; i >= 0; i--) { if (GET_CODE (XVECEXP (x, 0, i)) == SET && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx) sets_cc0 = 1; else if (GET_CODE (XVECEXP (x, 0, i)) == SET) other_things = 1; } return ! sets_cc0 ? 0 : other_things ? -1 : 1; } return 0;}/* Return 1 if in between BEG and END there is no CODE_LABEL insn. */intno_labels_between_p (beg, end) rtx beg, end;{ register rtx p; for (p = beg; p != end; p = NEXT_INSN (p)) if (GET_CODE (p) == CODE_LABEL) return 0; return 1;}/* Return the last INSN, CALL_INSN or JUMP_INSN before LABEL; or 0, if there is none. */rtxprev_real_insn (label) rtx label;{ register rtx insn = PREV_INSN (label); register RTX_CODE code; while (1) { if (insn == 0) return 0; code = GET_CODE (insn); if (code == INSN || code == CALL_INSN || code == JUMP_INSN) break; insn = PREV_INSN (insn); } return insn;}/* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL; or 0, if there is none. */rtxnext_real_insn (label) rtx label;{ register rtx insn = NEXT_INSN (label); register RTX_CODE code; while (1) { if (insn == 0) return insn; code = GET_CODE (insn); if (code == INSN || code == CALL_INSN || code == JUMP_INSN) break; insn = NEXT_INSN (insn); } return insn;}/* Return the next CODE_LABEL after the insn INSN, or 0 if there is none. */rtxnext_label (insn) rtx insn;{ do insn = NEXT_INSN (insn); while (insn != 0 && GET_CODE (insn) != CODE_LABEL); return insn;}/* Follow any unconditional jump at LABEL; return the ultimate label reached by any such chain of jumps. If LABEL is not followed by a jump, return LABEL. If IGNORE_LOOPS is 0, we do not chain across a NOTE_INSN_LOOP_BEG. */static rtxfollow_jumps (label, ignore_loops) rtx label; int ignore_loops;{ register rtx insn; register rtx next; register rtx value = label; register int depth; for (depth = 0; (depth < 10 && (insn = next_real_insn (value)) != 0 && GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn) != 0 && (next = NEXT_INSN (insn)) && GET_CODE (next) == BARRIER); depth++) { /* Don't chain through the insn that jumps into a loop from outside the loop, since that would create multiple loop entry jumps and prevent loop optimization. */ rtx tem; if (!ignore_loops) for (tem = value; tem != insn; tem = NEXT_INSN (tem)) if (GET_CODE (tem) == NOTE && NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG) return value; /* If we have found a cycle, make the insn jump to itself. */ if (JUMP_LABEL (insn) == label) break; value = JUMP_LABEL (insn); } return value;}/* Assuming that field IDX of X is a vector of label_refs, replace each of them by the ultimate label reached by it. Return nonzero if a change is made. If IGNORE_LOOPS is 0, we do not chain across a NOTE_INSN_LOOP_BEG. */static inttension_vector_labels (x, idx, ignore_loops) register rtx x;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -