OSDN Git Service

2007-03-04 Simon Martin <simartin@users.sourceforge.net>
[pf3gnuchains/gcc-fork.git] / gcc / fwprop.c
index 1e4f749..6ce9183 100644 (file)
@@ -104,7 +104,6 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    where the first two insns are now dead.  */
 
 
-static struct loops loops;
 static struct df *df;
 static int num_changes;
 
@@ -325,7 +324,8 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
          /* Dismiss transformation that we do not want to carry on.  */
          if (!valid_ops
              || new_op0 == op0
-             || GET_MODE (new_op0) != GET_MODE (op0))
+             || !(GET_MODE (new_op0) == GET_MODE (op0)
+                  || GET_MODE (new_op0) == VOIDmode))
            return true;
 
          canonicalize_address (new_op0);
@@ -390,7 +390,7 @@ propagate_rtx_1 (rtx *px, rtx old, rtx new, bool can_appear)
 }
 
 /* Replace all occurrences of OLD in X with NEW and try to simplify the
-   resulting expression (in mode MODE).  Return a new expresion if it is
+   resulting expression (in mode MODE).  Return a new expression if it is
    a constant, otherwise X.
 
    Simplifications where occurrences of NEW collapse to a constant are always
@@ -466,10 +466,22 @@ local_ref_killed_between_p (struct df_ref * ref, rtx from, rtx to)
 static bool
 use_killed_between (struct df_ref *use, rtx def_insn, rtx target_insn)
 {
-  basic_block def_bb, target_bb;
+  basic_block def_bb = BLOCK_FOR_INSN (def_insn);
+  basic_block target_bb = BLOCK_FOR_INSN (target_insn);
   int regno;
   struct df_ref * def;
 
+  /* In some obscure situations we can have a def reaching a use
+     that is _before_ the def.  In other words the def does not
+     dominate the use even though the use and def are in the same
+     basic block.  This can happen when a register may be used
+     uninitialized in a loop.  In such cases, we must assume that
+     DEF is not available.  */
+  if (def_bb == target_bb
+      ? DF_INSN_LUID (df, def_insn) >= DF_INSN_LUID (df, target_insn)
+      : !dominated_by_p (CDI_DOMINATORS, target_bb, def_bb))
+    return true;
+
   /* Check if the reg in USE has only one definition.  We already
      know that this definition reaches use, or we wouldn't be here.  */
   regno = DF_REF_REGNO (use);
@@ -477,22 +489,9 @@ use_killed_between (struct df_ref *use, rtx def_insn, rtx target_insn)
   if (def && (def->next_reg == NULL))
     return false;
 
-  /* Check if we are in the same basic block.  */
-  def_bb = BLOCK_FOR_INSN (def_insn);
-  target_bb = BLOCK_FOR_INSN (target_insn);
+  /* Check locally if we are in the same basic block.  */
   if (def_bb == target_bb)
-    {
-      /* In some obscure situations we can have a def reaching a use
-        that is _before_ the def.  In other words the def does not
-        dominate the use even though the use and def are in the same
-        basic block.  This can happen when a register may be used
-        uninitialized in a loop.  In such cases, we must assume that
-        DEF is not available.  */
-      if (DF_INSN_LUID (df, def_insn) >= DF_INSN_LUID (df, target_insn))
-       return true;
-
-      return local_ref_killed_between_p (use, def_insn, target_insn);
-    }
+    return local_ref_killed_between_p (use, def_insn, target_insn);
 
   /* Finally, if DEF_BB is the sole predecessor of TARGET_BB.  */
   if (single_pred_p (target_bb)
@@ -693,9 +692,10 @@ try_fwprop_subst (struct df_ref *use, rtx *loc, rtx new, rtx def_insn, bool set_
          if (dump_file)
            fprintf (dump_file, " Setting REG_EQUAL note\n");
 
-         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (new),
-                                               REG_NOTES (insn));
+         set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new));
 
+         /* ??? Is this still necessary if we add the note through
+            set_unique_reg_note?  */
           if (!CONSTANT_P (new))
            update_df (insn, loc, DF_INSN_USES (df, def_insn),
                       type, DF_REF_IN_NOTE);
@@ -848,6 +848,8 @@ forward_propagate_into (struct df_ref *use)
 
   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
     return;
+  if (DF_REF_FLAGS (use) & DF_REF_ARTIFICIAL)
+    return;
 
   /* Only consider uses that have a single definition.  */
   defs = DF_REF_CHAIN (use);
@@ -857,10 +859,12 @@ forward_propagate_into (struct df_ref *use)
   def = defs->ref;
   if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
     return;
+  if (DF_REF_FLAGS (def) & DF_REF_ARTIFICIAL)
+    return;
 
   /* Do not propagate loop invariant definitions inside the loop if
      we are going to unroll.  */
-  if (loops.num > 0
+  if (current_loops
       && DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father)
     return;
 
@@ -890,20 +894,18 @@ static void
 fwprop_init (void)
 {
   num_changes = 0;
+  calculate_dominance_info (CDI_DOMINATORS);
 
   /* We do not always want to propagate into loops, so we have to find
      loops and be careful about them.  But we have to call flow_loops_find
      before df_analyze, because flow_loops_find may introduce new jump
      insns (sadly) if we are not working in cfglayout mode.  */
   if (flag_rerun_cse_after_loop && (flag_unroll_loops || flag_peel_loops))
-    {
-      calculate_dominance_info (CDI_DOMINATORS);
-      flow_loops_find (&loops);
-    }
+    loop_optimizer_init (0);
 
   /* Now set up the dataflow problem (we only want use-def chains) and
      put the dataflow solver to work.  */
-  df = df_init (DF_SUBREGS | DF_EQUIV_NOTES);
+  df = df_init (DF_HARD_REGS | DF_SUBREGS | DF_EQUIV_NOTES);
   df_chain_add_problem (df, DF_UD_CHAIN);
   df_analyze (df);
   df_dump (df, dump_file);
@@ -915,12 +917,9 @@ fwprop_done (void)
   df_finish (df);
 
   if (flag_rerun_cse_after_loop && (flag_unroll_loops || flag_peel_loops))
-    {
-      flow_loops_free (&loops);
-      free_dominance_info (CDI_DOMINATORS);
-      loops.num = 0;
-    }
+    loop_optimizer_finalize ();
 
+  free_dominance_info (CDI_DOMINATORS);
   cleanup_cfg (0);
   delete_trivially_dead_insns (get_insns (), max_reg_num ());
 
@@ -958,7 +957,7 @@ fwprop (void)
     {
       struct df_ref *use = DF_USES_GET (df, i);
       if (use)
-       if (loops.num == 0
+       if (!current_loops 
            || DF_REF_TYPE (use) == DF_REF_REG_USE
            || DF_REF_BB (use)->loop_father == NULL)
          forward_propagate_into (use);