Paolo Bonzini - [PATCH] Move some functions used only in reorg.c (original) (raw)

This is the mail archive of the gcc-patches@gcc.gnu.orgmailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

These functions from jump.c are used only in reorg.c; one of them actually (get_label_after) is completely unused.Since I don't have access to a target with delay slots, I tested this with a cross to sparc-elf; I built a large collection of .i and .f (fortran 77) files and found no difference in assembly code.Ok to zap them?Paolo

2007-02-15 Paolo Bonzini bonzini@gnu.org

* jump.c (get_label_after): Delete.
(get_label_before, delete_computation, delete_jump,
delete_prior_computation, follow_jumps): Move...
* reorg.c (delete_computation, delete_prior_computation): ... here...
(get_label_before, delete_jump): ... making these static ...
(follow_jumps): ... and simplifying this since it only runs after
reload.
* rtl.h (get_label_after, get_label_before, delete_jump,
follow_jumps): Delete prototypes.

Index: gcc-test-df/base-gcc-src/gcc/reorg.c

--- gcc-test-df/base-gcc-src/gcc/reorg.c (revision 121997) +++ gcc-test-df/base-gcc-src/gcc/reorg.c (working copy) @@ -1972,6 +1972,28 @@ update_reg_unused_notes (rtx insn, rtx r } } +/* Return the label before INSN, or put a new label there. / + +static 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; +} + / Scan a function looking for insns that need a delay slot and find insns to put into the delay slot. @@ -2468,6 +2490,50 @@ fill_simple_delay_slots (int non_jumps_p #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. / + +static 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++) + { + rtx tem; + + /* 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; +} + /* Try to find insns to place in delay slots. INSN is the jump needing SLOTS_TO_FILL delay slots. It tests CONDITION @@ -3037,6 +3103,196 @@ fill_eager_delay_slots (void) } } +static void delete_computation (rtx 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); +} + +/ 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. / + +static void +delete_jump (rtx insn) +{ + rtx set = single_set (insn); + + if (set && GET_CODE (SET_DEST (set)) == PC) + delete_computation (insn); +} + + / Once we have tried two ways to fill a delay slot, make a pass over the code to try to improve the results and to do such things as more jump threading. */ Index: gcc-test-df/base-gcc-src/gcc/jump.c

--- gcc-test-df/base-gcc-src/gcc/jump.c (revision 121997) +++ gcc-test-df/base-gcc-src/gcc/jump.c (working copy) @@ -285,48 +285,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;

#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 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);

-}

-/* 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);

-}

-/* 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.

-#endif

/* Delete insn INSN from the chain of insns and update label ref counts and delete insns now unreachable. Index: gcc-test-df/base-gcc-src/gcc/rtl.h

--- gcc-test-df/base-gcc-src/gcc/rtl.h (revision 121997) +++ gcc-test-df/base-gcc-src/gcc/rtl.h (working copy) @@ -1598,10 +1598,6 @@ extern unsigned int cleanup_barriers (vo /* In jump.c */ extern bool squeeze_notes (rtx *, rtx *); extern rtx delete_related_insns (rtx); -extern void delete_jump (rtx); -extern rtx get_label_before (rtx); -extern rtx get_label_after (rtx); -extern rtx follow_jumps (rtx);

/* In recog.c */ extern rtx *find_constant_term_loc (rtx *);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]