OSDN Git Service

gcc/fortran:
[pf3gnuchains/gcc-fork.git] / gcc / struct-equiv.c
index fc563b6..3658e87 100644 (file)
@@ -1,6 +1,7 @@
 /* Control flow optimization code for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -54,7 +55,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    the number of inputs an miss an input conflict.  Sufficient information
    is gathered so that when we make another pass, we won't have to backtrack
    at the same point.
-   Another issue is that information in memory atttributes and/or REG_NOTES
+   Another issue is that information in memory attributes and/or REG_NOTES
    might have to be merged or discarded to make a valid match.  We don't want
    to discard such information when we are not certain that we want to merge
    the two (partial) blocks.
@@ -88,6 +89,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "target.h"
 #include "emit-rtl.h"
 #include "reload.h"
+#include "df.h"
 
 static void merge_memattrs (rtx, rtx);
 static bool set_dest_equiv_p (rtx x, rtx y, struct equiv_info *info);
@@ -99,7 +101,7 @@ static bool resolve_input_conflict (struct equiv_info *info);
    SECONDARY_MEMORY_NEEDED, cannot be done directly.  For our purposes, we
    consider them impossible to generate after reload (even though some
    might be synthesized when you throw enough code at them).
-   Since we don't know while procesing a cross-jump if a local register
+   Since we don't know while processing a cross-jump if a local register
    that is currently live will eventually be live and thus be an input,
    we keep track of potential inputs that would require an impossible move
    by using a prohibitively high cost for them.
@@ -201,7 +203,7 @@ merge_memattrs (rtx x, rtx y)
 }
 
 /* In SET, assign the bit for the register number of REG the value VALUE.
-   If REG is a hard register, do so for all its consituent registers.
+   If REG is a hard register, do so for all its constituent registers.
    Return the number of registers that have become included (as a positive
    number) or excluded (as a negative number).  */
 static int
