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
This commit is contained in:
Herman ten Brugge 1998-09-30 20:01:38 +02:00 committed by Jeff Law
parent c5cbf81ecf
commit 96960d10b7
2 changed files with 93 additions and 20 deletions

View File

@ -1,3 +1,17 @@
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)
* loop.c (check_dbra_loop): Use a vanilla loop reversal if the biv is

View File

@ -234,7 +234,7 @@ static int insn_sets_resource_p PROTO((rtx, struct resources *, int));
static rtx find_end_label PROTO((void));
static rtx emit_delay_sequence PROTO((rtx, rtx, int));
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 note_delay_statistics PROTO((int, int));
static rtx optimize_skip PROTO((rtx));
@ -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
produce an insn without anything in its delay slots. */
static void
static rtx
delete_from_delay_slot (insn)
rtx insn;
{
@ -1060,6 +1060,8 @@ delete_from_delay_slot (insn)
/* Show we need to fill this insn again. */
obstack_ptr_grow (&unfilled_slots_obstack, trial);
return trial;
}
/* 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)
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
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,
|| (! insn_sets_resource_p (trial, other_needed, 0)
&& ! may_trap_p (PATTERN (trial)))))
? eligible_for_delay (insn, total_slots_filled, trial, flags)
: (must_annul = 1,
eligible_for_annul_false (insn, total_slots_filled, trial, flags)))
: (must_annul || (delay_list == NULL && new_delay_list == NULL))
&& (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);
INSN_FROM_TARGET_P (temp) = 1;
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,
/* Add any new insns to the delay list and update the count of the
number of slots filled. */
*pslots_filled = total_slots_filled;
*pannul_p = must_annul;
if (used_annul)
*pannul_p = 1;
if (delay_list == 0)
return new_delay_list;
@ -1765,6 +1799,8 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
{
int i;
int flags;
int must_annul = *pannul_p;
int used_annul = 0;
flags = get_jump_flags (insn, JUMP_LABEL (insn));
@ -1798,14 +1834,17 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
continue;
}
if (! *pannul_p
if (! must_annul
&& ((condition == const_true_rtx
|| (! insn_sets_resource_p (trial, other_needed, 0)
&& ! may_trap_p (PATTERN (trial)))))
? eligible_for_delay (insn, *pslots_filled, trial, flags)
: (*pannul_p = 1,
eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
: (must_annul || delay_list == NULL) && (must_annul = 1,
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);
delay_list = add_to_delay_list (trial, delay_list);
@ -1816,8 +1855,11 @@ steal_delay_list_from_fallthrough (insn, condition, seq,
break;
}
if (used_annul)
*pannul_p = 1;
return delay_list;
}
/* Try merging insns starting at THREAD which match exactly the insns in
INSN's delay list.
@ -1849,13 +1891,15 @@ try_merge_delay_insns (insn, thread)
CLEAR_RESOURCE (&set);
/* 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
thing to do. (The alternative, looking at things set in NEXT_TO_MATCH
will essentially disable this optimization. This method is somewhat of
a kludge, but I don't see a better way.) */
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)
{
@ -1904,8 +1948,6 @@ try_merge_delay_insns (insn, thread)
break;
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);
@ -1941,8 +1983,12 @@ try_merge_delay_insns (insn, thread)
{
if (! annul_p)
{
rtx new;
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;
}
else
@ -1954,6 +2000,12 @@ try_merge_delay_insns (insn, thread)
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)
{
if (GET_MODE (merged_insns) == SImode)
{
rtx new;
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
{
@ -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
needed at the opposite thread and can't trap, or if it can
go into an annulled delay slot. */
if (condition == const_true_rtx
|| (! insn_sets_resource_p (trial, &opposite_needed, 1)
&& ! may_trap_p (pat)))
if (!must_annul
&& (condition == const_true_rtx
|| (! insn_sets_resource_p (trial, &opposite_needed, 1)
&& ! may_trap_p (pat))))
{
old_trial = trial;
trial = try_split (pat, trial, 0);
@ -3630,9 +3687,11 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (thread == old_trial)
thread = trial;
pat = PATTERN (trial);
if ((thread_if_true
? eligible_for_annul_false (insn, *pslots_filled, trial, flags)
: eligible_for_annul_true (insn, *pslots_filled, trial, flags)))
if ((must_annul || delay_list == NULL) && (thread_if_true
? check_annul_list_true_false (0, delay_list)
&& 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;