OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / rtl-factoring.c
index 298308f..07c66e2 100644 (file)
@@ -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))
         {
@@ -938,7 +962,7 @@ determine_seq_blocks (void)
 /* 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;
@@ -949,6 +973,17 @@ gen_symbol_ref_rtx_for_label (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 */
+ }
 };