This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATH: reorg.c improve optimize_skip (second try)
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATH: reorg.c improve optimize_skip (second try)
- From: Herman ten Brugge <Haj dot Ten dot Brugge at net dot HCC dot nl>
- Date: Mon, 31 Jul 2000 18:15:59 +0100 (WEST)
Hello,
This is the second time I am trying to send this patch. Could some one
review this patch?
Text from last patch:
I generated some new code for reorg.c to handle targets with more than
1 delay slot. Currently only the c4x (3 delay slots) has these. I know
some one who is working on the sharc port (2 delay slots) for gcc that
also uses these patches.
I optimized the routine optimize_skip to handle more than 1 delay slot.
The routine is only called for empty delay lists. We cannot generate
a skip insn if we allready have some delay insns in the delay list
because we could annul them.
We also do not return any insns from optimize_skip is we could not
find a skip. We do this because we only checked for annul_true/annul_false
and not for normal delay insns. Normal delay insns are prefered because
they allways execute in the delay list.
Herman.
2000-07-31 Herman A.J. ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
* reorg.c (optimize_skip) Handle targets with more than 1 delay slot.
--- reorg.c.org Mon Jul 31 17:48:33 2000
+++ reorg.c Mon Jul 31 17:48:42 2000
@@ -190,7 +190,7 @@ static rtx delete_from_delay_slot PARAMS
static void delete_scheduled_jump PARAMS ((rtx));
static void note_delay_statistics PARAMS ((int, int));
#if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
-static rtx optimize_skip PARAMS ((rtx));
+static rtx optimize_skip PARAMS ((rtx, int, int *));
#endif
static int get_jump_flags PARAMS ((rtx, rtx));
static int rare_destination PARAMS ((rtx));
@@ -692,83 +692,145 @@ note_delay_statistics (slots_filled, ind
L1: L1:
Bra L2 Bra L2
- INSN is a JUMP_INSN.
-
- This should be expanded to skip over N insns, where N is the number
- of delay slots required. */
+ INSN is a JUMP_INSN. */
static rtx
-optimize_skip (insn)
+optimize_skip (insn, slots_to_fill, slots_filled)
register rtx insn;
+ int slots_to_fill;
+ int *slots_filled;
{
register rtx trial = next_nonnote_insn (insn);
- rtx next_trial = next_active_insn (trial);
+ rtx next_trial;
+ rtx list;
+ rtx next_active;
rtx delay_list = 0;
- rtx target_label;
- int flags;
+ int slot;
+ int flags = get_jump_flags (insn, JUMP_LABEL (insn));
- flags = get_jump_flags (insn, JUMP_LABEL (insn));
+ for (slot = 0; slot < slots_to_fill ; slot++, trial = next_trial)
+ {
+ next_trial = next_nonnote_insn (trial);
- if (trial == 0
- || GET_CODE (trial) != INSN
- || GET_CODE (PATTERN (trial)) == SEQUENCE
- || recog_memoized (trial) < 0
- || (! eligible_for_annul_false (insn, 0, trial, flags)
- && ! eligible_for_annul_true (insn, 0, trial, flags)))
- return 0;
+ if (trial == 0
+ || GET_CODE (trial) != INSN
+ || GET_CODE (PATTERN (trial)) == SEQUENCE
+ || recog_memoized (trial) < 0
+ || (! eligible_for_annul_false (insn, slot, trial, flags)
+ && ! eligible_for_annul_true (insn, slot, trial, flags)))
+ return 0;
- /* There are two cases where we are just executing one insn (we assume
- here that a branch requires only one insn; this should be generalized
- at some point): Where the branch goes around a single insn or where
- we have one insn followed by a branch to the same label we branch to.
- In both of these cases, inverting the jump and annulling the delay
- slot give the same effect in fewer insns. */
- if ((next_trial == next_active_insn (JUMP_LABEL (insn))
- && ! (next_trial == 0 && current_function_epilogue_delay_list != 0))
- || (next_trial != 0
- && GET_CODE (next_trial) == JUMP_INSN
- && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
- && (simplejump_p (next_trial)
- || GET_CODE (PATTERN (next_trial)) == RETURN)))
- {
- if (eligible_for_annul_false (insn, 0, trial, flags))
- {
- if (invert_jump (insn, JUMP_LABEL (insn), 1))
- INSN_FROM_TARGET_P (trial) = 1;
- else if (! eligible_for_annul_true (insn, 0, trial, flags))
- return 0;
- }
+ /* The trial is a valid annul_true or annul_false insn so add to
+ the delay_list. */
+ delay_list = add_to_delay_list (trial, delay_list);
+
+ /* There are two cases where we can generate a skip insn (we assume
+ here that a branch requires only one insn; this should be generalized
+ at some point): Where the branch goes around a single insn or where
+ we have one insn followed by a branch to the same label we branch to.
+ In both of these cases, inverting the jump and annulling the delay
+ slot give the same effect in fewer insns. */
+
+ next_active = next_active_insn (trial);
+ if ((next_active == next_active_insn (JUMP_LABEL (insn))
+ && ! (next_active == 0 && current_function_epilogue_delay_list != 0))
+ || (next_active != 0
+ && GET_CODE (next_active) == JUMP_INSN
+ && JUMP_LABEL (insn) == JUMP_LABEL (next_active)
+ && (simplejump_p (next_active)
+ || GET_CODE (PATTERN (next_active)) == RETURN)))
+ {
+ /* Check if all insns in the list are allowed for annul_false. */
+ for (slot = 0, list = delay_list; list; list = XEXP (list, 1))
+ if (!eligible_for_annul_false (insn, slot++, XEXP (list, 0),
+ flags))
+ break;
- delay_list = add_to_delay_list (trial, NULL_RTX);
- next_trial = next_active_insn (trial);
- update_block (trial, trial);
- delete_insn (trial);
-
- /* Also, if we are targeting an unconditional
- branch, thread our jump to the target of that branch. Don't
- change this into a RETURN here, because it may not accept what
- we have in the delay slot. We'll fix this up later. */
- if (next_trial && GET_CODE (next_trial) == JUMP_INSN
- && (simplejump_p (next_trial)
- || GET_CODE (PATTERN (next_trial)) == RETURN))
- {
- target_label = JUMP_LABEL (next_trial);
- if (target_label == 0)
- target_label = find_end_label ();
-
- /* Recompute the flags based on TARGET_LABEL since threading
- the jump to TARGET_LABEL may change the direction of the
- jump (which may change the circumstances in which the
- delay slot is nullified). */
- flags = get_jump_flags (insn, target_label);
- if (eligible_for_annul_true (insn, 0, trial, flags))
- reorg_redirect_jump (insn, target_label);
- }
+ if (!list)
+ {
+ /* All insns did match annul_false. Now try to invert
+ the jump. */
+ if (invert_jump (insn, JUMP_LABEL (insn), 1), 1)
+ {
+ /* If we did invert the jump we have found a valid skip and
+ have to mark all insns in the list. The insns should only
+ be executed if the branch is taken. */
+ for (list = delay_list; list; list = XEXP (list, 1))
+ INSN_FROM_TARGET_P (XEXP (list, 0)) = 1;
+ }
+ else
+ {
+ /* If we could not invert the jump check if all insns in
+ the list are allowed for annul_true.
+ Fail if some do not match. */
+ for (slot = 0, list = delay_list; list; list = XEXP (list, 1))
+ if (!eligible_for_annul_true (insn, slot++, XEXP (list, 0),
+ flags))
+ return 0;
+ }
+ }
+ else
+ {
+ /* If not all insns match annul_false. Check if all insns
+ in the list are allowed for annul_true.
+ Fail if some do not match. */
+ for (slot = 0, list = delay_list; list; list = XEXP (list, 1))
+ if (!eligible_for_annul_true (insn, slot++, XEXP (list, 0),
+ flags))
+ return 0;
+ }
- INSN_ANNULLED_BRANCH_P (insn) = 1;
+ /* We found a valid list. Delete the insns. */
+ for (list = delay_list; list; list = XEXP (list, 1))
+ {
+ rtx tmp = XEXP (list, 0);
+
+ update_block (tmp, tmp);
+ delete_insn (tmp);
+ (*slots_filled)++;
+ }
+
+ /* Also, if we are targeting an unconditional
+ branch, thread our jump to the target of that branch. Don't
+ change this into a RETURN here, because it may not accept what
+ we have in the delay slot. We'll fix this up later. */
+ if (next_active && GET_CODE (next_active) == JUMP_INSN
+ && (simplejump_p (next_active)
+ || GET_CODE (PATTERN (next_active)) == RETURN))
+ {
+ rtx target_label = JUMP_LABEL (next_active);
+ if (target_label == 0)
+ target_label = find_end_label ();
+
+ /* Recompute the flags based on TARGET_LABEL since threading
+ the jump to TARGET_LABEL may change the direction of the
+ jump (which may change the circumstances in which the
+ delay slot is nullified). */
+ flags = get_jump_flags (insn, target_label);
+ for (slot = 0, trial = delay_list;
+ trial;
+ slot++, trial = XEXP (trial, 1))
+ {
+ rtx tmp = XEXP (trial, 0);
+
+ if (INSN_FROM_TARGET_P (tmp)
+ || !eligible_for_annul_true (insn, slot, tmp, flags))
+ break;
+ }
+ if (!trial)
+ reorg_redirect_jump (insn, target_label);
+ }
+
+ INSN_ANNULLED_BRANCH_P (insn) = 1;
+ return delay_list;
+ }
}
- return delay_list;
+ /* We can not return the delay list if we did not generate a skip.
+ We did only test for annulling branches and not for normal
+ delay insns. First trying the normal delay insns is better because
+ they allways execute in the delay slot. */
+ return 0;
}
#endif
@@ -2178,14 +2277,16 @@ fill_simple_delay_slots (non_jumps_p)
/* Try to optimize case of jumping around a single insn. */
#if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
+ /* Only call optimize_skip when the current delay list is empty.
+ If we allready had insns in the delay list we could not
+ use a skip insn because we could annul all the insns in the
+ delay list. */
if (slots_filled != slots_to_fill
&& delay_list == 0
&& GET_CODE (insn) == JUMP_INSN
&& (condjump_p (insn) || condjump_in_parallel_p (insn)))
{
- delay_list = optimize_skip (insn);
- if (delay_list)
- slots_filled += 1;
+ delay_list = optimize_skip (insn, slots_to_fill, &slots_filled);
}
#endif