summaryrefslogtreecommitdiff
path: root/gcc/config/bfin
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-12 14:35:13 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-12 14:35:13 +0000
commitd18119ae407ae77a17ac15e230590e1f0a9326a4 (patch)
tree82730146ed366479bd3a679168528be660164548 /gcc/config/bfin
parentb1906db7d9c2f59f2ecb6bd490eba4e0ef2cd3fe (diff)
downloadgcc-d18119ae407ae77a17ac15e230590e1f0a9326a4.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125648 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/bfin')
-rw-r--r--gcc/config/bfin/bfin.c94
-rw-r--r--gcc/config/bfin/bfin.md9
2 files changed, 82 insertions, 21 deletions
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 26fbc6cfdde..968735f2a17 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -54,6 +54,7 @@
#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. */
@@ -604,7 +605,7 @@ add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
{
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
@@ -3745,7 +3746,7 @@ bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
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))
@@ -3974,7 +3975,7 @@ bfin_reorder_loops (loop_info loops, FILE *dump_file)
FOR_EACH_BB (bb)
bb->aux = NULL;
- cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
+ cfg_layout_initialize (0);
for (loop = loops; loop; loop = loop->next)
{
@@ -4026,6 +4027,7 @@ bfin_reorder_loops (loop_info loops, FILE *dump_file)
bb->aux = NULL;
}
cfg_layout_finalize ();
+ df_analyze ();
}
/* Run from machine_dependent_reorg, this pass looks for doloop_end insns
@@ -4087,7 +4089,7 @@ bfin_reorg_loops (FILE *dump_file)
static bool
gen_one_bundle (rtx slot[3])
{
- rtx bundle;
+ rtx bundle, insn;
gcc_assert (slot[1] != NULL_RTX);
@@ -4116,9 +4118,15 @@ gen_one_bundle (rtx slot[3])
}
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])
@@ -4131,17 +4139,8 @@ gen_one_bundle (rtx slot[3])
/* 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;
}
@@ -4199,6 +4198,7 @@ bfin_gen_bundles (void)
{
SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
INSN_CODE (slot[0]) = -1;
+ df_insn_rescan (slot[0]);
}
}
n_filled = 0;
@@ -4209,6 +4209,58 @@ bfin_gen_bundles (void)
}
}
}
+
+/* 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;
+ }
+ }
+ }
+ }
+}
/* 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
@@ -4290,11 +4342,9 @@ bfin_reorg (void)
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);
@@ -4304,6 +4354,8 @@ bfin_reorg (void)
bfin_gen_bundles ();
}
+ df_analyze ();
+
/* Doloop optimization */
if (cfun->machine->has_hardware_loops)
bfin_reorg_loops (dump_file);
@@ -4451,8 +4503,10 @@ bfin_reorg (void)
{
timevar_push (TV_VAR_TRACKING);
variable_tracking_main ();
+ reorder_var_tracking_notes ();
timevar_pop (TV_VAR_TRACKING);
}
+ df_finish_pass ();
}
/* Handle interrupt_handler, exception_handler and nmi_handler function
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index d447825477b..1fafa881f78 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -137,7 +137,8 @@
(UNSPEC_FUNCDESC_GOT17M4 9)
(UNSPEC_LSETUP_END 10)
;; Distinguish a 32-bit version of an insn from a 16-bit version.
- (UNSPEC_32BIT 11)])
+ (UNSPEC_32BIT 11)
+ (UNSPEC_NOP 12)])
(define_constants
[(UNSPEC_VOLATILE_EH_RETURN 0)
@@ -2595,6 +2596,12 @@
""
"nop;")
+;; A nop which stays there when emitted.
+(define_insn "forced_nop"
+ [(unspec [(const_int 0)] UNSPEC_NOP)]
+ ""
+ "nop;")
+
(define_insn "mnop"
[(unspec [(const_int 0)] UNSPEC_32BIT)]
""