/* RTL factoring (sequence abstraction).
- Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
This file is part of GCC.
tmp_bucket.hash = compute_hash (insn);
/* Select the hash group. */
- bucket = htab_find (hash_buckets, &tmp_bucket);
+ bucket = (p_hash_bucket) htab_find (hash_buckets, &tmp_bucket);
if (bucket)
{
tmp_elem.insn = insn;
/* Select the insn. */
- elem = htab_find (bucket->seq_candidates, &tmp_elem);
+ elem = (p_hash_elem) htab_find (bucket->seq_candidates, &tmp_elem);
/* If INSN is parsed the cost will be the cached length. */
if (elem)
htab_iterator hti0, hti1, hti2;
p_hash_bucket hash_bucket;
p_hash_elem e0, e1;
-#ifdef STACK_REGS
+#if defined STACK_REGS || defined HAVE_cc0
basic_block bb;
- bitmap_head stack_reg_live;
+ bitmap_head dont_collect;
/* Extra initialization step to ensure that no stack registers (if present)
- are live across abnormal edges. Set a flag in STACK_REG_LIVE for an insn
- if a stack register is live after the insn. */
- bitmap_initialize (&stack_reg_live, NULL);
+ or cc0 code (if present) are live across abnormal edges.
+ Set a flag in DONT_COLLECT for an insn if a stack register is live
+ after the insn or the insn is cc0 setter or user. */
+ bitmap_initialize (&dont_collect, NULL);
+#ifdef STACK_REGS
FOR_EACH_BB (bb)
{
regset_head live;
{
if (REGNO_REG_SET_P (&live, reg))
{
- bitmap_set_bit (&stack_reg_live, INSN_UID (insn));
+ bitmap_set_bit (&dont_collect, INSN_UID (insn));
break;
}
}
}
if (insn == BB_HEAD (bb))
break;
- df_simulate_one_insn_backwards (bb, insn, &live);
+ df_simulate_one_insn (bb, insn, &live);
insn = prev;
}
}
#endif
+#ifdef HAVE_cc0
+ /* Mark CC0 setters and users as ineligible for collection into sequences.
+ This is an over-conservative fix, since it is OK to include
+ a cc0_setter, but only if we also include the corresponding cc0_user,
+ and vice versa. */
+ FOR_EACH_BB (bb)
+ {
+ rtx insn;
+ rtx next_tail;
+
+ next_tail = NEXT_INSN (BB_END (bb));
+
+ for (insn = BB_HEAD (bb); insn != next_tail; insn = NEXT_INSN (insn))
+ {
+ if (INSN_P (insn) && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
+ bitmap_set_bit (&dont_collect, INSN_UID (insn));
+ }
+ }
+#endif
+
+#endif /* defined STACK_REGS || defined HAVE_cc0 */
+
/* Initialize PATTERN_SEQS to empty. */
pattern_seqs = 0;
FOR_EACH_HTAB_ELEMENT (hash_bucket->seq_candidates, e1, p_hash_elem,
hti2)
if (e0 != e1
-#ifdef STACK_REGS
- && !bitmap_bit_p (&stack_reg_live, INSN_UID (e0->insn))
- && !bitmap_bit_p (&stack_reg_live, INSN_UID (e1->insn))
+#if defined STACK_REGS || defined HAVE_cc0
+ && !bitmap_bit_p (&dont_collect, INSN_UID (e0->insn))
+ && !bitmap_bit_p (&dont_collect, INSN_UID (e1->insn))
#endif
)
match_seqs (e0, e1);
-#ifdef STACK_REGS
+#if defined STACK_REGS || defined HAVE_cc0
/* Free unused data. */
- bitmap_clear (&stack_reg_live);
+ bitmap_clear (&dont_collect);
#endif
}
df_simulate_artificial_refs_at_end (bb, &live);
/* Propagate until INSN if found. */
- for (x = BB_END (bb); x != insn;)
- df_simulate_one_insn_backwards (bb, insn, &live);
+ for (x = BB_END (bb); x != insn; x = PREV_INSN (x))
+ df_simulate_one_insn (bb, x, &live);
/* Clear registers live after INSN. */
renumbered_reg_set_to_hard_reg_set (&hlive, &live);
for (i = 0; i < length;)
{
rtx prev = PREV_INSN (x);
- df_simulate_one_insn_backwards (bb, insn, &live);
+ df_simulate_one_insn (bb, x, &live);
if (INSN_P (x))
{
/* Builds a symbol_ref for LABEL. */
static rtx
-gen_symbol_ref_rtx_for_label (rtx label)
+gen_symbol_ref_rtx_for_label (const_rtx label)
{
char name[20];
rtx sym;
return sym;
}
+/* Splits basic block at the requested insn and rebuilds dataflow. */
+
+static basic_block
+split_block_and_df_analyze (basic_block bb, rtx insn)
+{
+ basic_block next;
+ next = split_block (bb, insn)->dest;
+ df_analyze ();
+ return next;
+}
+
/* Ensures that INSN is the last insn in its block and returns the block label
of the next block. */
if ((insn == BB_END (bb)) && (bb->next_bb != EXIT_BLOCK_PTR))
return block_label (bb->next_bb);
else
- return block_label (split_block (bb, insn)->dest);
+ return block_label (split_block_and_df_analyze (bb, insn));
}
/* Ensures that the last insns of the best pattern and its matching sequences
/* Emit an indirect jump via the link register after the sequence acting
as the return insn. Also emit a barrier and update the basic block. */
- retjmp = emit_jump_insn_after (gen_indirect_jump (pattern_seqs->link_reg),
- BB_END (bb));
+ if (!find_reg_note (BB_END (bb), REG_NORETURN, NULL))
+ retjmp = emit_jump_insn_after (gen_indirect_jump (pattern_seqs->link_reg),
+ BB_END (bb));
emit_barrier_after (BB_END (bb));
/* Replace all outgoing edges with a new one to the block of RETLABEL. */
for (; i < sb->length; i++)
insn = prev_insn_in_block (insn);
- sb->label = block_label (split_block (bb, insn)->dest);
+ sb->label = block_label (split_block_and_df_analyze (bb, insn));
}
/* Emit an insn saving the return address to the link register before the
/* Delete the insns of the sequence. */
for (i = 0; i < sb->length; i++)
insn = prev_insn_in_block (insn);
- delete_basic_block (split_block (bb, insn)->dest);
+ delete_basic_block (split_block_and_df_analyze (bb, insn));
/* Emit an insn saving the return address to the link register
before the deleted sequence. */
tmp_bucket.hash = compute_hash (insn);
/* Select the hash group. */
- bucket = htab_find (hash_buckets, &tmp_bucket);
+ bucket = (p_hash_bucket) htab_find (hash_buckets, &tmp_bucket);
if (!bucket)
{
return 0;
}
-struct tree_opt_pass pass_rtl_seqabstr = {
+struct rtl_opt_pass pass_rtl_seqabstr =
+{
+ {
+ RTL_PASS,
"seqabstr", /* name */
gate_rtl_seqabstr, /* gate */
rest_of_rtl_seqabstr, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_df_finish |
+ TODO_df_finish | TODO_verify_rtl_sharing |
TODO_dump_func |
- TODO_ggc_collect, /* todo_flags_finish */
- 'Q' /* letter */
+ TODO_ggc_collect /* todo_flags_finish */
+ }
};