+2007-06-12 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * config/bfin/bfin.md (UNSPEC_NOP): New constant.
+ (forced_nop): New pattern.
+ * config/bfin/bfin.c: Include "df.h".
+ (add_to_reg): Use df_regs_ever_live_p instead of regs_ever_live.
+ (bfin_discover_loop): Use df_get_live_in instead of
+ global_live_at_start.
+ (bfin_reorder_loops): Pass 0 to cfg_layout_initialize. Call
+ df_analyze when done.
+ (gen_one_bundle): Don't generate SEQUENCE insns, just put modes on
+ the insns. Use QImode for the final insn in a bundle. Call
+ df_insn_rescan on generated NOPs; use gen_forced_nop instead of
+ gen_nop.
+ (reorder_var_tracking_notes): New function.
+ (bfin_reorg): Pass no argument to split_all_insns. Don't call
+ update_life_info. Call df_analyze after scheduling and bundle
+ generation. Call reorder_var_tracking_notes if generating these notes.
+ Call df_finish_pass at the end.
+
2007-06-12 Dirk Mueller <dmueller@suse.de>
* trans-stmt.c (gfc_trans_call): fix gcc_assert to
#include "basic-block.h"
#include "cfglayout.h"
#include "timevar.h"
+#include "df.h"
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
{
int i;
for (i = REG_P0; i <= REG_P5; i++)
- if ((regs_ever_live[i] && ! call_used_regs[i])
+ if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
|| (!TARGET_FDPIC
&& i == PIC_OFFSET_TABLE_REGNUM
&& (current_function_uses_pic_offset_table
FOR_EACH_EDGE (e, ei, bb->succs)
{
basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
- if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
+ if (!REGNO_REG_SET_P (df_get_live_in (succ),
REGNO (loop->iter_reg)))
continue;
if (!VEC_space (basic_block, works, 1))
FOR_EACH_BB (bb)
bb->aux = NULL;
- cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
+ cfg_layout_initialize (0);
for (loop = loops; loop; loop = loop->next)
{
bb->aux = NULL;
}
cfg_layout_finalize ();
+ df_analyze ();
}
/* Run from machine_dependent_reorg, this pass looks for doloop_end insns
static bool
gen_one_bundle (rtx slot[3])
{
- rtx bundle;
+ rtx bundle, insn;
gcc_assert (slot[1] != NULL_RTX);
}
if (slot[0] == NULL_RTX)
- slot[0] = emit_insn_before (gen_mnop (), slot[1]);
+ {
+ slot[0] = emit_insn_before (gen_mnop (), slot[1]);
+ df_insn_rescan (slot[0]);
+ }
if (slot[2] == NULL_RTX)
- slot[2] = emit_insn_after (gen_nop (), slot[1]);
+ {
+ slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
+ df_insn_rescan (slot[2]);
+ }
/* Avoid line number information being printed inside one bundle. */
if (INSN_LOCATOR (slot[1])
/* Terminate them with "|| " instead of ";" in the output. */
PUT_MODE (slot[0], SImode);
PUT_MODE (slot[1], SImode);
-
- /* This is a cheat to avoid emit_insn's special handling of SEQUENCEs.
- Generating a PARALLEL first and changing its code later is the
- easiest way to emit a SEQUENCE insn. */
- bundle = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (3, slot[0], slot[1], slot[2]));
- emit_insn_before (bundle, slot[0]);
- remove_insn (slot[0]);
- remove_insn (slot[1]);
- remove_insn (slot[2]);
- PUT_CODE (bundle, SEQUENCE);
-
+ /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
+ PUT_MODE (slot[2], QImode);
return true;
}
{
SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
INSN_CODE (slot[0]) = -1;
+ df_insn_rescan (slot[0]);
}
}
n_filled = 0;
}
}
}
+
+/* Ensure that no var tracking notes are emitted in the middle of a
+ three-instruction bundle. */
+
+static void
+reorder_var_tracking_notes (void)
+{
+ basic_block bb;
+ FOR_EACH_BB (bb)
+ {
+ rtx insn, next;
+ rtx queue = NULL_RTX;
+ bool in_bundle = false;
+
+ for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
+ {
+ next = NEXT_INSN (insn);
+
+ if (INSN_P (insn))
+ {
+ /* Emit queued up notes at the last instruction of a bundle. */
+ if (GET_MODE (insn) == QImode)
+ {
+ while (queue)
+ {
+ rtx next_queue = PREV_INSN (queue);
+ PREV_INSN (NEXT_INSN (insn)) = queue;
+ NEXT_INSN (queue) = NEXT_INSN (insn);
+ NEXT_INSN (insn) = queue;
+ PREV_INSN (queue) = insn;
+ queue = next_queue;
+ }
+ in_bundle = false;
+ }
+ else if (GET_MODE (insn) == SImode)
+ in_bundle = true;
+ }
+ else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
+ {
+ if (in_bundle)
+ {
+ rtx prev = PREV_INSN (insn);
+ PREV_INSN (next) = prev;
+ NEXT_INSN (prev) = next;
+
+ PREV_INSN (insn) = queue;
+ queue = insn;
+ }
+ }
+ }
+ }
+}
\f
/* Return an insn type for INSN that can be used by the caller for anomaly
workarounds. This differs from plain get_attr_type in that it handles
if (bfin_flag_schedule_insns2)
{
splitting_for_sched = 1;
- split_all_insns (0);
+ split_all_insns ();
splitting_for_sched = 0;
- update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
-
timevar_push (TV_SCHED2);
schedule_insns ();
timevar_pop (TV_SCHED2);
bfin_gen_bundles ();
}
+ df_analyze ();
+
/* Doloop optimization */
if (cfun->machine->has_hardware_loops)
bfin_reorg_loops (dump_file);
{
timevar_push (TV_VAR_TRACKING);
variable_tracking_main ();
+ reorder_var_tracking_notes ();
timevar_pop (TV_VAR_TRACKING);
}
+ df_finish_pass ();
}
\f
/* Handle interrupt_handler, exception_handler and nmi_handler function