X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fjump.c;h=e61e2fba9d7d53b6f1da21dbbedc8bfd811a4255;hb=6776dec81181ac5268babea9d9e258e8c2ea02b7;hp=e3e2cdaa501b9efcfa439a0915946365269725ae;hpb=280566a7e7fa4e5436445b676a41507e8b6626db;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/jump.c b/gcc/jump.c index e3e2cdaa501..e61e2fba9d7 100644 --- a/gcc/jump.c +++ b/gcc/jump.c @@ -21,7 +21,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* This is the pathetic reminder of old fame of the jump-optimization pass - of the compiler. Now it contains basically set of utility function to + of the compiler. Now it contains basically a set of utility functions to operate with jumps. Each CODE_LABEL has a count of the times it is used @@ -68,11 +68,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA static void init_label_info (rtx); static void mark_all_labels (rtx); -static void delete_computation (rtx); static void redirect_exp_1 (rtx *, rtx, rtx, rtx); static int invert_exp_1 (rtx, rtx); static int returnjump_p_1 (rtx *, void *); -static void delete_prior_computation (rtx, rtx); /* Alternate entry into the jump optimizer. This entry point only rebuilds the JUMP_LABEL field in jumping insns and REG_LABEL notes in non-jumping @@ -104,7 +102,7 @@ rebuild_jump_labels (rtx f) This simple pass moves barriers and removes duplicates so that the old code is happy. */ -void +unsigned int cleanup_barriers (void) { rtx insn, next, prev; @@ -120,11 +118,12 @@ cleanup_barriers (void) reorder_insns (insn, insn, prev); } } + return 0; } struct tree_opt_pass pass_cleanup_barriers = { - NULL, /* name */ + "barriers", /* name */ NULL, /* gate */ cleanup_barriers, /* execute */ NULL, /* sub */ @@ -135,62 +134,7 @@ struct tree_opt_pass pass_cleanup_barriers = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ - 0 /* letter */ -}; - -void -purge_line_number_notes (void) -{ - rtx last_note = 0; - rtx insn; - /* 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. */ - - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - 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 - 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 -#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) -#endif -) - { - delete_related_insns (insn); - continue; - } - - last_note = insn; - } - } -} - -struct tree_opt_pass pass_purge_lineno_notes = -{ - NULL, /* name */ - NULL, /* gate */ - purge_line_number_notes, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - 0, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ + TODO_dump_func, /* todo_flags_finish */ 0 /* letter */ }; @@ -256,13 +200,38 @@ mark_all_labels (rtx f) } } } + + /* If we are in cfglayout mode, there may be non-insns between the + basic blocks. If those non-insns represent tablejump data, they + contain label references that we must record. */ + if (current_ir_type () == IR_RTL_CFGLAYOUT) + { + basic_block bb; + rtx insn; + FOR_EACH_BB (bb) + { + for (insn = bb->il.rtl->header; insn; insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + { + gcc_assert (JUMP_TABLE_DATA_P (insn)); + mark_jump_label (PATTERN (insn), insn, 0); + } + + for (insn = bb->il.rtl->footer; insn; insn = NEXT_INSN (insn)) + if (INSN_P (insn)) + { + gcc_assert (JUMP_TABLE_DATA_P (insn)); + mark_jump_label (PATTERN (insn), insn, 0); + } + } + } } -/* 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 - notes. Returns the values of the new starting and ending insns, which - may be different if the original ones were such notes. - Return true if there were only such notes and no real instructions. */ +/* Move all block-beg, block-end and loop-beg notes between START and END out + before START. START and END may be such notes. Returns the values of the + new starting and ending insns, which may be different if the original ones + were such notes. Return true if there were only such notes and no real + instructions. */ bool squeeze_notes (rtx* startp, rtx* endp) @@ -280,9 +249,7 @@ squeeze_notes (rtx* startp, rtx* endp) next = NEXT_INSN (insn); 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_BLOCK_BEG)) { /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass. */ gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG @@ -316,48 +283,6 @@ squeeze_notes (rtx* startp, rtx* endp) return false; } -/* Return the label before INSN, or put a new label there. */ - -rtx -get_label_before (rtx insn) -{ - rtx label; - - /* Find an existing label at this point - or make a new one if there is none. */ - label = prev_nonnote_insn (insn); - - if (label == 0 || !LABEL_P (label)) - { - rtx prev = PREV_INSN (insn); - - label = gen_label_rtx (); - emit_label_after (label, prev); - LABEL_NUSES (label) = 0; - } - return label; -} - -/* Return the label after INSN, or put a new label there. */ - -rtx -get_label_after (rtx insn) -{ - rtx label; - - /* Find an existing label at this point - or make a new one if there is none. */ - label = next_nonnote_insn (insn); - - if (label == 0 || !LABEL_P (label)) - { - label = gen_label_rtx (); - emit_label_after (label, insn); - LABEL_NUSES (label) = 0; - } - return label; -} - /* Given a comparison (CODE ARG0 ARG1), inside an insn, INSN, return a code of reversed comparison if it is possible to do so. Otherwise return UNKNOWN. UNKNOWN may be returned in case we are having CC_MODE compare and we don't @@ -1032,66 +957,6 @@ sets_cc0_p (rtx x) } #endif -/* 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. - - If RELOAD_COMPLETED is 0, we do not chain across a NOTE_INSN_LOOP_BEG or - a USE or CLOBBER. */ - -rtx -follow_jumps (rtx label) -{ - rtx insn; - rtx next; - rtx value = label; - int depth; - - for (depth = 0; - (depth < 10 - && (insn = next_active_insn (value)) != 0 - && JUMP_P (insn) - && ((JUMP_LABEL (insn) != 0 && any_uncondjump_p (insn) - && onlyjump_p (insn)) - || GET_CODE (PATTERN (insn)) == RETURN) - && (next = NEXT_INSN (insn)) - && BARRIER_P (next)); - 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 (!reload_completed) - for (tem = value; tem != insn; tem = NEXT_INSN (tem)) - if (NOTE_P (tem) - && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG - /* ??? Optional. Disables some optimizations, but makes - gcov output more accurate with -O. */ - || (flag_test_coverage && NOTE_LINE_NUMBER (tem) > 0))) - return value; - - /* If we have found a cycle, make the insn jump to itself. */ - if (JUMP_LABEL (insn) == label) - return label; - - tem = next_active_insn (JUMP_LABEL (insn)); - if (tem && (GET_CODE (PATTERN (tem)) == ADDR_VEC - || GET_CODE (PATTERN (tem)) == ADDR_DIFF_VEC)) - break; - - value = JUMP_LABEL (insn); - } - if (depth == 10) - return label; - return value; -} - - /* Find all CODE_LABELs referred to in X, and increment their use counts. If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced in INSN, then store one of them in JUMP_LABEL (INSN). @@ -1127,6 +992,12 @@ mark_jump_label (rtx x, rtx insn, int in_mem) in_mem = 1; break; + case SEQUENCE: + for (i = 0; i < XVECLEN (x, 0); i++) + mark_jump_label (PATTERN (XVECEXP (x, 0, i)), + XVECEXP (x, 0, i), 0); + return; + case SYMBOL_REF: if (!in_mem) return; @@ -1205,192 +1076,6 @@ mark_jump_label (rtx x, rtx insn, int in_mem) } } -/* 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. */ - -void -delete_jump (rtx insn) -{ - rtx set = single_set (insn); - - if (set && GET_CODE (SET_DEST (set)) == PC) - delete_computation (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. */ - -static void -delete_prior_computation (rtx note, rtx insn) -{ - rtx our_prev; - rtx reg = XEXP (note, 0); - - for (our_prev = prev_nonnote_insn (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 (CALL_P (our_prev) - && (! CONST_OR_PURE_CALL_P (our_prev) - || GET_CODE (pat) != SET || GET_CODE (SET_SRC (pat)) != CALL)) - break; - - /* If we reach a SEQUENCE, it is too complex to try to - do anything with it, so give up. We can be run during - and after reorg, so SEQUENCE rtl can legitimately show - up here. */ - if (GET_CODE (pat) == SEQUENCE) - break; - - if (GET_CODE (pat) == USE - && 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) && !CALL_P (our_prev)) - break; - - if (GET_CODE (pat) == PARALLEL) - { - /* If we find a SET of something else, we can't - delete the insn. */ - - int i; - - for (i = 0; i < XVECLEN (pat, 0); i++) - { - rtx part = XVECEXP (pat, 0, i); - - if (GET_CODE (part) == SET - && SET_DEST (part) != reg) - break; - } - - if (i == XVECLEN (pat, 0)) - delete_computation (our_prev); - } - else if (GET_CODE (pat) == SET - && REG_P (SET_DEST (pat))) - { - int dest_regno = REGNO (SET_DEST (pat)); - int dest_endregno - = (dest_regno - + (dest_regno < FIRST_PSEUDO_REGISTER - ? hard_regno_nregs[dest_regno] - [GET_MODE (SET_DEST (pat))] : 1)); - int regno = REGNO (reg); - int endregno - = (regno - + (regno < FIRST_PSEUDO_REGISTER - ? hard_regno_nregs[regno][GET_MODE (reg)] : 1)); - - if (dest_regno >= regno - && dest_endregno <= endregno) - delete_computation (our_prev); - - /* We may have a multi-word hard register and some, but not - all, of the words of the register are needed in subsequent - insns. Write REG_UNUSED notes for those parts that were not - needed. */ - else if (dest_regno <= regno - && dest_endregno >= endregno) - { - int i; - - REG_NOTES (our_prev) - = gen_rtx_EXPR_LIST (REG_UNUSED, reg, - REG_NOTES (our_prev)); - - for (i = dest_regno; i < dest_endregno; i++) - if (! find_regno_note (our_prev, REG_UNUSED, i)) - break; - - if (i == dest_endregno) - delete_computation (our_prev); - } - } - - break; - } - - /* If PAT references the register that dies here, it is an - additional use. Hence any prior SET isn't dead. However, this - insn becomes the new place for the REG_DEAD note. */ - if (reg_overlap_mentioned_p (reg, pat)) - { - XEXP (note, 1) = REG_NOTES (our_prev); - REG_NOTES (our_prev) = note; - break; - } - } -} - -/* Delete INSN and recursively delete insns that compute values used only - by INSN. This uses the REG_DEAD notes computed during flow analysis. - If we are running before flow.c, we need do nothing since flow.c will - delete dead code. We also can't know if the registers being used are - dead or not at this point. - - Otherwise, look at all our REG_DEAD notes. If a previous insn does - nothing other than set a register that dies in this insn, we can delete - that insn as well. - - On machines with CC0, if CC0 is used in this insn, we may be able to - delete the insn that set it. */ - -static void -delete_computation (rtx insn) -{ - rtx note, next; - -#ifdef HAVE_cc0 - if (reg_referenced_p (cc0_rtx, PATTERN (insn))) - { - rtx prev = prev_nonnote_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.). */ - if (prev && NONJUMP_INSN_P (prev) - && sets_cc0_p (PATTERN (prev))) - { - if (sets_cc0_p (PATTERN (prev)) > 0 - && ! side_effects_p (PATTERN (prev))) - delete_computation (prev); - else - /* Otherwise, show that cc0 won't be used. */ - REG_NOTES (prev) = gen_rtx_EXPR_LIST (REG_UNUSED, - cc0_rtx, REG_NOTES (prev)); - } - } -#endif - - for (note = REG_NOTES (insn); note; note = next) - { - next = XEXP (note, 1); - - if (REG_NOTE_KIND (note) != REG_DEAD - /* Verify that the REG_NOTE is legitimate. */ - || !REG_P (XEXP (note, 0))) - continue; - - delete_prior_computation (note, insn); - } - - delete_related_insns (insn); -} /* Delete insn INSN from the chain of insns and update label ref counts and delete insns now unreachable. @@ -1503,8 +1188,7 @@ delete_related_insns (rtx insn) while (next) { code = GET_CODE (next); - if (code == NOTE - && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END) + if (code == NOTE) next = NEXT_INSN (next); /* Keep going past other deleted labels to delete what follows. */ else if (code == CODE_LABEL && INSN_DELETED_P (next)) @@ -1667,8 +1351,7 @@ redirect_jump (rtx jump, rtx nlabel, int delete_unused) } /* 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. + NLABEL in JUMP. If DELETE_UNUSED is positive, delete related insn to OLABEL if its ref count has dropped to zero. */ void @@ -1677,6 +1360,10 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused, { rtx note; + /* Negative DELETE_UNUSED used to be used to signalize behavior on + moving FUNCTION_END note. Just sanity check that no user still worry + about this. */ + gcc_assert (delete_unused >= 0); JUMP_LABEL (jump) = nlabel; if (nlabel) ++LABEL_NUSES (nlabel); @@ -1693,15 +1380,6 @@ redirect_jump_2 (rtx jump, rtx olabel, rtx nlabel, int delete_unused, } } - /* 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) - && 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 > 0 /* Undefined labels will remain outside the insn stream. */ && INSN_UID (olabel)) @@ -1879,6 +1557,7 @@ rtx_renumbered_equal_p (rtx x, rtx y) case ADDR_VEC: case ADDR_DIFF_VEC: case CONST_INT: + case CONST_DOUBLE: return 0; case LABEL_REF: @@ -1993,7 +1672,11 @@ true_regnum (rtx x) if (GET_CODE (x) == SUBREG) { int base = true_regnum (SUBREG_REG (x)); - if (base >= 0 && base < FIRST_PSEUDO_REGISTER) + if (base >= 0 + && base < FIRST_PSEUDO_REGISTER + && subreg_offset_representable_p (REGNO (SUBREG_REG (x)), + GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x), GET_MODE (x))) return base + subreg_regno_offset (REGNO (SUBREG_REG (x)), GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x), GET_MODE (x));