/* RTL factoring (sequence abstraction).
- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
#include "tree-flow.h"
#include "timevar.h"
#include "output.h"
+#include "df.h"
+#include "addresses.h"
/* Sequence abstraction:
TODO:
- Use REG_ALLOC_ORDER when choosing link register.
- Handle JUMP_INSNs. Also handle volatile function calls (handle them
- simmilar to unconditional jumps.)
+ similar to unconditional jumps.)
- Test command line option -fpic.
*/
struct seq_block_def *next_seq_block;
} *seq_block;
-/* Contains same sequence candidates for futher searching. */
+/* Contains same sequence candidates for further searching. */
typedef struct hash_bucket_def
{
/* The hash value of the group. */
FOR_EACH_BB (bb)
{
regset_head live;
- struct propagate_block_info *pbi;
rtx insn;
+ rtx prev;
/* Initialize liveness propagation. */
INIT_REG_SET (&live);
- COPY_REG_SET (&live, bb->il.rtl->global_live_at_end);
- pbi = init_propagate_block_info (bb, &live, NULL, NULL, 0);
+ bitmap_copy (&live, DF_LR_OUT (bb));
+ df_simulate_artificial_refs_at_end (bb, &live);
/* Propagate liveness info and mark insns where a stack reg is live. */
insn = BB_END (bb);
- while (1)
+ for (insn = BB_END (bb); ; insn = prev)
{
- int reg;
- for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
- {
- if (REGNO_REG_SET_P (&live, reg))
- {
- bitmap_set_bit (&stack_reg_live, INSN_UID (insn));
- break;
- }
- }
-
- if (insn == BB_HEAD (bb))
- break;
- insn = propagate_one_insn (pbi, insn);
+ prev = PREV_INSN (insn);
+ if (INSN_P (insn))
+ {
+ int reg;
+ for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
+ {
+ if (REGNO_REG_SET_P (&live, reg))
+ {
+ bitmap_set_bit (&stack_reg_live, INSN_UID (insn));
+ break;
+ }
+ }
+
+ }
+ if (insn == BB_HEAD (bb))
+ break;
+ df_simulate_one_insn_backwards (bb, insn, &live);
+ insn = prev;
}
/* Free unused data. */
CLEAR_REG_SET (&live);
- free_propagate_block_info (pbi);
}
#endif
basic_block bb;
regset_head live;
HARD_REG_SET hlive;
- struct propagate_block_info *pbi;
rtx x;
int i;
/* Initialize liveness propagation. */
bb = BLOCK_FOR_INSN (insn);
INIT_REG_SET (&live);
- COPY_REG_SET (&live, bb->il.rtl->global_live_at_end);
- pbi = init_propagate_block_info (bb, &live, NULL, NULL, 0);
+ bitmap_copy (&live, DF_LR_OUT (bb));
+ df_simulate_artificial_refs_at_end (bb, &live);
/* Propagate until INSN if found. */
for (x = BB_END (bb); x != insn;)
- x = propagate_one_insn (pbi, x);
+ df_simulate_one_insn_backwards (bb, insn, &live);
/* Clear registers live after INSN. */
renumbered_reg_set_to_hard_reg_set (&hlive, &live);
/* Clear registers live in and before the sequence. */
for (i = 0; i < length;)
{
- rtx prev = propagate_one_insn (pbi, x);
+ rtx prev = PREV_INSN (x);
+ df_simulate_one_insn_backwards (bb, insn, &live);
if (INSN_P (x))
{
}
/* Free unused data. */
- free_propagate_block_info (pbi);
CLEAR_REG_SET (&live);
}
#ifdef REGNO_OK_FOR_INDIRECT_JUMP_P
|| (!REGNO_OK_FOR_INDIRECT_JUMP_P (i, Pmode))
#else
- || (!REGNO_MODE_OK_FOR_BASE_P (i, Pmode))
- || (!reg_class_subset_p (REGNO_REG_CLASS (i), BASE_REG_CLASS))
+ || (!ok_for_base_p_1 (i, Pmode, MEM, SCRATCH))
+ || (!reg_class_subset_p (REGNO_REG_CLASS (i),
+ base_reg_class (VOIDmode, MEM, SCRATCH)))
#endif
|| (hascall && call_used_regs[i])
- || (!call_used_regs[i] && !regs_ever_live[i]))
+ || (!call_used_regs[i] && !df_regs_ever_live_p (i)))
CLEAR_HARD_REG_BIT (linkregs, i);
/* Find an appropriate register to be used as the link register. */
}
/* Ensure that SB contains a seq_block with the appropriate length.
- Insert a new seq_block if neccessary. */
+ Insert a new seq_block if necessary. */
if (!seq_blocks || ((*mseq)->abstracted_length < seq_blocks->length))
{
sb = (seq_block) xmalloc (sizeof (struct seq_block_def));
for (mseq = sb->matching_seqs; mseq; mseq = mseq->next_matching_seq)
{
block_label_after (mseq->insn);
- IOR_REG_SET (BLOCK_FOR_INSN (pattern_seqs->insn)->
- il.rtl->global_live_at_end,
- BLOCK_FOR_INSN (mseq->insn)->il.rtl->global_live_at_end);
+ IOR_REG_SET (df_get_live_out (BLOCK_FOR_INSN (pattern_seqs->insn)),
+ df_get_live_out (BLOCK_FOR_INSN (mseq->insn)));
}
}
}
-/* Splits the best pattern sequence accoring to SEQ_BLOCKS. Emits pseudo-call
+/* Splits the best pattern sequence according to SEQ_BLOCKS. Emits pseudo-call
and -return insns before and after the sequence. */
static void
gen_symbol_ref_rtx_for_label
(retlabel)), BB_END (bb));
/* Update liveness info. */
- SET_REGNO_REG_SET (bb->il.rtl->global_live_at_end,
+ SET_REGNO_REG_SET (df_get_live_out (bb),
REGNO (pattern_seqs->link_reg));
}
BB_END (bb) = callinsn;
/* Maintain control flow and liveness information. */
- SET_REGNO_REG_SET (bb->il.rtl->global_live_at_end,
+ SET_REGNO_REG_SET (df_get_live_out (bb),
REGNO (pattern_seqs->link_reg));
emit_barrier_after (BB_END (bb));
make_single_succ_edge (bb, BLOCK_FOR_INSN (sb->label), 0);
- IOR_REG_SET (bb->il.rtl->global_live_at_end,
- BLOCK_FOR_INSN (sb->label)->il.rtl->global_live_at_start);
+ IOR_REG_SET (df_get_live_out (bb),
+ df_get_live_in (BLOCK_FOR_INSN (sb->label)));
make_edge (BLOCK_FOR_INSN (seq_blocks->label),
BLOCK_FOR_INSN (retlabel), EDGE_ABNORMAL);
free_seq_blocks ();
/* Record the usage of the link register. */
- regs_ever_live[REGNO (pattern_seqs->link_reg)] = 1;
+ df_set_regs_ever_live (REGNO (pattern_seqs->link_reg), true);
/* Remove the best pattern sequence. */
bestpseq = pattern_seqs;
rtl_seqabstr (void)
{
int iter;
+ df_set_flags (DF_LR_RUN_DCE);
+ df_analyze ();
/* Create a hash list for COLLECT_PATTERN_SEQS. */
hash_buckets = htab_create (HASH_INIT, htab_hash_bucket , htab_eq_bucket ,
/* Iterate until there are no sequences to abstract. */
for (iter = 1;; iter++)
{
- /* Recompute gain for sequences if neccessary and select sequence with
+ /* Recompute gain for sequences if necessary and select sequence with
biggest gain. */
recompute_gain ();
if (!pattern_seqs)
/* Cleanup hash tables. */
htab_delete (hash_buckets);
-
- if (iter > 1)
- {
- /* Update notes. */
- count_or_remove_death_notes (NULL, 1);
-
- life_analysis (PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
- | PROP_KILL_DEAD_CODE);
-
- /* Extra cleanup. */
- cleanup_cfg (CLEANUP_EXPENSIVE |
- CLEANUP_UPDATE_LIFE |
- (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
- }
}
/* The gate function for TREE_OPT_PASS. */
/* The entry point of the sequence abstraction algorithm. */
-static void
+static unsigned int
rest_of_rtl_seqabstr (void)
{
- life_analysis (PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE | PROP_KILL_DEAD_CODE);
-
- cleanup_cfg (CLEANUP_EXPENSIVE |
- CLEANUP_UPDATE_LIFE |
- (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
-
/* Abstract out common insn sequences. */
rtl_seqabstr ();
+ return 0;
}
struct tree_opt_pass pass_rtl_seqabstr = {
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
+ TODO_df_finish |
TODO_dump_func |
TODO_ggc_collect, /* todo_flags_finish */
'Q' /* letter */