X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Frtl-factoring.c;h=07c66e20cc377133cf488e4fc1ba4bc21affc614;hb=e4cdb4c6a9fe30297ea553e9724a836fd46fe331;hp=d0386d61c3e6ea07b62ebf83a57f7cd01e678cd7;hpb=b7bf20db425f8aea1f5c9fdd01cab096ac154a31;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/rtl-factoring.c b/gcc/rtl-factoring.c index d0386d61c3e..07c66e20cc3 100644 --- a/gcc/rtl-factoring.c +++ b/gcc/rtl-factoring.c @@ -1,5 +1,5 @@ /* 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. @@ -323,14 +323,14 @@ compute_rtx_cost (rtx insn) 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) @@ -444,15 +444,17 @@ collect_pattern_seqs (void) 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; @@ -476,7 +478,7 @@ collect_pattern_seqs (void) { 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; } } @@ -484,7 +486,7 @@ collect_pattern_seqs (void) } if (insn == BB_HEAD (bb)) break; - df_simulate_one_insn_backwards (bb, insn, &live); + df_simulate_one_insn (bb, insn, &live); insn = prev; } @@ -493,6 +495,28 @@ collect_pattern_seqs (void) } #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; @@ -505,15 +529,15 @@ collect_pattern_seqs (void) 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 } @@ -551,8 +575,8 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length) 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); @@ -562,7 +586,7 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length) 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)) { @@ -949,6 +973,17 @@ gen_symbol_ref_rtx_for_label (const_rtx label) 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. */ @@ -959,7 +994,7 @@ block_label_after (rtx insn) 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 @@ -1008,8 +1043,9 @@ split_pattern_seq (void) /* 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. */ @@ -1025,7 +1061,7 @@ split_pattern_seq (void) 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 @@ -1067,7 +1103,7 @@ erase_matching_seqs (void) /* 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. */ @@ -1283,7 +1319,7 @@ fill_hash_bucket (void) 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) { @@ -1416,7 +1452,10 @@ rest_of_rtl_seqabstr (void) 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 */ @@ -1428,8 +1467,8 @@ struct tree_opt_pass pass_rtl_seqabstr = { 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 */ + } };