📄 jump.c
字号:
if ((SET_SRC (PATTERN (temp1)) != const0_rtx) == want_nonzero) ultimate = XEXP (choice, 1); else ultimate = XEXP (choice, 2); /* Get it as a CODE_LABEL. */ if (ultimate == pc_rtx) ultimate = get_label_after (insn); else /* Get the label out of the LABEL_REF. */ ultimate = XEXP (ultimate, 0); /* Insert the jump immediately before TEMP, specifically after the label that is between TEMP1 and TEMP. */ last_insn = PREV_INSN (temp); /* If we would be branching to the next insn, the jump would immediately be deleted and the re-inserted in a subsequent pass over the code. So don't do anything in that case. */ if (next_active_insn (last_insn) != next_active_insn (ultimate)) { emit_barrier_after (last_insn); p = emit_jump_insn_after (gen_jump (ultimate), last_insn); JUMP_LABEL (p) = ultimate; ++LABEL_NUSES (ultimate); if (INSN_UID (ultimate) < max_jump_chain && INSN_CODE (p) < max_jump_chain) { jump_chain[INSN_UID (p)] = jump_chain[INSN_UID (ultimate)]; jump_chain[INSN_UID (ultimate)] = p; } changed = 1; continue; } } }#endif /* Detect a conditional jump going to the same place as an immediately following unconditional jump. */ else if (this_is_condjump && (temp = next_active_insn (insn)) != 0 && simplejump_p (temp) && (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (JUMP_LABEL (temp)))) { delete_jump (insn); changed = 1; continue; } /* Detect a conditional jump jumping over an unconditional jump. */ else if (this_is_condjump && ! this_is_simplejump && reallabelprev != 0 && GET_CODE (reallabelprev) == JUMP_INSN && prev_active_insn (reallabelprev) == insn && no_labels_between_p (insn, reallabelprev) && simplejump_p (reallabelprev)) { /* When we invert the unconditional jump, we will be decrementing the usage count of its old label. Make sure that we don't delete it now because that might cause the following code to be deleted. */ rtx prev_uses = prev_nonnote_insn (reallabelprev); rtx prev_label = JUMP_LABEL (insn); ++LABEL_NUSES (prev_label); if (invert_jump (insn, JUMP_LABEL (reallabelprev))) { /* It is very likely that if there are USE insns before this jump, they hold REG_DEAD notes. These REG_DEAD notes are no longer valid due to this optimization, and will cause the life-analysis that following passes (notably delayed-branch scheduling) to think that these registers are dead when they are not. To prevent this trouble, we just remove the USE insns from the insn chain. */ while (prev_uses && GET_CODE (prev_uses) == INSN && GET_CODE (PATTERN (prev_uses)) == USE) { rtx useless = prev_uses; prev_uses = prev_nonnote_insn (prev_uses); delete_insn (useless); } delete_insn (reallabelprev); next = insn; changed = 1; } /* We can now safely delete the label if it is unreferenced since the delete_insn above has deleted the BARRIER. */ if (--LABEL_NUSES (prev_label) == 0) delete_insn (prev_label); continue; } else { /* Detect a jump to a jump. */ nlabel = follow_jumps (JUMP_LABEL (insn)); if (nlabel != JUMP_LABEL (insn) && redirect_jump (insn, nlabel)) { changed = 1; next = insn; } /* Look for if (foo) bar; else break; */ /* The insns look like this: insn = condjump label1; ...range1 (some insns)... jump label2; label1: ...range2 (some insns)... jump somewhere unconditionally label2: */ { rtx label1 = next_label (insn); rtx range1end = label1 ? prev_active_insn (label1) : 0; /* Don't do this optimization on the first round, so that jump-around-a-jump gets simplified before we ask here whether a jump is unconditional. Also don't do it when we are called after reload since it will confuse reorg. */ if (! first && (reload_completed ? ! flag_delayed_branch : 1) /* Make sure INSN is something we can invert. */ && condjump_p (insn) && label1 != 0 && JUMP_LABEL (insn) == label1 && LABEL_NUSES (label1) == 1 && GET_CODE (range1end) == JUMP_INSN && simplejump_p (range1end)) { rtx label2 = next_label (label1); rtx range2end = label2 ? prev_active_insn (label2) : 0; if (range1end != range2end && JUMP_LABEL (range1end) == label2 && GET_CODE (range2end) == JUMP_INSN && GET_CODE (NEXT_INSN (range2end)) == BARRIER /* Invert the jump condition, so we still execute the same insns in each case. */ && invert_jump (insn, label1)) { rtx range1beg = next_active_insn (insn); rtx range2beg = next_active_insn (label1); rtx range1after, range2after; rtx range1before, range2before; /* Include in each range any line number before it. */ while (PREV_INSN (range1beg) && GET_CODE (PREV_INSN (range1beg)) == NOTE && NOTE_LINE_NUMBER (PREV_INSN (range1beg)) > 0) range1beg = PREV_INSN (range1beg); while (PREV_INSN (range2beg) && GET_CODE (PREV_INSN (range2beg)) == NOTE && NOTE_LINE_NUMBER (PREV_INSN (range2beg)) > 0) range2beg = PREV_INSN (range2beg); /* Don't move NOTEs for blocks or loops; shift them outside the ranges, where they'll stay put. */ range1beg = squeeze_notes (range1beg, range1end); range2beg = squeeze_notes (range2beg, range2end); /* Get current surrounds of the 2 ranges. */ range1before = PREV_INSN (range1beg); range2before = PREV_INSN (range2beg); range1after = NEXT_INSN (range1end); range2after = NEXT_INSN (range2end); /* Splice range2 where range1 was. */ NEXT_INSN (range1before) = range2beg; PREV_INSN (range2beg) = range1before; NEXT_INSN (range2end) = range1after; PREV_INSN (range1after) = range2end; /* Splice range1 where range2 was. */ NEXT_INSN (range2before) = range1beg; PREV_INSN (range1beg) = range2before; NEXT_INSN (range1end) = range2after; PREV_INSN (range2after) = range1end; changed = 1; continue; } } } /* Now that the jump has been tensioned, try cross jumping: check for identical code before the jump and before its target label. */ /* First, cross jumping of conditional jumps: */ if (cross_jump && condjump_p (insn)) { rtx newjpos, newlpos; rtx x = prev_real_insn (JUMP_LABEL (insn)); /* A conditional jump may be crossjumped only if the place it jumps to follows an opposing jump that comes back here. */ if (x != 0 && ! jump_back_p (x, insn)) /* We have no opposing jump; cannot cross jump this insn. */ x = 0; newjpos = 0; /* TARGET is nonzero if it is ok to cross jump to code before TARGET. If so, see if matches. */ if (x != 0) find_cross_jump (insn, x, 2, &newjpos, &newlpos); if (newjpos != 0) { do_cross_jump (insn, newjpos, newlpos); /* Make the old conditional jump into an unconditional one. */ SET_SRC (PATTERN (insn)) = gen_rtx (LABEL_REF, VOIDmode, JUMP_LABEL (insn)); INSN_CODE (insn) = -1; emit_barrier_after (insn); /* Add to jump_chain unless this is a new label whose UID is too large. */ if (INSN_UID (JUMP_LABEL (insn)) < max_jump_chain) { jump_chain[INSN_UID (insn)] = jump_chain[INSN_UID (JUMP_LABEL (insn))]; jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn; } changed = 1; next = insn; } } /* Cross jumping of unconditional jumps: a few differences. */ if (cross_jump && simplejump_p (insn)) { rtx newjpos, newlpos; rtx target; 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; } } /* This code was dead in the previous jump.c! */ if (cross_jump && GET_CODE (PATTERN (insn)) == RETURN) { /* Return insns all "jump to the same place" so we can cross-jump between any two of them. */ 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; } /* Delete extraneous line number notes. Note that two consecutive notes for different lines are not really extraneous. There should be some indication where that line belonged, even if it became empty. */ { rtx last_note = 0; for (insn = f; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) >= 0) { /* Delete this note if it is identical to previous note. */ if (last_note && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note) && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note)) { delete_insn (insn); continue; } last_note = insn; } } /* 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); } /* Report if control can fall through at the end of the function. */ if (insn && GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END) { can_reach_end = 1; delete_insn (insn); } /* Show JUMP_CHAIN no longer valid. */ jump_chain = 0;}/* LOOP_START is a NOTE_INSN_LOOP_BEG note that is followed by an unconditional jump. Assume that this unconditional jump is to the exit test code. If the code is sufficiently simple, make a copy of it before INSN, followed by a jump to the exit of the loop. Then delete the unconditional jump after INSN. Note that it is possible we can get confused here if the jump immediately after the loop start branches outside the loop but within an outer loop. If we are near the exit of that loop, we will copy its exit test. This will not generate incorrec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -