X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjump.c;h=dc81c52185147cc1bde376804e111ddf6eaa315d;hb=99617355e9cba5fc47f5283caefbe0f22ef8c578;hp=5567bb7ea665dc0c3010885333acf359a2d38fb8;hpb=8665fd86ec484f3d50512537c57b9e64fe2a98b8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/jump.c b/gcc/jump.c index 5567bb7ea66..dc81c521851 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -1,6 +1,7 @@ /* Optimize jump instructions, for GNU compiler. Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997 - 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. This file is part of GCC. @@ -63,15 +64,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA or even change what is live at any point. So perhaps let combiner do it. */ -static rtx next_nonnote_insn_in_loop (rtx); static void init_label_info (rtx); static void mark_all_labels (rtx); -static int duplicate_loop_exit_test (rtx); static void delete_computation (rtx); static void redirect_exp_1 (rtx *, rtx, rtx, rtx); -static int redirect_exp (rtx, rtx, rtx); -static void invert_exp_1 (rtx); -static int invert_exp (rtx); +static int invert_exp_1 (rtx, rtx); static int returnjump_p_1 (rtx *, void *); static void delete_prior_computation (rtx, rtx); @@ -92,7 +89,7 @@ rebuild_jump_labels (rtx f) count doesn't drop to zero. */ for (insn = forced_labels; insn; insn = XEXP (insn, 1)) - if (GET_CODE (XEXP (insn, 0)) == CODE_LABEL) + if (LABEL_P (XEXP (insn, 0))) LABEL_NUSES (XEXP (insn, 0))++; timevar_pop (TV_REBUILD_JUMP); } @@ -112,65 +109,16 @@ cleanup_barriers (void) for (insn = get_insns (); insn; insn = next) { next = NEXT_INSN (insn); - if (GET_CODE (insn) == BARRIER) + if (BARRIER_P (insn)) { prev = prev_nonnote_insn (insn); - if (GET_CODE (prev) == BARRIER) - delete_barrier (insn); + if (BARRIER_P (prev)) + delete_insn (insn); else if (prev != PREV_INSN (insn)) reorder_insns (insn, insn, prev); } } } - -/* Return the next insn after INSN that is not a NOTE and is in the loop, - i.e. when there is no such INSN before NOTE_INSN_LOOP_END return NULL_RTX. - This routine does not look inside SEQUENCEs. */ - -static rtx -next_nonnote_insn_in_loop (rtx insn) -{ - while (insn) - { - insn = NEXT_INSN (insn); - if (insn == 0 || GET_CODE (insn) != NOTE) - break; - if (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) - return NULL_RTX; - } - - return insn; -} - -void -copy_loop_headers (rtx f) -{ - rtx insn, next; - /* Now iterate optimizing jumps until nothing changes over one pass. */ - for (insn = f; insn; insn = next) - { - rtx temp, temp1; - - 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 (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG - && (temp1 = next_nonnote_insn_in_loop (insn)) != 0 - && any_uncondjump_p (temp1) && onlyjump_p (temp1)) - { - temp = PREV_INSN (insn); - if (duplicate_loop_exit_test (insn)) - { - next = NEXT_INSN (temp); - } - } - } -} void purge_line_number_notes (rtx f) @@ -183,7 +131,7 @@ purge_line_number_notes (rtx f) even if it became empty. */ for (insn = f; insn; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == NOTE) + if (NOTE_P (insn)) { if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG) /* Any previous line note was for the prologue; gdb wants a new @@ -193,8 +141,13 @@ purge_line_number_notes (rtx f) { /* Delete this note if it is identical to previous note. */ if (last_note +#ifdef USE_MAPPED_LOCATION + && NOTE_SOURCE_LOCATION (insn) == NOTE_SOURCE_LOCATION (last_note) +#else && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note) - && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note)) + && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note) +#endif +) { delete_related_insns (insn); continue; @@ -214,11 +167,11 @@ init_label_info (rtx f) rtx insn; for (insn = f; insn; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == CODE_LABEL) + if (LABEL_P (insn)) LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0); - else if (GET_CODE (insn) == JUMP_INSN) + else if (JUMP_P (insn)) JUMP_LABEL (insn) = 0; - else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN) + else if (NONJUMP_INSN_P (insn) || CALL_P (insn)) { rtx note, next; @@ -243,28 +196,8 @@ mark_all_labels (rtx f) for (insn = f; insn; insn = NEXT_INSN (insn)) if (INSN_P (insn)) { - if (GET_CODE (insn) == CALL_INSN - && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER) - { - mark_all_labels (XEXP (PATTERN (insn), 0)); - mark_all_labels (XEXP (PATTERN (insn), 1)); - mark_all_labels (XEXP (PATTERN (insn), 2)); - - /* Canonicalize the tail recursion label attached to the - CALL_PLACEHOLDER insn. */ - if (XEXP (PATTERN (insn), 3)) - { - rtx label_ref = gen_rtx_LABEL_REF (VOIDmode, - XEXP (PATTERN (insn), 3)); - mark_jump_label (label_ref, insn, 0); - XEXP (PATTERN (insn), 3) = XEXP (label_ref, 0); - } - - continue; - } - mark_jump_label (PATTERN (insn), insn, 0); - if (! INSN_DELETED_P (insn) && GET_CODE (insn) == JUMP_INSN) + if (! INSN_DELETED_P (insn) && JUMP_P (insn)) { /* When we know the LABEL_REF contained in a REG used in an indirect jump, we'll have a REG_LABEL note so that @@ -287,245 +220,6 @@ mark_all_labels (rtx f) } } } - -/* 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. - - Return 1 if we made the change, else 0. - - This is only safe immediately after a regscan pass because it uses the - values of regno_first_uid and regno_last_uid. */ - -static int -duplicate_loop_exit_test (rtx loop_start) -{ - rtx insn, set, reg, p, link; - rtx copy = 0, first_copy = 0; - int num_insns = 0; - rtx exitcode - = NEXT_INSN (JUMP_LABEL (next_nonnote_insn_in_loop (loop_start))); - rtx lastexit; - int max_reg = max_reg_num (); - rtx *reg_map = 0; - rtx loop_pre_header_label; - - /* Scan the exit code. We do not perform this optimization if any insn: - - is a CALL_INSN - is a CODE_LABEL - has a REG_RETVAL or REG_LIBCALL note (hard to adjust) - is a NOTE_INSN_LOOP_BEG because this means we have a nested loop - - We also do not do this if we find an insn with ASM_OPERANDS. While - this restriction should not be necessary, copying an insn with - ASM_OPERANDS can confuse asm_noperands in some cases. - - Also, don't do this if the exit code is more than 20 insns. */ - - for (insn = exitcode; - insn - && ! (GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END); - insn = NEXT_INSN (insn)) - { - switch (GET_CODE (insn)) - { - case CODE_LABEL: - case CALL_INSN: - return 0; - case NOTE: - - if (optimize < 2 - && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG - || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)) - /* If we were to duplicate this code, we would not move - the BLOCK notes, and so debugging the moved code would - be difficult. Thus, we only move the code with -O2 or - higher. */ - return 0; - - break; - case JUMP_INSN: - case INSN: - if (++num_insns > 20 - || find_reg_note (insn, REG_RETVAL, NULL_RTX) - || find_reg_note (insn, REG_LIBCALL, NULL_RTX)) - return 0; - break; - default: - break; - } - } - - /* Unless INSN is zero, we can do the optimization. */ - if (insn == 0) - return 0; - - lastexit = insn; - - /* See if any insn sets a register only used in the loop exit code and - not a user variable. If so, replace it with a new register. */ - for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) - if (GET_CODE (insn) == INSN - && (set = single_set (insn)) != 0 - && ((reg = SET_DEST (set), GET_CODE (reg) == REG) - || (GET_CODE (reg) == SUBREG - && (reg = SUBREG_REG (reg), GET_CODE (reg) == REG))) - && REGNO (reg) >= FIRST_PSEUDO_REGISTER - && REGNO_FIRST_UID (REGNO (reg)) == INSN_UID (insn)) - { - for (p = NEXT_INSN (insn); p != lastexit; p = NEXT_INSN (p)) - if (REGNO_LAST_UID (REGNO (reg)) == INSN_UID (p)) - break; - - if (p != lastexit) - { - /* We can do the replacement. Allocate reg_map if this is the - first replacement we found. */ - if (reg_map == 0) - reg_map = xcalloc (max_reg, sizeof (rtx)); - - REG_LOOP_TEST_P (reg) = 1; - - reg_map[REGNO (reg)] = gen_reg_rtx (GET_MODE (reg)); - } - } - loop_pre_header_label = gen_label_rtx (); - - /* Now copy each insn. */ - for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) - { - switch (GET_CODE (insn)) - { - case BARRIER: - copy = emit_barrier_before (loop_start); - break; - case NOTE: - /* Only copy line-number notes. */ - if (NOTE_LINE_NUMBER (insn) >= 0) - { - copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start); - NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn); - } - break; - - case INSN: - copy = emit_insn_before (copy_insn (PATTERN (insn)), loop_start); - if (reg_map) - replace_regs (PATTERN (copy), reg_map, max_reg, 1); - - mark_jump_label (PATTERN (copy), copy, 0); - INSN_LOCATOR (copy) = INSN_LOCATOR (insn); - - /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will - make them. */ - for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) - if (REG_NOTE_KIND (link) != REG_LABEL) - { - if (GET_CODE (link) == EXPR_LIST) - REG_NOTES (copy) - = copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link), - XEXP (link, 0), - REG_NOTES (copy))); - else - REG_NOTES (copy) - = copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link), - XEXP (link, 0), - REG_NOTES (copy))); - } - - if (reg_map && REG_NOTES (copy)) - replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); - break; - - case JUMP_INSN: - copy = emit_jump_insn_before (copy_insn (PATTERN (insn)), - loop_start); - INSN_LOCATOR (copy) = INSN_LOCATOR (insn); - if (reg_map) - replace_regs (PATTERN (copy), reg_map, max_reg, 1); - mark_jump_label (PATTERN (copy), copy, 0); - if (REG_NOTES (insn)) - { - REG_NOTES (copy) = copy_insn_1 (REG_NOTES (insn)); - if (reg_map) - replace_regs (REG_NOTES (copy), reg_map, max_reg, 1); - } - - /* Predict conditional jump that do make loop looping as taken. - Other jumps are probably exit conditions, so predict - them as untaken. */ - if (any_condjump_p (copy)) - { - rtx label = JUMP_LABEL (copy); - if (label) - { - /* The jump_insn after loop_start should be followed - by barrier and loopback label. */ - if (prev_nonnote_insn (label) - && (prev_nonnote_insn (prev_nonnote_insn (label)) - == next_nonnote_insn (loop_start))) - { - predict_insn_def (copy, PRED_LOOP_HEADER, TAKEN); - /* To keep pre-header, we need to redirect all loop - entrances before the LOOP_BEG note. */ - redirect_jump (copy, loop_pre_header_label, 0); - } - else - predict_insn_def (copy, PRED_LOOP_HEADER, NOT_TAKEN); - } - } - break; - - default: - abort (); - } - - /* Record the first insn we copied. We need it so that we can - scan the copied insns for new pseudo registers. */ - if (! first_copy) - first_copy = copy; - } - - /* Now clean up by emitting a jump to the end label and deleting the jump - at the start of the loop. */ - if (! copy || GET_CODE (copy) != BARRIER) - { - copy = emit_jump_insn_before (gen_jump (get_label_after (insn)), - loop_start); - - /* Record the first insn we copied. We need it so that we can - scan the copied insns for new pseudo registers. This may not - be strictly necessary since we should have copied at least one - insn above. But I am going to be safe. */ - if (! first_copy) - first_copy = copy; - - mark_jump_label (PATTERN (copy), copy, 0); - emit_barrier_before (loop_start); - } - - emit_label_before (loop_pre_header_label, loop_start); - - /* Now scan from the first insn we copied to the last insn we copied - (copy) for new pseudo registers. Do this after the code to jump to - the end label since that might create a new pseudo too. */ - reg_scan_update (first_copy, copy, max_reg); - - /* Mark the exit code as the virtual top of the converted loop. */ - emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode); - - delete_related_insns (next_nonnote_insn (loop_start)); - - /* Clean up. */ - if (reg_map) - free (reg_map); - - return 1; -} /* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end, notes between START and END out before START. START and END may be such @@ -547,14 +241,16 @@ squeeze_notes (rtx* startp, rtx* endp) for (insn = start; insn != past_end; insn = next) { next = NEXT_INSN (insn); - if (GET_CODE (insn) == NOTE + if (NOTE_P (insn) && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG - || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END - || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT - || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP)) + || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)) { + /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass. */ + gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG + && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_END); + if (insn == start) start = next; else @@ -594,7 +290,7 @@ get_label_before (rtx insn) or make a new one if there is none. */ label = prev_nonnote_insn (insn); - if (label == 0 || GET_CODE (label) != CODE_LABEL) + if (label == 0 || !LABEL_P (label)) { rtx prev = PREV_INSN (insn); @@ -616,7 +312,7 @@ get_label_after (rtx insn) or make a new one if there is none. */ label = next_nonnote_insn (insn); - if (label == 0 || GET_CODE (label) != CODE_LABEL) + if (label == 0 || !LABEL_P (label)) { label = gen_label_rtx (); emit_label_after (label, insn); @@ -645,9 +341,9 @@ reversed_comparison_code_parts (enum rtx_code code, rtx arg0, rtx arg1, rtx insn if (mode == VOIDmode) mode = GET_MODE (arg1); - /* First see if machine description supply us way to reverse the comparison. - Give it priority over everything else to allow machine description to do - tricks. */ + /* First see if machine description supplies us way to reverse the + comparison. Give it priority over everything else to allow + machine description to do tricks. */ if (GET_MODE_CLASS (mode) == MODE_CC && REVERSIBLE_CC_MODE (mode)) { @@ -698,7 +394,7 @@ reversed_comparison_code_parts (enum rtx_code code, rtx arg0, rtx arg1, rtx insn return UNKNOWN; for (prev = prev_nonnote_insn (insn); - prev != 0 && GET_CODE (prev) != CODE_LABEL; + prev != 0 && !LABEL_P (prev); prev = prev_nonnote_insn (prev)) { rtx set = set_of (arg0, prev); @@ -753,6 +449,20 @@ reversed_comparison_code (rtx comparison, rtx insn) XEXP (comparison, 0), XEXP (comparison, 1), insn); } + +/* Return comparison with reversed code of EXP. + Return NULL_RTX in case we fail to do the reversal. */ +rtx +reversed_comparison (rtx exp, enum machine_mode mode) +{ + enum rtx_code reversed_code = reversed_comparison_code (exp, NULL_RTX); + if (reversed_code == UNKNOWN) + return NULL_RTX; + else + return simplify_gen_relational (reversed_code, mode, VOIDmode, + XEXP (exp, 0), XEXP (exp, 1)); +} + /* Given an rtx-code for a comparison, return the code for the negated comparison. If no such code exists, return UNKNOWN. @@ -1041,7 +751,7 @@ comparison_dominates_p (enum rtx_code code1, enum rtx_code code2) int simplejump_p (rtx insn) { - return (GET_CODE (insn) == JUMP_INSN + return (JUMP_P (insn) && GET_CODE (PATTERN (insn)) == SET && GET_CODE (SET_DEST (PATTERN (insn))) == PC && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF); @@ -1073,8 +783,6 @@ condjump_p (rtx insn) || (GET_CODE (XEXP (x, 1)) == PC && (GET_CODE (XEXP (x, 2)) == LABEL_REF || GET_CODE (XEXP (x, 2)) == RETURN)))); - - return 0; } /* Return nonzero if INSN is a (possibly) conditional jump inside a @@ -1118,7 +826,7 @@ rtx pc_set (rtx insn) { rtx pat; - if (GET_CODE (insn) != JUMP_INSN) + if (!JUMP_P (insn)) return NULL_RTX; pat = PATTERN (insn); @@ -1143,6 +851,8 @@ any_uncondjump_p (rtx insn) return 0; if (GET_CODE (SET_SRC (x)) != LABEL_REF) return 0; + if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX)) + return 0; return 1; } @@ -1206,7 +916,7 @@ returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED) int returnjump_p (rtx insn) { - if (GET_CODE (insn) != JUMP_INSN) + if (!JUMP_P (insn)) return 0; return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL); } @@ -1219,7 +929,7 @@ onlyjump_p (rtx insn) { rtx set; - if (GET_CODE (insn) != JUMP_INSN) + if (!JUMP_P (insn)) return 0; set = single_set (insn); @@ -1287,6 +997,7 @@ sets_cc0_p (rtx x) /* Follow any unconditional jump at LABEL; return the ultimate label reached by any such chain of jumps. + Return null if the chain ultimately leads to a return instruction. If LABEL is not followed by a jump, return LABEL. If the chain loops or we can't find end, return LABEL, since that tells caller to avoid changing the insn. @@ -1305,12 +1016,12 @@ follow_jumps (rtx label) for (depth = 0; (depth < 10 && (insn = next_active_insn (value)) != 0 - && GET_CODE (insn) == JUMP_INSN + && JUMP_P (insn) && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn) && onlyjump_p (insn)) || GET_CODE (PATTERN (insn)) == RETURN) && (next = NEXT_INSN (insn)) - && GET_CODE (next) == BARRIER); + && BARRIER_P (next)); depth++) { /* Don't chain through the insn that jumps into a loop @@ -1320,7 +1031,7 @@ follow_jumps (rtx label) rtx tem; if (!reload_completed) for (tem = value; tem != insn; tem = NEXT_INSN (tem)) - if (GET_CODE (tem) == NOTE + if (NOTE_P (tem) && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG /* ??? Optional. Disables some optimizations, but makes gcov output more accurate with -O. */ @@ -1394,11 +1105,11 @@ mark_jump_label (rtx x, rtx insn, int in_mem) /* Ignore remaining references to unreachable labels that have been deleted. */ - if (GET_CODE (label) == NOTE + if (NOTE_P (label) && NOTE_LINE_NUMBER (label) == NOTE_INSN_DELETED_LABEL) break; - if (GET_CODE (label) != CODE_LABEL) + if (!LABEL_P (label)) abort (); /* Ignore references to labels of containing functions. */ @@ -1411,7 +1122,7 @@ mark_jump_label (rtx x, rtx insn, int in_mem) if (insn) { - if (GET_CODE (insn) == JUMP_INSN) + if (JUMP_P (insn)) JUMP_LABEL (insn) = label; else { @@ -1471,17 +1182,6 @@ delete_jump (rtx insn) delete_computation (insn); } -/* Verify INSN is a BARRIER and delete it. */ - -void -delete_barrier (rtx insn) -{ - if (GET_CODE (insn) != BARRIER) - abort (); - - delete_insn (insn); -} - /* Recursively delete prior insns that compute the value (used only by INSN which the caller is deleting) stored in the register mentioned by NOTE which is a REG_DEAD note associated with INSN. */ @@ -1493,15 +1193,15 @@ delete_prior_computation (rtx note, rtx insn) rtx reg = XEXP (note, 0); for (our_prev = prev_nonnote_insn (insn); - our_prev && (GET_CODE (our_prev) == INSN - || GET_CODE (our_prev) == CALL_INSN); + our_prev && (NONJUMP_INSN_P (our_prev) + || CALL_P (our_prev)); our_prev = prev_nonnote_insn (our_prev)) { rtx pat = PATTERN (our_prev); /* If we reach a CALL which is not calling a const function or the callee pops the arguments, then give up. */ - if (GET_CODE (our_prev) == CALL_INSN + if (CALL_P (our_prev) && (! CONST_OR_PURE_CALL_P (our_prev) || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL)) break; @@ -1514,14 +1214,14 @@ delete_prior_computation (rtx note, rtx insn) break; if (GET_CODE (pat) == USE - && GET_CODE (XEXP (pat, 0)) == INSN) + && NONJUMP_INSN_P (XEXP (pat, 0))) /* reorg creates USEs that look like this. We leave them alone because reorg needs them for its own purposes. */ break; if (reg_set_p (reg, pat)) { - if (side_effects_p (pat) && GET_CODE (our_prev) != CALL_INSN) + if (side_effects_p (pat) && !CALL_P (our_prev)) break; if (GET_CODE (pat) == PARALLEL) @@ -1544,7 +1244,7 @@ delete_prior_computation (rtx note, rtx insn) delete_computation (our_prev); } else if (GET_CODE (pat) == SET - && GET_CODE (SET_DEST (pat)) == REG) + && REG_P (SET_DEST (pat))) { int dest_regno = REGNO (SET_DEST (pat)); int dest_endregno @@ -1627,7 +1327,7 @@ delete_computation (rtx insn) will use them. So if the previous insn exists to set the CC's, delete it (unless it performs auto-increments, etc.). */ - if (prev && GET_CODE (prev) == INSN + if (prev && NONJUMP_INSN_P (prev) && sets_cc0_p (PATTERN (prev))) { if (sets_cc0_p (PATTERN (prev)) > 0 @@ -1647,7 +1347,7 @@ delete_computation (rtx insn) if (REG_NOTE_KIND (note) != REG_DEAD /* Verify that the REG_NOTE is legitimate. */ - || GET_CODE (XEXP (note, 0)) != REG) + || !REG_P (XEXP (note, 0))) continue; delete_prior_computation (note, insn); @@ -1667,7 +1367,7 @@ delete_computation (rtx insn) rtx delete_related_insns (rtx insn) { - int was_code_label = (GET_CODE (insn) == CODE_LABEL); + int was_code_label = (LABEL_P (insn)); rtx note; rtx next = NEXT_INSN (insn), prev = PREV_INSN (insn); @@ -1683,13 +1383,13 @@ delete_related_insns (rtx insn) /* If instruction is followed by a barrier, delete the barrier too. */ - if (next != 0 && GET_CODE (next) == BARRIER) + if (next != 0 && BARRIER_P (next)) delete_insn (next); /* 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 (JUMP_P (insn) && JUMP_LABEL (insn)) { rtx lab = JUMP_LABEL (insn), lab_next; @@ -1720,7 +1420,7 @@ delete_related_insns (rtx insn) /* Likewise if we're deleting a dispatch table. */ - if (GET_CODE (insn) == JUMP_INSN + if (JUMP_P (insn) && (GET_CODE (PATTERN (insn)) == ADDR_VEC || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)) { @@ -1737,15 +1437,15 @@ delete_related_insns (rtx insn) } /* Likewise for an ordinary INSN / CALL_INSN with a REG_LABEL note. */ - if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN) + if (NONJUMP_INSN_P (insn) || CALL_P (insn)) for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) if (REG_NOTE_KIND (note) == REG_LABEL /* This could also be a NOTE_INSN_DELETED_LABEL note. */ - && GET_CODE (XEXP (note, 0)) == CODE_LABEL) + && LABEL_P (XEXP (note, 0))) if (LABEL_NUSES (XEXP (note, 0)) == 0) delete_related_insns (XEXP (note, 0)); - while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE)) + while (prev && (INSN_DELETED_P (prev) || NOTE_P (prev))) prev = PREV_INSN (prev); /* If INSN was a label and a dispatch table follows it, @@ -1754,14 +1454,14 @@ delete_related_insns (rtx insn) if (was_code_label && NEXT_INSN (insn) != 0 - && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN + && JUMP_P (NEXT_INSN (insn)) && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC)) next = delete_related_insns (NEXT_INSN (insn)); /* If INSN was a label, delete insns following it if now unreachable. */ - if (was_code_label && prev && GET_CODE (prev) == BARRIER) + if (was_code_label && prev && BARRIER_P (prev)) { enum rtx_code code; while (next) @@ -1802,7 +1502,7 @@ delete_for_peephole (rtx from, rtx to) rtx next = NEXT_INSN (insn); rtx prev = PREV_INSN (insn); - if (GET_CODE (insn) != NOTE) + if (!NOTE_P (insn)) { INSN_DELETED_P (insn) = 1; @@ -1827,75 +1527,6 @@ delete_for_peephole (rtx from, rtx to) is also an unconditional jump in that case. */ } -/* We have determined that AVOIDED_INSN is never reached, and are - about to delete it. If the insn chain between AVOIDED_INSN and - FINISH contains more than one line from the current function, and - contains at least one operation, print a warning if the user asked - for it. If FINISH is NULL, look between AVOIDED_INSN and a LABEL. - - CSE and inlining can duplicate insns, so it's possible to get - spurious warnings from this. */ - -void -never_reached_warning (rtx avoided_insn, rtx finish) -{ - rtx insn; - rtx a_line_note = NULL; - int two_avoided_lines = 0, contains_insn = 0, reached_end = 0; - - if (!warn_notreached) - return; - - /* Back up to the first of any NOTEs preceding avoided_insn; flow passes - us the head of a block, a NOTE_INSN_BASIC_BLOCK, which often follows - the line note. */ - insn = avoided_insn; - while (1) - { - rtx prev = PREV_INSN (insn); - if (prev == NULL_RTX - || GET_CODE (prev) != NOTE) - break; - insn = prev; - } - - /* Scan forwards, looking at LINE_NUMBER notes, until we hit a LABEL - in case FINISH is NULL, otherwise until we run out of insns. */ - - for (; insn != NULL; insn = NEXT_INSN (insn)) - { - if ((finish == NULL && GET_CODE (insn) == CODE_LABEL) - || GET_CODE (insn) == BARRIER) - break; - - if (GET_CODE (insn) == NOTE /* A line number note? */ - && NOTE_LINE_NUMBER (insn) >= 0) - { - if (a_line_note == NULL) - a_line_note = insn; - else - two_avoided_lines |= (NOTE_LINE_NUMBER (a_line_note) - != NOTE_LINE_NUMBER (insn)); - } - else if (INSN_P (insn)) - { - if (reached_end) - break; - contains_insn = 1; - } - - if (insn == finish) - reached_end = 1; - } - if (two_avoided_lines && contains_insn) - { - location_t locus; - locus.file = NOTE_SOURCE_FILE (a_line_note); - locus.line = NOTE_LINE_NUMBER (a_line_note); - warning ("%Hwill never be executed", &locus); - } -} - /* Throughout LOC, redirect OLABEL to NLABEL. Treat null OLABEL or NLABEL as a return. Accrue modifications into the change group. */ @@ -1923,7 +1554,10 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn) } else if (code == RETURN && olabel == 0) { - x = gen_rtx_LABEL_REF (VOIDmode, nlabel); + if (nlabel) + x = gen_rtx_LABEL_REF (VOIDmode, nlabel); + else + x = gen_rtx_RETURN (VOIDmode); if (loc == &PATTERN (insn)) x = gen_rtx_SET (VOIDmode, pc_rtx, x); validate_change (insn, loc, x, 1); @@ -1952,25 +1586,6 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn) } } -/* Similar, but apply the change group and report success or failure. */ - -static int -redirect_exp (rtx olabel, rtx nlabel, rtx insn) -{ - rtx *loc; - - if (GET_CODE (PATTERN (insn)) == PARALLEL) - loc = &XVECEXP (PATTERN (insn), 0, 0); - else - loc = &PATTERN (insn); - - redirect_exp_1 (loc, olabel, nlabel, insn); - if (num_validated_changes () == 0) - return 0; - - return apply_change_group (); -} - /* Make JUMP go to NLABEL instead of where it jumps now. Accrue the modifications into the change group. Return false if we did not see how to do that. */ @@ -2004,14 +1619,28 @@ int redirect_jump (rtx jump, rtx nlabel, int delete_unused) { rtx olabel = JUMP_LABEL (jump); - rtx note; if (nlabel == olabel) return 1; - if (! redirect_exp (olabel, nlabel, jump)) + if (! redirect_jump_1 (jump, nlabel) || ! apply_change_group ()) return 0; + redirect_jump_2 (jump, olabel, nlabel, delete_unused, 0); + return 1; +} + +/* Fix up JUMP_LABEL and label ref counts after OLABEL has been replaced with + NLABEL in JUMP. If DELETE_UNUSED is non-negative, copy a + NOTE_INSN_FUNCTION_END found after OLABEL to the place after NLABEL. + If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref + count has dropped to zero. */ +void +redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused, + int invert) +{ + rtx note; + JUMP_LABEL (jump) = nlabel; if (nlabel) ++LABEL_NUSES (nlabel); @@ -2019,56 +1648,38 @@ redirect_jump (rtx jump, rtx nlabel, int delete_unused) /* Update labels in any REG_EQUAL note. */ if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX) { - if (nlabel && olabel) + if (!nlabel || (invert && !invert_exp_1 (XEXP (note, 0), jump))) + remove_note (jump, note); + else { - rtx dest = XEXP (note, 0); - - if (GET_CODE (dest) == IF_THEN_ELSE) - { - if (GET_CODE (XEXP (dest, 1)) == LABEL_REF - && XEXP (XEXP (dest, 1), 0) == olabel) - XEXP (XEXP (dest, 1), 0) = nlabel; - if (GET_CODE (XEXP (dest, 2)) == LABEL_REF - && XEXP (XEXP (dest, 2), 0) == olabel) - XEXP (XEXP (dest, 2), 0) = nlabel; - } - else - remove_note (jump, note); + redirect_exp_1 (&XEXP (note, 0), olabel, nlabel, jump); + confirm_change_group (); } - else - remove_note (jump, note); } /* If we're eliding the jump over exception cleanups at the end of a function, move the function end note so that -Wreturn-type works. */ if (olabel && nlabel && NEXT_INSN (olabel) - && GET_CODE (NEXT_INSN (olabel)) == NOTE - && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END) + && NOTE_P (NEXT_INSN (olabel)) + && NOTE_LINE_NUMBER (NEXT_INSN (olabel)) == NOTE_INSN_FUNCTION_END + && delete_unused >= 0) emit_note_after (NOTE_INSN_FUNCTION_END, nlabel); - if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused + if (olabel && --LABEL_NUSES (olabel) == 0 && delete_unused > 0 /* Undefined labels will remain outside the insn stream. */ && INSN_UID (olabel)) delete_related_insns (olabel); - - return 1; + if (invert) + invert_br_probabilities (jump); } -/* Invert the jump condition of rtx X contained in jump insn, INSN. - Accrue the modifications into the change group. */ - -static void -invert_exp_1 (rtx insn) +/* Invert the jump condition X contained in jump insn INSN. Accrue the + modifications into the change group. Return nonzero for success. */ +static int +invert_exp_1 (rtx x, rtx insn) { - RTX_CODE code; - rtx x = pc_set (insn); - - if (!x) - abort (); - x = SET_SRC (x); - - code = GET_CODE (x); + RTX_CODE code = GET_CODE (x); if (code == IF_THEN_ELSE) { @@ -2090,30 +1701,16 @@ invert_exp_1 (rtx insn) GET_MODE (comp), XEXP (comp, 0), XEXP (comp, 1)), 1); - return; + return 1; } tem = XEXP (x, 1); validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1); validate_change (insn, &XEXP (x, 2), tem, 1); + return 1; } else - abort (); -} - -/* Invert the jump condition of conditional jump insn, INSN. - - Return 1 if we can do so, 0 if we cannot find a way to do so that - matches a pattern. */ - -static int -invert_exp (rtx insn) -{ - invert_exp_1 (insn); - if (num_validated_changes () == 0) return 0; - - return apply_change_group (); } /* Invert the condition of the jump JUMP, and make it jump to label @@ -2124,14 +1721,18 @@ invert_exp (rtx insn) int invert_jump_1 (rtx jump, rtx nlabel) { + rtx x = pc_set (jump); int ochanges; ochanges = num_validated_changes (); - invert_exp_1 (jump); + if (!x || !invert_exp_1 (SET_SRC (x), jump)) + abort (); if (num_validated_changes () == ochanges) return 0; - return redirect_jump_1 (jump, nlabel); + /* redirect_jump_1 will fail of nlabel == olabel, and the current use is + in Pmode, so checking this is not merely an optimization. */ + return nlabel == JUMP_LABEL (jump) || redirect_jump_1 (jump, nlabel); } /* Invert the condition of the jump JUMP, and make it jump to label @@ -2140,30 +1741,14 @@ invert_jump_1 (rtx jump, rtx nlabel) int invert_jump (rtx jump, rtx nlabel, int delete_unused) { - /* We have to either invert the condition and change the label or - do neither. Either operation could fail. We first try to invert - the jump. If that succeeds, we try changing the label. If that fails, - we invert the jump back to what it was. */ - - if (! invert_exp (jump)) - return 0; + rtx olabel = JUMP_LABEL (jump); - if (redirect_jump (jump, nlabel, delete_unused)) + if (invert_jump_1 (jump, nlabel) && apply_change_group ()) { - /* Remove REG_EQUAL note if we have one. */ - rtx note = find_reg_note (jump, REG_EQUAL, NULL_RTX); - if (note) - remove_note (jump, note); - - invert_br_probabilities (jump); - + redirect_jump_2 (jump, olabel, nlabel, delete_unused, 1); return 1; } - - if (! invert_exp (jump)) - /* This should just be putting it back the way it was. */ - abort (); - + cancel_changes (0); return 0; } @@ -2191,9 +1776,9 @@ rtx_renumbered_equal_p (rtx x, rtx y) 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))) + if ((code == REG || (code == SUBREG && REG_P (SUBREG_REG (x)))) + && (REG_P (y) || (GET_CODE (y) == SUBREG + && REG_P (SUBREG_REG (y))))) { int reg_x = -1, reg_y = -1; int byte_x = 0, byte_y = 0; @@ -2370,7 +1955,7 @@ rtx_renumbered_equal_p (rtx x, rtx y) int true_regnum (rtx x) { - if (GET_CODE (x) == REG) + if (REG_P (x)) { if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0) return reg_renumber[REGNO (x)];