@@ -249,7 +251,8 @@ struct_equiv_improve_checkpoint (struct struct_equiv_checkpoint *p,
                                 struct equiv_info *info)
 {
 #ifdef HAVE_cc0
-  if (reg_mentioned_p (cc0_rtx, info->x_start) && !sets_cc0_p (info->x_start))
+  if (reg_mentioned_p (cc0_rtx, info->cur.x_start)
+      && !sets_cc0_p (info->cur.x_start))
     return;
 #endif
   if (info->cur.input_count >= IMPOSSIBLE_MOVE_FACTOR)
@@ -309,10 +312,17 @@ struct_equiv_restore_checkpoint (struct struct_equiv_checkpoint *p,
 static int
 note_local_live (struct equiv_info *info, rtx x, rtx y, int rvalue)
 {
+  unsigned x_regno = REGNO (x);
+  unsigned y_regno = REGNO (y);
+  int x_nominal_nregs = (x_regno >= FIRST_PSEUDO_REGISTER
+                        ? 1 : hard_regno_nregs[x_regno][GET_MODE (x)]);
+  int y_nominal_nregs = (y_regno >= FIRST_PSEUDO_REGISTER
+                        ? 1 : hard_regno_nregs[y_regno][GET_MODE (y)]);
   int x_change = assign_reg_reg_set (info->x_local_live, x, rvalue);
   int y_change = assign_reg_reg_set (info->y_local_live, y, rvalue);
 
-  gcc_assert (x_change == y_change);
+  gcc_assert (x_nominal_nregs && y_nominal_nregs);
+  gcc_assert (x_change * y_nominal_nregs == y_change * x_nominal_nregs);
   if (y_change)
     {
       if (reload_completed)
@@ -336,7 +346,7 @@ note_local_live (struct equiv_info *info, rtx x, rtx y, int rvalue)
   return x_change;
 }
 
-/* Check if *XP is equivalent to Y.  Until an an unreconcilable difference is
+/* Check if *XP is equivalent to Y.  Until an unreconcilable difference is
    found, use in-group changes with validate_change on *XP to make register
    assignments agree.  It is the (not necessarily direct) callers
    responsibility to verify / confirm / cancel these changes, as appropriate.
@@ -475,7 +485,7 @@ rtx_equiv_p (rtx *xp, rtx y, int rvalue, struct equiv_info *info)
                   pair, use the old one.  If the width is the same, use the
                   old one if the modes match, but the new if they don't.
                   We don't want to get too fancy with subreg_regno_offset
-                  here, so we just test two straightforwad cases each.  */
+                  here, so we just test two straightforward cases each.  */
                if (info->live_update
                    && (x_mode != GET_MODE (info->x_local[i])
                        ? size >= size_i : size > size_i))
@@ -562,17 +572,13 @@ rtx_equiv_p (rtx *xp, rtx y, int rvalue, struct equiv_info *info)
          return false;
        x_dest1 = XEXP (x, 0);
        /* validate_change might have changed the destination.  Put it back
-          so that we can do a valid source match.  */
+          so that we can do a proper match for its role as an input.  */
        XEXP (x, 0) = x_dest0;
-       if (!rtx_equiv_p (&XEXP (x, 1), XEXP (y, 1), 0, info))
+       if (!rtx_equiv_p (&XEXP (x, 0), XEXP (y, 0), 1, info))
          return false;
        gcc_assert (x_dest1 == XEXP (x, 0));
        /* Process source.  */
        return rtx_equiv_p (&XEXP (x, 1), XEXP (y, 1), 1, info);
-      if (!rtx_equiv_p (&XEXP(x, 0), XEXP (y, 0), 0, info))
-       return false;
-      /* Process both subexpressions as inputs.  */
-      break;
       }
     case CLOBBER:
       gcc_assert (rvalue < 0);
@@ -861,12 +867,8 @@ death_notes_match_p (rtx i1 ATTRIBUTE_UNUSED, rtx i2 ATTRIBUTE_UNUSED,
            SET_HARD_REG_BIT (i2_regset, regno);
          }
 
-      GO_IF_HARD_REG_EQUAL (i1_regset, i2_regset, done);
-
-      return false;
-
-    done:
-      ;
+      if (!hard_reg_set_equal_p (i1_regset, i2_regset))
+       return false;
     }
 #endif
   return true;
@@ -983,13 +985,8 @@ insns_match_p (rtx i1, rtx i2, struct equiv_info *info)
 bool
 struct_equiv_init (int mode, struct equiv_info *info)
 {
-  if ((info->x_block->flags | info->y_block->flags) & BB_DIRTY)
-    update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
-                                     (PROP_DEATH_NOTES
-                                      | ((mode & CLEANUP_POST_REGSTACK)
-                                         ? PROP_POST_REGSTACK : 0)));
-  if (!REG_SET_EQUAL_P (info->x_block->il.rtl->global_live_at_end,
-                       info->y_block->il.rtl->global_live_at_end))
+  if (!REG_SET_EQUAL_P (DF_LR_OUT (info->x_block),
+                       DF_LR_OUT (info->y_block)))
     {
 #ifdef STACK_REGS
       unsigned rn;
@@ -1002,11 +999,11 @@ struct_equiv_init (int mode, struct equiv_info *info)
         least makes the regsets comparable.  */
       for (rn = FIRST_STACK_REG; rn <= LAST_STACK_REG; rn++)
        {
-         CLEAR_REGNO_REG_SET (info->x_block->il.rtl->global_live_at_end, rn);
-         CLEAR_REGNO_REG_SET (info->y_block->il.rtl->global_live_at_end, rn);
+         CLEAR_REGNO_REG_SET (DF_LR_OUT (info->x_block), rn);
+         CLEAR_REGNO_REG_SET (DF_LR_OUT (info->y_block), rn);
        }
-      if (!REG_SET_EQUAL_P (info->x_block->il.rtl->global_live_at_end,
-                           info->y_block->il.rtl->global_live_at_end))
+      if (!REG_SET_EQUAL_P (DF_LR_OUT (info->x_block),
+                           DF_LR_OUT (info->y_block)))
 #endif
        return false;
     }
@@ -1028,7 +1025,7 @@ struct_equiv_init (int mode, struct equiv_info *info)
   info->common_live = ALLOC_REG_SET (&reg_obstack);
   info->x_local_live = ALLOC_REG_SET (&reg_obstack);
   info->y_local_live = ALLOC_REG_SET (&reg_obstack);
-  COPY_REG_SET (info->common_live, info->x_block->il.rtl->global_live_at_end);
+  COPY_REG_SET (info->common_live, DF_LR_OUT (info->x_block));
   struct_equiv_make_checkpoint (&info->best_match, info);
   return true;
 }
@@ -1121,7 +1118,7 @@ struct_equiv_block_eq (int mode, struct equiv_info *info)
 
   if (mode & STRUCT_EQUIV_MATCH_JUMPS)
     {
-      /* The caller is expected to have comapred the jumps already, but we
+      /* The caller is expected to have compared the jumps already, but we
         need to match them again to get any local registers and inputs.  */
       gcc_assert (!info->cur.x_start == !info->cur.y_start);
       if (info->cur.x_start)
@@ -1272,7 +1269,7 @@ find_dying_inputs (struct equiv_info *info)
       int nregs = (regno >= FIRST_PSEUDO_REGISTER
                   ? 1 : hard_regno_nregs[regno][GET_MODE (x)]);
 
-      for (info->local_rvalue[i] = false; nregs >= 0; regno++, --nregs)
+      for (info->local_rvalue[i] = false; nregs > 0; regno++, --nregs)
        if (REGNO_REG_SET_P (info->x_local_live, regno))
          {
            info->dying_inputs++;