OSDN Git Service

2007-10-20 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / struct-equiv.c
index e38ae73..6675e5b 100644 (file)
@@ -1,12 +1,13 @@
 /* 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.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* Try to match two basic blocks - or their ends - for structural equivalence.
    We scan the blocks from their ends backwards, and expect that insns are
@@ -88,6 +88,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);
@@ -326,7 +327,7 @@ note_local_live (struct equiv_info *info, rtx x, rtx y, int rvalue)
       if (reload_completed)
        {
          unsigned x_regno ATTRIBUTE_UNUSED = REGNO (x);
-         unsigned y_regno = REGNO (y);
+         unsigned y_regno ATTRIBUTE_UNUSED = REGNO (y);
          enum machine_mode x_mode = GET_MODE (x);
 
          if (secondary_reload_class (0, REGNO_REG_CLASS (y_regno), x_mode, x)
@@ -344,7 +345,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.
@@ -429,7 +430,7 @@ rtx_equiv_p (rtx *xp, rtx y, int rvalue, struct equiv_info *info)
          return false;
        else if (x_common_live)
          {
-           if (! rvalue || info->input_cost < 0 || no_new_pseudos)
+           if (! rvalue || info->input_cost < 0 || reload_completed)
              return false;
            /* If info->live_update is not set, we are processing notes.
               We then allow a match with x_input / y_input found in a
@@ -483,7 +484,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))
@@ -570,17 +571,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);
@@ -869,12 +866,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;
@@ -991,13 +984,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;
@@ -1010,11 +998,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;
     }
@@ -1036,7 +1024,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;
 }
@@ -1280,7 +1268,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++;