WA_SPECULATIVE_LOADS | WA_RETS},
{"bf531", BFIN_CPU_BF531, 0x0006,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS},
{"bf531", BFIN_CPU_BF531, 0x0005,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS},
{"bf531", BFIN_CPU_BF531, 0x0004,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf531", BFIN_CPU_BF531, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf532", BFIN_CPU_BF532, 0x0006,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS},
{"bf532", BFIN_CPU_BF532, 0x0005,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS},
{"bf532", BFIN_CPU_BF532, 0x0004,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf532", BFIN_CPU_BF532, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf533", BFIN_CPU_BF533, 0x0006,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS},
{"bf533", BFIN_CPU_BF533, 0x0005,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS},
{"bf533", BFIN_CPU_BF533, 0x0004,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf533", BFIN_CPU_BF533, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf534", BFIN_CPU_BF534, 0x0003,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS},
{"bf534", BFIN_CPU_BF534, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf534", BFIN_CPU_BF534, 0x0001,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf536", BFIN_CPU_BF536, 0x0003,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS},
{"bf536", BFIN_CPU_BF536, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf536", BFIN_CPU_BF536, 0x0001,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf537", BFIN_CPU_BF537, 0x0003,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS},
{"bf537", BFIN_CPU_BF537, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf537", BFIN_CPU_BF537, 0x0001,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf538", BFIN_CPU_BF538, 0x0005,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS},
{"bf538", BFIN_CPU_BF538, 0x0004,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS},
{"bf538", BFIN_CPU_BF538, 0x0003,
WA_SPECULATIVE_LOADS | WA_RETS
- | WA_05000283 | WA_05000315},
+ | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS},
{"bf538", BFIN_CPU_BF538, 0x0002,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000257 | WA_05000315},
+ WA_SPECULATIVE_LOADS | WA_RETS
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf539", BFIN_CPU_BF539, 0x0005,
- WA_SPECULATIVE_LOADS},
+ WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS},
{"bf539", BFIN_CPU_BF539, 0x0004,
- WA_SPECULATIVE_LOADS | WA_RETS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS},
{"bf539", BFIN_CPU_BF539, 0x0003,
WA_SPECULATIVE_LOADS | WA_RETS
- | WA_05000283 | WA_05000315},
+ | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS},
{"bf539", BFIN_CPU_BF539, 0x0002,
WA_SPECULATIVE_LOADS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf542", BFIN_CPU_BF542, 0x0002,
WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
{"bf542", BFIN_CPU_BF542, 0x0001,
WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
{"bf542", BFIN_CPU_BF542, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS},
{"bf544", BFIN_CPU_BF544, 0x0002,
WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
{"bf544", BFIN_CPU_BF544, 0x0001,
WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
{"bf544", BFIN_CPU_BF544, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS},
{"bf547", BFIN_CPU_BF547, 0x0002,
WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
{"bf547", BFIN_CPU_BF547, 0x0001,
WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
{"bf547", BFIN_CPU_BF547, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS},
{"bf548", BFIN_CPU_BF548, 0x0002,
WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
{"bf548", BFIN_CPU_BF548, 0x0001,
WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
{"bf548", BFIN_CPU_BF548, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS},
{"bf549", BFIN_CPU_BF549, 0x0002,
WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
{"bf549", BFIN_CPU_BF549, 0x0001,
WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
{"bf549", BFIN_CPU_BF549, 0x0000,
- WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
+ WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS},
{"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS
- | WA_05000283 | WA_05000315},
+ | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS},
{"bf561", BFIN_CPU_BF561, 0x0003,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{"bf561", BFIN_CPU_BF561, 0x0002,
WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
- | WA_05000283 | WA_05000257 | WA_05000315},
+ | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS},
{NULL, 0, 0, 0}
};
-int splitting_for_sched;
+int splitting_for_sched, splitting_loops;
static void
bfin_globalize_label (FILE *stream, const char *name)
/* The iteration register. */
rtx iter_reg;
- /* The new initialization insn. */
- rtx init;
-
- /* The new initialization instruction. */
- rtx loop_init;
-
/* The new label placed at the beginning of the loop. */
rtx start_label;
{
basic_block bb;
loop_info inner;
- rtx insn, init_insn, last_insn;
+ rtx insn, last_insn;
rtx loop_init, start_label, end_label;
rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
- rtx iter_reg;
+ rtx iter_reg, scratchreg;
rtx lc_reg, lt_reg, lb_reg;
rtx seq, seq_end;
int length;
/* Get the loop iteration register. */
iter_reg = loop->iter_reg;
- if (!DPREG_P (iter_reg))
+ if (!REG_P (iter_reg))
{
if (dump_file)
- fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
+ fprintf (dump_file, ";; loop %d iteration count not in a register\n",
loop->loop_no);
goto bad_loop;
}
+ scratchreg = NULL_RTX;
+ if (!PREG_P (iter_reg) && loop->incoming_src)
+ {
+ int i;
+ for (i = REG_P0; i <= REG_P5; i++)
+ if ((df_regs_ever_live_p (i)
+ || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
+ && call_used_regs[i]))
+ && !REGNO_REG_SET_P (df_get_live_out (loop->incoming_src), i))
+ {
+ scratchreg = gen_rtx_REG (SImode, i);
+ break;
+ }
+ }
if (loop->incoming_src)
{
for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
length += length_for_loop (insn);
-
+
if (!insn)
{
if (dump_file)
goto bad_loop;
}
+ /* Account for the pop of a scratch register where necessary. */
+ if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
+ && ENABLE_WA_LOAD_LCREGS)
+ length += 2;
+
if (length > MAX_LSETUP_DISTANCE)
{
if (dump_file)
loop->clobber_loop0 = 1;
}
- /* If iter_reg is a DREG, we need generate an instruction to load
- the loop count into LC register. */
- if (D_REGNO_P (REGNO (iter_reg)))
+ loop->end_label = end_label;
+
+ /* Create a sequence containing the loop setup. */
+ start_sequence ();
+
+ /* LSETUP only accepts P registers. If we have one, we can use it,
+ otherwise there are several ways of working around the problem.
+ If we're not affected by anomaly 312, we can load the LC register
+ from any iteration register, and use LSETUP without initialization.
+ If we've found a P scratch register that's not live here, we can
+ instead copy the iter_reg into that and use an initializing LSETUP.
+ If all else fails, push and pop P0 and use it as a scratch. */
+ if (P_REGNO_P (REGNO (iter_reg)))
+ {
+ loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
+ lb_reg, end_label,
+ lc_reg, iter_reg);
+ seq_end = emit_insn (loop_init);
+ }
+ else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
{
- init_insn = gen_movsi (lc_reg, iter_reg);
+ emit_insn (gen_movsi (lc_reg, iter_reg));
loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
lb_reg, end_label,
lc_reg);
+ seq_end = emit_insn (loop_init);
}
- else if (P_REGNO_P (REGNO (iter_reg)))
+ else if (scratchreg != NULL_RTX)
{
- init_insn = NULL_RTX;
+ emit_insn (gen_movsi (scratchreg, iter_reg));
loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
lb_reg, end_label,
- lc_reg, iter_reg);
+ lc_reg, scratchreg);
+ seq_end = emit_insn (loop_init);
}
else
- gcc_unreachable ();
-
- loop->init = init_insn;
- loop->end_label = end_label;
- loop->loop_init = loop_init;
+ {
+ rtx p0reg = gen_rtx_REG (SImode, REG_P0);
+ rtx push = gen_frame_mem (SImode,
+ gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
+ rtx pop = gen_frame_mem (SImode,
+ gen_rtx_POST_INC (SImode, stack_pointer_rtx));
+ emit_insn (gen_movsi (push, p0reg));
+ emit_insn (gen_movsi (p0reg, iter_reg));
+ loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
+ lb_reg, end_label,
+ lc_reg, p0reg);
+ emit_insn (loop_init);
+ seq_end = emit_insn (gen_movsi (p0reg, pop));
+ }
if (dump_file)
{
fprintf (dump_file, ";; replacing loop %d initializer with\n",
loop->loop_no);
- print_rtl_single (dump_file, loop->loop_init);
+ print_rtl_single (dump_file, loop_init);
fprintf (dump_file, ";; replacing loop %d terminator with\n",
loop->loop_no);
print_rtl_single (dump_file, loop->loop_end);
}
- /* Create a sequence containing the loop setup. */
- start_sequence ();
-
- if (loop->init != NULL_RTX)
- emit_insn (loop->init);
- seq_end = emit_insn (loop->loop_init);
-
/* If the loop isn't entered at the top, also create a jump to the entry
point. */
if (!loop->incoming_src && loop->head != loop->incoming_dest)
seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
}
else
- seq_end = emit_insn (gen_jump (label));
+ seq_end = emit_jump_insn (gen_jump (label));
}
seq = get_insns ();
loop->outer = NULL;
loop->loops = NULL;
loop->incoming = VEC_alloc (edge, gc, 2);
- loop->init = loop->loop_init = NULL_RTX;
loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
loop->end_label = NULL_RTX;
loop->bad = 0;
fprintf (dump_file, ";; All loops found:\n\n");
bfin_dump_loops (loops);
}
-
+
/* Now apply the optimizations. */
for (loop = loops; loop; loop = loop->next)
bfin_optimize_loop (loop);
FOR_EACH_BB (bb)
bb->aux = NULL;
+
+ splitting_loops = 1;
+ FOR_EACH_BB (bb)
+ {
+ rtx insn = BB_END (bb);
+ if (!JUMP_P (insn))
+ continue;
+
+ try_split (PATTERN (insn), insn, 1);
+ }
+ splitting_loops = 0;
}
\f
/* Possibly generate a SEQUENCE out of three insns found in SLOT.