we can hoist insns from the fall-through path for forward branches or
steal insns from the target of backward branches.
+ The TMS320C3x and C4x have three branch delay slots. When the three
+ slots are filled, the branch penalty is zero. Most insns can fill the
+ delay slots except jump insns.
+
Three techniques for filling delay slots have been implemented so far:
(1) `fill_simple_delay_slots' is the simplest, most efficient way
#include "obstack.h"
#include "insn-attr.h"
-/* Import list of registers used as spill regs from reload. */
-extern HARD_REG_SET used_spill_regs;
-
-/* Import highest label used in function at end of reload. */
-extern int max_label_num_after_reload;
-
#ifdef DELAY_SLOTS
int must_annul = *pannul_p;
int i;
int used_annul = 0;
+ struct resources cc_set;
/* We can't do anything if there are more delay slots in SEQ than we
can handle, or if we don't know that it will be a taken branch.
Also, exit if the branch has more than one set, since then it is computing
other results that can't be ignored, e.g. the HPPA mov&branch instruction.
??? It may be possible to move other sets into INSN in addition to
- moving the instructions in the delay slots. */
+ moving the instructions in the delay slots.
+
+ We can not steal the delay list if one of the instructions in the
+ current delay_list modifies the condition codes and the jump in the
+ sequence is a conditional jump. We can not do this because we can
+ not change the direction of the jump because the condition codes
+ will effect the direction of the jump in the sequence. */
+
+ CLEAR_RESOURCE (&cc_set);
+ for (temp = delay_list; temp; temp = XEXP (temp, 1))
+ {
+ rtx trial = XEXP (temp, 0);
+
+ mark_set_resources (trial, &cc_set, 0, 1);
+ if (insn_references_resource_p (XVECEXP (seq , 0, 0), &cc_set, 0))
+ return delay_list;
+ }
if (XVECLEN (seq, 0) - 1 > slots_remaining
|| ! condition_dominates_p (condition, XVECEXP (seq, 0, 0))
AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
CLEAR_HARD_REG_SET (pending_dead_regs);
- if (CODE_LABEL_NUMBER (insn) < max_label_num_after_reload)
- {
- /* All spill registers are dead at a label, so kill all of the
- ones that aren't needed also. */
- COPY_HARD_REG_SET (scratch, used_spill_regs);
- AND_COMPL_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (res->regs, scratch);
- }
continue;
case BARRIER:
SET_HARD_REG_BIT (needed.regs, HARD_FRAME_POINTER_REGNUM);
#endif
#ifdef EXIT_IGNORE_STACK
- if (! EXIT_IGNORE_STACK)
+ if (! EXIT_IGNORE_STACK
+ || current_function_sp_is_unchanging)
#endif
SET_HARD_REG_BIT (needed.regs, STACK_POINTER_REGNUM);
}
delay_list = add_to_delay_list (temp, delay_list);
- mark_set_resources (trial, &opposite_needed, 0, 1);
-
if (slots_to_fill == ++(*pslots_filled))
{
/* Even though we have filled all the slots, we
{
/* If this is the `true' thread, we will want to follow the jump,
so we can only do this if we have taken everything up to here. */
- if (thread_if_true && trial == new_thread
- && ! insn_references_resource_p (XVECEXP (PATTERN (trial), 0, 0),
- &opposite_needed, 0))
+ if (thread_if_true && trial == new_thread)
delay_list
= steal_delay_list_from_target (insn, condition, PATTERN (trial),
delay_list, &set, &needed,
&& (other = prev_active_insn (insn)) != 0
&& (condjump_p (other) || condjump_in_parallel_p (other))
&& no_labels_between_p (other, insn)
- && 0 < mostly_true_jump (other,
+ && 0 > mostly_true_jump (other,
get_branch_condition (other,
JUMP_LABEL (other))))
{
SET_HARD_REG_BIT (end_of_function_needs.regs, HARD_FRAME_POINTER_REGNUM);
#endif
#ifdef EXIT_IGNORE_STACK
- if (! EXIT_IGNORE_STACK)
+ if (! EXIT_IGNORE_STACK
+ || current_function_sp_is_unchanging)
#endif
SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
}