Commit 96960d10 by Herman ten Brugge Committed by Jeff Law

reorg.c (try_merge_delay_insns): Account for resources referenced in each…

reorg.c (try_merge_delay_insns): Account for resources referenced in each instruction in INSN's delay list...

        * reorg.c (try_merge_delay_insns): Account for resources referenced
        in each instruction in INSN's delay list before trying to eliminate
        useless instructions.  Similarly when looking at a trial insn's delay
        slots.
        * reorg.c (check_annul_list_true_false): New function.
        (steal_delay_list_from_{target,fallthrough}): Call it and also
        refine tests for when we may annul if already filled a slot.
        (fill_slots_from_thread): Likewise.
        (delete_from_delay_slot): Return newly-created thread.
        (try_merge_delay_isns): Use its new return value.

From-SVN: r22685
parent c5cbf81e
Wed Sep 30 18:43:32 1998 Herman ten Brugge <Haj.Ten.Brugge@net.HCC.nl>
* reorg.c (try_merge_delay_insns): Account for resources referenced
in each instruction in INSN's delay list before trying to eliminate
useless instructions. Similarly when looking at a trial insn's delay
slots.
* reorg.c (check_annul_list_true_false): New function.
(steal_delay_list_from_{target,fallthrough}): Call it and also
refine tests for when we may annul if already filled a slot.
(fill_slots_from_thread): Likewise.
(delete_from_delay_slot): Return newly-created thread.
(try_merge_delay_isns): Use its new return value.
Wed Sep 30 18:29:26 1998 Jeffrey A Law (law@cygnus.com) Wed Sep 30 18:29:26 1998 Jeffrey A Law (law@cygnus.com)
* loop.c (check_dbra_loop): Use a vanilla loop reversal if the biv is * loop.c (check_dbra_loop): Use a vanilla loop reversal if the biv is
......
...@@ -234,7 +234,7 @@ static int insn_sets_resource_p PROTO((rtx, struct resources *, int)); ...@@ -234,7 +234,7 @@ static int insn_sets_resource_p PROTO((rtx, struct resources *, int));
static rtx find_end_label PROTO((void)); static rtx find_end_label PROTO((void));
static rtx emit_delay_sequence PROTO((rtx, rtx, int)); static rtx emit_delay_sequence PROTO((rtx, rtx, int));
static rtx add_to_delay_list PROTO((rtx, rtx)); static rtx add_to_delay_list PROTO((rtx, rtx));
static void delete_from_delay_slot PROTO((rtx)); static rtx delete_from_delay_slot PROTO((rtx));
static void delete_scheduled_jump PROTO((rtx)); static void delete_scheduled_jump PROTO((rtx));
static void note_delay_statistics PROTO((int, int)); static void note_delay_statistics PROTO((int, int));
static rtx optimize_skip PROTO((rtx)); static rtx optimize_skip PROTO((rtx));
...@@ -1011,7 +1011,7 @@ add_to_delay_list (insn, delay_list) ...@@ -1011,7 +1011,7 @@ add_to_delay_list (insn, delay_list)
/* Delete INSN from the delay slot of the insn that it is in. This may /* Delete INSN from the delay slot of the insn that it is in. This may
produce an insn without anything in its delay slots. */ produce an insn without anything in its delay slots. */
static void static rtx
delete_from_delay_slot (insn) delete_from_delay_slot (insn)
rtx insn; rtx insn;
{ {
...@@ -1060,6 +1060,8 @@ delete_from_delay_slot (insn) ...@@ -1060,6 +1060,8 @@ delete_from_delay_slot (insn)
/* Show we need to fill this insn again. */ /* Show we need to fill this insn again. */
obstack_ptr_grow (&unfilled_slots_obstack, trial); obstack_ptr_grow (&unfilled_slots_obstack, trial);
return trial;
} }
/* Delete INSN, a JUMP_INSN. If it is a conditional jump, we must track down /* Delete INSN, a JUMP_INSN. If it is a conditional jump, we must track down
...@@ -1624,6 +1626,31 @@ redirect_with_delay_list_safe_p (jump, newlabel, delay_list) ...@@ -1624,6 +1626,31 @@ redirect_with_delay_list_safe_p (jump, newlabel, delay_list)
return (li == NULL); return (li == NULL);
} }
/* DELAY_LIST is a list of insns that have already been placed into delay
slots. See if all of them have the same annulling status as ANNUL_TRUE_P.
If not, return 0; otherwise return 1. */
static int
check_annul_list_true_false (annul_true_p, delay_list)
int annul_true_p;
rtx delay_list;
{
rtx temp, trial;
if (delay_list)
{
for (temp = delay_list; temp; temp = XEXP (temp, 1))
{
rtx trial = XEXP (temp, 0);
if ((annul_true_p && INSN_FROM_TARGET_P (trial))
|| (!annul_true_p && !INSN_FROM_TARGET_P (trial)))
return 0;
}
}
return 1;
}
/* INSN branches to an insn whose pattern SEQ is a SEQUENCE. Given that /* INSN branches to an insn whose pattern SEQ is a SEQUENCE. Given that
the condition tested by INSN is CONDITION and the resources shown in the condition tested by INSN is CONDITION and the resources shown in
...@@ -1714,9 +1741,15 @@ steal_delay_list_from_target (insn, condition, seq, delay_list, ...@@ -1714,9 +1741,15 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
|| (! insn_sets_resource_p (trial, other_needed, 0) || (! insn_sets_resource_p (trial, other_needed, 0)
&& ! may_trap_p (PATTERN (trial))))) && ! may_trap_p (PATTERN (trial)))))
? eligible_for_delay (insn, total_slots_filled, trial, flags) ? eligible_for_delay (insn, total_slots_filled, trial, flags)
: (must_annul = 1, : (must_annul || (delay_list == NULL && new_delay_list == NULL))
eligible_for_annul_false (insn, total_slots_filled, trial, flags))) && (must_annul = 1,
check_annul_list_true_false (0, delay_list)
&& check_annul_list_true_false (0, new_delay_list)
&& eligible_for_annul_false (insn, total_slots_filled,
trial, flags)))
{ {
if (must_annul)
used_annul = 1;
temp = copy_rtx (trial); temp = copy_rtx (trial);
INSN_FROM_TARGET_P (temp) = 1; INSN_FROM_TARGET_P (temp) = 1;
new_delay_list = add_to_delay_list (temp, new_delay_list); new_delay_list = add_to_delay_list (temp, new_delay_list);
...@@ -1735,7 +1768,8 @@ steal_delay_list_from_target (insn, condition, seq, delay_list, ...@@ -1735,7 +1768,8 @@ steal_delay_list_from_target (insn, condition, seq, delay_list,
/* Add any new insns to the delay list and update the count of the /* Add any new insns to the delay list and update the count of the
number of slots filled. */ number of slots filled. */
*pslots_filled = total_slots_filled; *pslots_filled = total_slots_filled;
*pannul_p = must_annul; if (used_annul)
*pannul_p = 1;
if (delay_list == 0) if (delay_list == 0)
return new_delay_list; return new_delay_list;
...@@ -1765,6 +1799,8 @@ steal_delay_list_from_fallthrough (insn, condition, seq, ...@@ -1765,6 +1799,8 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
{ {
int i; int i;
int flags; int flags;
int must_annul = *pannul_p;
int used_annul = 0;
flags = get_jump_flags (insn, JUMP_LABEL (insn)); flags = get_jump_flags (insn, JUMP_LABEL (insn));
...@@ -1798,14 +1834,17 @@ steal_delay_list_from_fallthrough (insn, condition, seq, ...@@ -1798,14 +1834,17 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
continue; continue;
} }
if (! *pannul_p if (! must_annul
&& ((condition == const_true_rtx && ((condition == const_true_rtx
|| (! insn_sets_resource_p (trial, other_needed, 0) || (! insn_sets_resource_p (trial, other_needed, 0)
&& ! may_trap_p (PATTERN (trial))))) && ! may_trap_p (PATTERN (trial)))))
? eligible_for_delay (insn, *pslots_filled, trial, flags) ? eligible_for_delay (insn, *pslots_filled, trial, flags)
: (*pannul_p = 1, : (must_annul || delay_list == NULL) && (must_annul = 1,
eligible_for_annul_true (insn, *pslots_filled, trial, flags))) check_annul_list_true_false (1, delay_list)
&& eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
{ {
if (must_annul)
used_annul = 1;
delete_from_delay_slot (trial); delete_from_delay_slot (trial);
delay_list = add_to_delay_list (trial, delay_list); delay_list = add_to_delay_list (trial, delay_list);
...@@ -1816,8 +1855,11 @@ steal_delay_list_from_fallthrough (insn, condition, seq, ...@@ -1816,8 +1855,11 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
break; break;
} }
if (used_annul)
*pannul_p = 1;
return delay_list; return delay_list;
} }
/* Try merging insns starting at THREAD which match exactly the insns in /* Try merging insns starting at THREAD which match exactly the insns in
INSN's delay list. INSN's delay list.
...@@ -1849,13 +1891,15 @@ try_merge_delay_insns (insn, thread) ...@@ -1849,13 +1891,15 @@ try_merge_delay_insns (insn, thread)
CLEAR_RESOURCE (&set); CLEAR_RESOURCE (&set);
/* If this is not an annulling branch, take into account anything needed in /* If this is not an annulling branch, take into account anything needed in
NEXT_TO_MATCH. This prevents two increments from being incorrectly INSN's delay slot. This prevents two increments from being incorrectly
folded into one. If we are annulling, this would be the correct folded into one. If we are annulling, this would be the correct
thing to do. (The alternative, looking at things set in NEXT_TO_MATCH thing to do. (The alternative, looking at things set in NEXT_TO_MATCH
will essentially disable this optimization. This method is somewhat of will essentially disable this optimization. This method is somewhat of
a kludge, but I don't see a better way.) */ a kludge, but I don't see a better way.) */
if (! annul_p) if (! annul_p)
mark_referenced_resources (next_to_match, &needed, 1); for (i = 1 ; i < num_slots ; i++)
if (XVECEXP (PATTERN (insn), 0, i))
mark_referenced_resources (XVECEXP (PATTERN (insn), 0, i), &needed, 1);
for (trial = thread; !stop_search_p (trial, 1); trial = next_trial) for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)
{ {
...@@ -1904,8 +1948,6 @@ try_merge_delay_insns (insn, thread) ...@@ -1904,8 +1948,6 @@ try_merge_delay_insns (insn, thread)
break; break;
next_to_match = XVECEXP (PATTERN (insn), 0, slot_number); next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
if (! annul_p)
mark_referenced_resources (next_to_match, &needed, 1);
} }
mark_set_resources (trial, &set, 0, 1); mark_set_resources (trial, &set, 0, 1);
...@@ -1941,8 +1983,12 @@ try_merge_delay_insns (insn, thread) ...@@ -1941,8 +1983,12 @@ try_merge_delay_insns (insn, thread)
{ {
if (! annul_p) if (! annul_p)
{ {
rtx new;
update_block (dtrial, thread); update_block (dtrial, thread);
delete_from_delay_slot (dtrial); new = delete_from_delay_slot (dtrial);
if (INSN_DELETED_P (thread))
thread = new;
INSN_FROM_TARGET_P (next_to_match) = 0; INSN_FROM_TARGET_P (next_to_match) = 0;
} }
else else
...@@ -1954,6 +2000,12 @@ try_merge_delay_insns (insn, thread) ...@@ -1954,6 +2000,12 @@ try_merge_delay_insns (insn, thread)
next_to_match = XVECEXP (PATTERN (insn), 0, slot_number); next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
} }
else
{
/* Keep track of the set/referenced resources for
mark_set_resources (dtrial, &set, 0, 1);
mark_referenced_resources (dtrial, &needed, 1);
}
} }
} }
...@@ -1968,8 +2020,12 @@ try_merge_delay_insns (insn, thread) ...@@ -1968,8 +2020,12 @@ try_merge_delay_insns (insn, thread)
{ {
if (GET_MODE (merged_insns) == SImode) if (GET_MODE (merged_insns) == SImode)
{ {
rtx new;
update_block (XEXP (merged_insns, 0), thread); update_block (XEXP (merged_insns, 0), thread);
delete_from_delay_slot (XEXP (merged_insns, 0)); new = delete_from_delay_slot (XEXP (merged_insns, 0));
if (INSN_DELETED_P (thread))
thread = new;
} }
else else
{ {
...@@ -3600,9 +3656,10 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely, ...@@ -3600,9 +3656,10 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
/* There are two ways we can win: If TRIAL doesn't set anything /* There are two ways we can win: If TRIAL doesn't set anything
needed at the opposite thread and can't trap, or if it can needed at the opposite thread and can't trap, or if it can
go into an annulled delay slot. */ go into an annulled delay slot. */
if (condition == const_true_rtx if (!must_annul
|| (! insn_sets_resource_p (trial, &opposite_needed, 1) && (condition == const_true_rtx
&& ! may_trap_p (pat))) || (! insn_sets_resource_p (trial, &opposite_needed, 1)
&& ! may_trap_p (pat))))
{ {
old_trial = trial; old_trial = trial;
trial = try_split (pat, trial, 0); trial = try_split (pat, trial, 0);
...@@ -3630,9 +3687,11 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely, ...@@ -3630,9 +3687,11 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (thread == old_trial) if (thread == old_trial)
thread = trial; thread = trial;
pat = PATTERN (trial); pat = PATTERN (trial);
if ((thread_if_true if ((must_annul || delay_list == NULL) && (thread_if_true
? eligible_for_annul_false (insn, *pslots_filled, trial, flags) ? check_annul_list_true_false (0, delay_list)
: eligible_for_annul_true (insn, *pslots_filled, trial, flags))) && eligible_for_annul_false (insn, *pslots_filled, trial, flags)
: check_annul_list_true_false (1, delay_list)
&& eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
{ {
rtx temp; rtx temp;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment