OSDN Git Service

* config/pa/fptr.c: Update license header.
[pf3gnuchains/gcc-fork.git] / gcc / rtl-factoring.c
index 864836e..6e37df7 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -36,6 +36,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "tree-flow.h"
 #include "timevar.h"
 #include "output.h"
+#include "df.h"
+#include "addresses.h"
 
 /* Sequence abstraction:
 
@@ -125,7 +127,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    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.
 */
 
@@ -227,7 +229,7 @@ typedef struct seq_block_def
   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.  */
@@ -453,36 +455,40 @@ collect_pattern_seqs (void)
   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
 
@@ -534,19 +540,18 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length)
   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);
@@ -555,7 +560,8 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length)
   /* 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))
         {
@@ -568,7 +574,6 @@ clear_regs_live_in_seq (HARD_REG_SET * regs, rtx insn, int length)
     }
 
   /* Free unused data.  */
-  free_propagate_block_info (pbi);
   CLEAR_REG_SET (&live);
 }
 
@@ -689,11 +694,12 @@ recompute_gain_for_pattern_seq (pattern_seq pseq)
 #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.  */
@@ -888,7 +894,7 @@ determine_seq_blocks (void)
         }
 
       /* 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));
@@ -972,14 +978,13 @@ split_blocks_after_seqs (void)
       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
@@ -1028,7 +1033,7 @@ split_pattern_seq (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));
 }
 
@@ -1080,12 +1085,12 @@ erase_matching_seqs (void)
           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);
@@ -1129,7 +1134,7 @@ abstract_best_seq (void)
   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;
@@ -1357,6 +1362,8 @@ static void
 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 ,
@@ -1373,7 +1380,7 @@ rtl_seqabstr (void)
   /* 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)
@@ -1388,20 +1395,6 @@ rtl_seqabstr (void)
 
   /* 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.  */
@@ -1414,17 +1407,12 @@ gate_rtl_seqabstr (void)
 
 /* 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 = {
@@ -1439,6 +1427,7 @@ 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 */