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] |
- From: Paolo Bonzini
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 15 Feb 2007 17:15:07 +0100
- Subject: [PATCH] Move some functions used only in reorg.c
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;
- /* 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 @@ -1001,61 +959,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 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++)
- {
rtx tem;
if (!reload_completed && flag_test_coverage)
- {
/* ??? Optional. Disables some optimizations, but makes
gcov output more accurate with -O. */
for (tem = value; tem != insn; tem = NEXT_INSN (tem))
if (NOTE_P (tem) && 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). @@ -1169,192 +1072,6 @@ mark_jump_label (rtx x, rtx insn, int in } }
-/* 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. 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 *);
- Follow-Ups:
- Re: [PATCH] Move some functions used only in reorg.c
* From: Richard Henderson
- Re: [PATCH] Move some functions used only in reorg.c
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |