-
- /* Quit now if we just wanted to rebuild the JUMP_LABEL and REG_LABEL
- notes and recompute LABEL_NUSES. */
- if (mark_labels_only)
- goto end;
-
- delete_barrier_successors (f);
-
- last_insn = delete_unreferenced_labels (f);
-
- if (noop_moves)
- delete_noop_moves (f);
-
- /* Now iterate optimizing jumps until nothing changes over one pass. */
- changed = 1;
- old_max_reg = max_reg_num ();
- while (changed)
- {
- changed = 0;
-
- for (insn = f; insn; insn = next)
- {
- rtx reallabelprev;
- rtx temp, temp1, temp2 = NULL_RTX;
- rtx temp4 ATTRIBUTE_UNUSED;
- rtx nlabel;
- int this_is_any_uncondjump;
- int this_is_any_condjump;
- int this_is_onlyjump;
-
- next = NEXT_INSN (insn);
-
- /* See if this is a NOTE_INSN_LOOP_BEG followed by an unconditional
- jump. Try to optimize by duplicating the loop exit test if so.
- This is only safe immediately after regscan, because it uses
- the values of regno_first_uid and regno_last_uid. */
- if (after_regscan && GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- && (temp1 = next_nonnote_insn (insn)) != 0
- && any_uncondjump_p (temp1)
- && onlyjump_p (temp1))
- {
- temp = PREV_INSN (insn);
- if (duplicate_loop_exit_test (insn))
- {
- changed = 1;
- next = NEXT_INSN (temp);
- continue;
- }
- }
-
- if (GET_CODE (insn) != JUMP_INSN)
- continue;
-
- this_is_any_condjump = any_condjump_p (insn);
- this_is_any_uncondjump = any_uncondjump_p (insn);
- this_is_onlyjump = onlyjump_p (insn);
-
- /* Tension the labels in dispatch tables. */
-
- if (GET_CODE (PATTERN (insn)) == ADDR_VEC)
- changed |= tension_vector_labels (PATTERN (insn), 0);
- if (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
- changed |= tension_vector_labels (PATTERN (insn), 1);
-
- /* See if this jump goes to another jump and redirect if so. */
- nlabel = follow_jumps (JUMP_LABEL (insn));
- if (nlabel != JUMP_LABEL (insn))
- changed |= redirect_jump (insn, nlabel, 1);
-
- if (! optimize || minimal)
- continue;
-
- /* If a dispatch table always goes to the same place,
- get rid of it and replace the insn that uses it. */
-
- if (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
- {
- int i;
- rtx pat = PATTERN (insn);
- int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
- int len = XVECLEN (pat, diff_vec_p);
- rtx dispatch = prev_real_insn (insn);
- rtx set;
-
- for (i = 0; i < len; i++)
- if (XEXP (XVECEXP (pat, diff_vec_p, i), 0)
- != XEXP (XVECEXP (pat, diff_vec_p, 0), 0))
- break;
-
- if (i == len
- && dispatch != 0
- && GET_CODE (dispatch) == JUMP_INSN
- && JUMP_LABEL (dispatch) != 0
- /* Don't mess with a casesi insn.
- XXX according to the comment before computed_jump_p(),
- all casesi insns should be a parallel of the jump
- and a USE of a LABEL_REF. */
- && ! ((set = single_set (dispatch)) != NULL
- && (GET_CODE (SET_SRC (set)) == IF_THEN_ELSE))
- && next_real_insn (JUMP_LABEL (dispatch)) == insn)
- {
- redirect_tablejump (dispatch,
- XEXP (XVECEXP (pat, diff_vec_p, 0), 0));
- changed = 1;
- }
- }
-
- reallabelprev = prev_active_insn (JUMP_LABEL (insn));
-
- /* Detect jump to following insn. */
- if (reallabelprev == insn
- && (this_is_any_condjump || this_is_any_uncondjump)
- && this_is_onlyjump)
- {
- next = next_real_insn (JUMP_LABEL (insn));
- delete_jump (insn);
-
- /* Remove the "inactive" but "real" insns (i.e. uses and
- clobbers) in between here and there. */
- temp = insn;
- while ((temp = next_real_insn (temp)) != next)
- delete_insn (temp);
-
- changed = 1;
- continue;
- }
-
- /* Detect a conditional jump going to the same place
- as an immediately following unconditional jump. */
- else if (this_is_any_condjump && this_is_onlyjump
- && (temp = next_active_insn (insn)) != 0
- && simplejump_p (temp)
- && (next_active_insn (JUMP_LABEL (insn))
- == next_active_insn (JUMP_LABEL (temp))))
- {
- /* Don't mess up test coverage analysis. */
- temp2 = temp;
- if (flag_test_coverage && !reload_completed)
- for (temp2 = insn; temp2 != temp; temp2 = NEXT_INSN (temp2))
- if (GET_CODE (temp2) == NOTE && NOTE_LINE_NUMBER (temp2) > 0)
- break;
-
- if (temp2 == temp)
- {
- /* Ensure that we jump to the later of the two labels.
- Consider:
-
- if (test) goto L2;
- goto L1;
- ...
- L1:
- (clobber return-reg)
- L2:
- (use return-reg)
-
- If we leave the goto L1, we'll incorrectly leave
- return-reg dead for TEST true. */
-
- temp2 = next_active_insn (JUMP_LABEL (insn));
- if (!temp2)
- temp2 = get_last_insn ();
- if (GET_CODE (temp2) != CODE_LABEL)
- temp2 = prev_label (temp2);
- if (temp2 != JUMP_LABEL (temp))
- redirect_jump (temp, temp2, 1);
-
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
-
- /* Detect a conditional jump jumping over an unconditional jump. */
-
- else if (this_is_any_condjump
- && reallabelprev != 0
- && GET_CODE (reallabelprev) == JUMP_INSN
- && prev_active_insn (reallabelprev) == insn
- && no_labels_between_p (insn, reallabelprev)
- && any_uncondjump_p (reallabelprev)
- && onlyjump_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);
-
- if (prev_label)
- ++LABEL_NUSES (prev_label);
-
- if (invert_jump (insn, JUMP_LABEL (reallabelprev), 1))
- {
- /* 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);
- changed = 1;
- }
-
- /* We can now safely delete the label if it is unreferenced
- since the delete_insn above has deleted the BARRIER. */
- if (prev_label && --LABEL_NUSES (prev_label) == 0)
- delete_insn (prev_label);
-
- next = NEXT_INSN (insn);
- }
-
- /* If we have an unconditional jump preceded by a USE, try to put
- the USE before the target and jump there. This simplifies many
- of the optimizations below since we don't have to worry about
- dealing with these USE insns. We only do this if the label
- being branch to already has the identical USE or if code
- never falls through to that label. */
-
- else if (this_is_any_uncondjump
- && (temp = prev_nonnote_insn (insn)) != 0
- && GET_CODE (temp) == INSN
- && GET_CODE (PATTERN (temp)) == USE
- && (temp1 = prev_nonnote_insn (JUMP_LABEL (insn))) != 0
- && (GET_CODE (temp1) == BARRIER
- || (GET_CODE (temp1) == INSN
- && rtx_equal_p (PATTERN (temp), PATTERN (temp1))))
- /* Don't do this optimization if we have a loop containing
- only the USE instruction, and the loop start label has
- a usage count of 1. This is because we will redo this
- optimization everytime through the outer loop, and jump
- opt will never exit. */
- && ! ((temp2 = prev_nonnote_insn (temp)) != 0
- && temp2 == JUMP_LABEL (insn)
- && LABEL_NUSES (temp2) == 1))
- {
- if (GET_CODE (temp1) == BARRIER)
- {
- emit_insn_after (PATTERN (temp), temp1);
- temp1 = NEXT_INSN (temp1);
- }
-
- delete_insn (temp);
- redirect_jump (insn, get_label_before (temp1), 1);
- reallabelprev = prev_real_insn (temp1);
- changed = 1;
- next = NEXT_INSN (insn);
- }
-
-#ifdef HAVE_trap
- /* Detect a conditional jump jumping over an unconditional trap. */
- if (HAVE_trap
- && this_is_any_condjump && this_is_onlyjump
- && reallabelprev != 0
- && GET_CODE (reallabelprev) == INSN
- && GET_CODE (PATTERN (reallabelprev)) == TRAP_IF
- && TRAP_CONDITION (PATTERN (reallabelprev)) == const_true_rtx
- && prev_active_insn (reallabelprev) == insn
- && no_labels_between_p (insn, reallabelprev)
- && (temp2 = get_condition (insn, &temp4))
- && ((reversed_code = reversed_comparison_code (temp2, insn))
- != UNKNOWN))
- {
- rtx new = gen_cond_trap (reversed_code,
- XEXP (temp2, 0), XEXP (temp2, 1),
- TRAP_CODE (PATTERN (reallabelprev)));
-
- if (new)
- {
- emit_insn_before (new, temp4);
- delete_insn (reallabelprev);
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
- /* Detect a jump jumping to an unconditional trap. */
- else if (HAVE_trap && this_is_onlyjump
- && (temp = next_active_insn (JUMP_LABEL (insn)))
- && GET_CODE (temp) == INSN
- && GET_CODE (PATTERN (temp)) == TRAP_IF
- && (this_is_any_uncondjump
- || (this_is_any_condjump
- && (temp2 = get_condition (insn, &temp4)))))
- {
- rtx tc = TRAP_CONDITION (PATTERN (temp));
-
- if (tc == const_true_rtx
- || (! this_is_any_uncondjump && rtx_equal_p (temp2, tc)))
- {
- rtx new;
- /* Replace an unconditional jump to a trap with a trap. */
- if (this_is_any_uncondjump)
- {
- emit_barrier_after (emit_insn_before (gen_trap (), insn));
- delete_jump (insn);
- changed = 1;
- continue;
- }
- new = gen_cond_trap (GET_CODE (temp2), XEXP (temp2, 0),
- XEXP (temp2, 1),
- TRAP_CODE (PATTERN (temp)));
- if (new)
- {
- emit_insn_before (new, temp4);
- delete_jump (insn);
- changed = 1;
- continue;
- }
- }
- /* If the trap condition and jump condition are mutually
- exclusive, redirect the jump to the following insn. */
- else if (GET_RTX_CLASS (GET_CODE (tc)) == '<'
- && this_is_any_condjump
- && swap_condition (GET_CODE (temp2)) == GET_CODE (tc)
- && rtx_equal_p (XEXP (tc, 0), XEXP (temp2, 0))
- && rtx_equal_p (XEXP (tc, 1), XEXP (temp2, 1))
- && redirect_jump (insn, get_label_after (temp), 1))
- {
- changed = 1;
- continue;
- }
- }
-#endif
- else
- {
- /* 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. */
- PATTERN (insn) = gen_jump (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)
- {
- if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG)
- /* Any previous line note was for the prologue; gdb wants a new
- note after the prologue even if it is for the same line. */
- last_note = NULL_RTX;
- else if (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;
- }
- }
- }
-
-end:
- /* Clean up. */
- free (jump_chain);
- jump_chain = 0;