/* 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.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
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;
/* Initialize liveness propagation. */
INIT_REG_SET (&live);
bitmap_copy (&live, DF_LR_OUT (bb));
- df_simulate_artificial_refs_at_end (bb, &live);
+ df_simulate_initialize_backwards (bb, &live);
/* Propagate liveness info and mark insns where a stack reg is live. */
insn = BB_END (bb);
{
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;
}
}
}
#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
}
bb = BLOCK_FOR_INSN (insn);
INIT_REG_SET (&live);
bitmap_copy (&live, DF_LR_OUT (bb));
- df_simulate_artificial_refs_at_end (bb, &live);
+ df_simulate_initialize_backwards (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_backwards (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_backwards (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 */
+ }
};