aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/bfin/bfin.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/bfin/bfin.c')
-rw-r--r--gcc/config/bfin/bfin.c303
1 files changed, 172 insertions, 131 deletions
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index adb72b077a8..17201c652e1 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -173,134 +173,135 @@ struct bfin_cpu bfin_cpus[] =
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)
@@ -1417,22 +1418,6 @@ bfin_return_addr_rtx (int count)
return get_hard_reg_initial_val (Pmode, REG_RETS);
}
-/* Try machine-dependent ways of modifying an illegitimate address X
- to be legitimate. If we find one, return the new, valid address,
- otherwise return NULL_RTX.
-
- OLDX is the address as it was before break_out_memory_refs was called.
- In some cases it is useful to look at this to decide what needs to be done.
-
- MODE is the mode of the memory reference. */
-
-rtx
-legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return NULL_RTX;
-}
-
static rtx
bfin_delegitimize_address (rtx orig_x)
{
@@ -2331,20 +2316,14 @@ bfin_register_move_cost (enum machine_mode mode,
enum reg_class class1, enum reg_class class2)
{
/* These need secondary reloads, so they're more expensive. */
- if ((class1 == CCREGS && class2 != DREGS)
- || (class1 != DREGS && class2 == CCREGS))
+ if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
+ || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
return 4;
/* If optimizing for size, always prefer reg-reg over reg-memory moves. */
if (optimize_size)
return 2;
- /* There are some stalls involved when moving from a DREG to a different
- class reg, and using the value in one of the following instructions.
- Attempt to model this by slightly discouraging such moves. */
- if (class1 == DREGS && class2 != DREGS)
- return 2 * 2;
-
if (GET_MODE_CLASS (mode) == MODE_INT)
{
/* Discourage trying to use the accumulators. */
@@ -3646,12 +3625,6 @@ struct GTY (()) loop_info
/* 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;
@@ -3792,10 +3765,10 @@ bfin_optimize_loop (loop_info loop)
{
basic_block bb;
loop_info inner;
- rtx insn, init_insn, last_insn, nop_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, scratch_init, scratch_init_insn;
rtx lc_reg, lt_reg, lb_reg;
rtx seq, seq_end;
int length;
@@ -3841,13 +3814,49 @@ bfin_optimize_loop (loop_info loop)
/* 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;
+ scratch_init = iter_reg;
+ scratch_init_insn = NULL_RTX;
+ if (!PREG_P (iter_reg) && loop->incoming_src)
+ {
+ basic_block bb_in = 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 (bb_in), i))
+ {
+ scratchreg = gen_rtx_REG (SImode, i);
+ break;
+ }
+ for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
+ insn = PREV_INSN (insn))
+ {
+ rtx set;
+ if (NOTE_P (insn) || BARRIER_P (insn))
+ continue;
+ set = single_set (insn);
+ if (set && rtx_equal_p (SET_DEST (set), iter_reg))
+ {
+ if (CONSTANT_P (SET_SRC (set)))
+ {
+ scratch_init = SET_SRC (set);
+ scratch_init_insn = insn;
+ }
+ break;
+ }
+ else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
+ break;
+ }
+ }
if (loop->incoming_src)
{
@@ -3866,7 +3875,7 @@ bfin_optimize_loop (loop_info loop)
for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
length += length_for_loop (insn);
-
+
if (!insn)
{
if (dump_file)
@@ -3875,6 +3884,11 @@ bfin_optimize_loop (loop_info loop)
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)
@@ -3982,6 +3996,7 @@ bfin_optimize_loop (loop_info loop)
break;
if (single_pred_p (bb)
+ && single_pred_edge (bb)->flags & EDGE_FALLTHRU
&& single_pred (bb) != ENTRY_BLOCK_PTR)
{
bb = single_pred (bb);
@@ -4003,42 +4018,34 @@ bfin_optimize_loop (loop_info loop)
goto bad_loop;
}
- if (JUMP_P (last_insn))
+ if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
{
- loop_info inner = (loop_info) bb->aux;
- if (inner
- && inner->outer == loop
- && inner->loop_end == last_insn
- && inner->depth == 1)
- /* This jump_insn is the exact loop_end of an inner loop
- and to be optimized away. So use the inner's last_insn. */
- last_insn = inner->last_insn;
- else
+ if (dump_file)
+ fprintf (dump_file, ";; loop %d has bad last instruction\n",
+ loop->loop_no);
+ goto bad_loop;
+ }
+ /* In all other cases, try to replace a bad last insn with a nop. */
+ else if (JUMP_P (last_insn)
+ || CALL_P (last_insn)
+ || get_attr_type (last_insn) == TYPE_SYNC
+ || get_attr_type (last_insn) == TYPE_CALL
+ || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
+ || recog_memoized (last_insn) == CODE_FOR_return_internal
+ || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (last_insn)) >= 0)
+ {
+ if (loop->length + 2 > MAX_LOOP_LENGTH)
{
if (dump_file)
- fprintf (dump_file, ";; loop %d has bad last instruction\n",
- loop->loop_no);
+ fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
goto bad_loop;
}
- }
- else if (CALL_P (last_insn)
- || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
- && get_attr_type (last_insn) == TYPE_SYNC)
- || recog_memoized (last_insn) == CODE_FOR_return_internal)
- {
if (dump_file)
- fprintf (dump_file, ";; loop %d has bad last instruction\n",
+ fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
loop->loop_no);
- goto bad_loop;
- }
- if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
- || asm_noperands (PATTERN (last_insn)) >= 0
- || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
- && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
- {
- nop_insn = emit_insn_after (gen_nop (), last_insn);
- last_insn = nop_insn;
+ last_insn = emit_insn_after (gen_forced_nop (), last_insn);
}
loop->last_insn = last_insn;
@@ -4063,46 +4070,71 @@ bfin_optimize_loop (loop_info loop)
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, scratch_init));
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);
+ if (scratch_init_insn != NULL_RTX)
+ delete_insn (scratch_init_insn);
}
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, scratch_init));
+ 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 (scratch_init_insn != NULL_RTX)
+ delete_insn (scratch_init_insn);
+ }
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)
@@ -4120,7 +4152,7 @@ bfin_optimize_loop (loop_info loop)
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 ();
@@ -4169,7 +4201,7 @@ bfin_optimize_loop (loop_info loop)
redirect_edge_succ (e, new_bb);
}
}
-
+
delete_insn (loop->loop_end);
/* Insert the loop end label before the last instruction of the loop. */
emit_label_before (loop->end_label, loop->last_insn);
@@ -4230,7 +4262,6 @@ bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
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;
@@ -4604,7 +4635,7 @@ bfin_reorg_loops (FILE *dump_file)
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);
@@ -4622,6 +4653,17 @@ bfin_reorg_loops (FILE *dump_file)
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;
}
/* Possibly generate a SEQUENCE out of three insns found in SLOT.
@@ -6169,15 +6211,14 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
- emit_insn (gen_flag_mulhi_parts (tmp2, op0, op0, const0_rtx,
+ emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
const0_rtx, const1_rtx,
GEN_INT (MACFLAG_NONE)));
- emit_insn (gen_ssaddhi3_parts (target, tmp2, tmp2, const1_rtx,
- const0_rtx, const0_rtx));
-
- emit_insn (gen_sssubhi3_parts (target, tmp1, tmp1, const0_rtx,
- const0_rtx, const1_rtx));
+ emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
+ const0_rtx));
+ emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
+ const0_rtx, const1_rtx));
return target;