OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / rtlanal.c
index 3692c16..7c4a49b 100644 (file)
@@ -1,7 +1,7 @@
 /* Analyze RTL for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -25,8 +25,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "diagnostic-core.h"
-#include "rtl.h"
 #include "hard-reg-set.h"
+#include "rtl.h"
 #include "insn-config.h"
 #include "recog.h"
 #include "target.h"
@@ -999,6 +999,56 @@ set_of (const_rtx pat, const_rtx insn)
   note_stores (INSN_P (insn) ? PATTERN (insn) : insn, set_of_1, &data);
   return data.found;
 }
+
+/* This function, called through note_stores, collects sets and
+   clobbers of hard registers in a HARD_REG_SET, which is pointed to
+   by DATA.  */
+void
+record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
+{
+  HARD_REG_SET *pset = (HARD_REG_SET *)data;
+  if (REG_P (x) && HARD_REGISTER_P (x))
+    add_to_hard_reg_set (pset, GET_MODE (x), REGNO (x));
+}
+
+/* Examine INSN, and compute the set of hard registers written by it.
+   Store it in *PSET.  Should only be called after reload.  */
+void
+find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset)
+{
+  rtx link;
+
+  CLEAR_HARD_REG_SET (*pset);
+  note_stores (PATTERN (insn), record_hard_reg_sets, pset);
+  if (CALL_P (insn))
+    IOR_HARD_REG_SET (*pset, call_used_reg_set);
+  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+    if (REG_NOTE_KIND (link) == REG_INC)
+      record_hard_reg_sets (XEXP (link, 0), NULL, pset);
+}
+
+/* A for_each_rtx subroutine of record_hard_reg_uses.  */
+static int
+record_hard_reg_uses_1 (rtx *px, void *data)
+{
+  rtx x = *px;
+  HARD_REG_SET *pused = (HARD_REG_SET *)data;
+
+  if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
+    {
+      int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)];
+      while (nregs-- > 0)
+       SET_HARD_REG_BIT (*pused, REGNO (x) + nregs);
+    }
+  return 0;
+}
+
+/* Like record_hard_reg_sets, but called through note_uses.  */
+void
+record_hard_reg_uses (rtx *px, void *data)
+{
+  for_each_rtx (px, record_hard_reg_uses_1, data);
+}
 \f
 /* Given an INSN, return a SET expression if this insn has only a single SET.
    It may also have CLOBBERs, USEs, or SET whose output
@@ -1868,6 +1918,7 @@ alloc_reg_note (enum reg_note kind, rtx datum, rtx list)
     case REG_CC_USER:
     case REG_LABEL_TARGET:
     case REG_LABEL_OPERAND:
+    case REG_TM:
       /* These types of register notes use an INSN_LIST rather than an
         EXPR_LIST, so that copying is done right and dumps look
         better.  */
@@ -2660,8 +2711,11 @@ tablejump_p (const_rtx insn, rtx *labelp, rtx *tablep)
 {
   rtx label, table;
 
-  if (JUMP_P (insn)
-      && (label = JUMP_LABEL (insn)) != NULL_RTX
+  if (!JUMP_P (insn))
+    return false;
+
+  label = JUMP_LABEL (insn);
+  if (label != NULL_RTX && !ANY_RETURN_P (label)
       && (table = next_active_insn (label)) != NULL_RTX
       && JUMP_TABLE_DATA_P (table))
     {
@@ -3671,11 +3725,12 @@ label_is_jump_target_p (const_rtx label, const_rtx jump_insn)
    Another is in rtl generation, to pick the cheapest way to multiply.
    Other uses like the latter are expected in the future.
 
-   SPEED parameter specify whether costs optimized for speed or size should
+   X appears as operand OPNO in an expression with code OUTER_CODE.
+   SPEED specifies whether costs optimized for speed or size should
    be returned.  */
 
 int
-rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed)
+rtx_cost (rtx x, enum rtx_code outer_code, int opno, bool speed)
 {
   int i, j;
   enum rtx_code code;
@@ -3723,7 +3778,7 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed)
       break;
 
     default:
-      if (targetm.rtx_costs (x, code, outer_code, &total, speed))
+      if (targetm.rtx_costs (x, code, outer_code, opno, &total, speed))
        return total;
       break;
     }
@@ -3734,22 +3789,23 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed)
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
-      total += rtx_cost (XEXP (x, i), code, speed);
+      total += rtx_cost (XEXP (x, i), code, i, speed);
     else if (fmt[i] == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-       total += rtx_cost (XVECEXP (x, i, j), code, speed);
+       total += rtx_cost (XVECEXP (x, i, j), code, i, speed);
 
   return total;
 }
 
 /* Fill in the structure C with information about both speed and size rtx
-   costs for X, with outer code OUTER.  */
+   costs for X, which is operand OPNO in an expression with code OUTER.  */
 
 void
-get_full_rtx_cost (rtx x, enum rtx_code outer, struct full_rtx_costs *c)
+get_full_rtx_cost (rtx x, enum rtx_code outer, int opno,
+                  struct full_rtx_costs *c)
 {
-  c->speed = rtx_cost (x, outer, true);
-  c->size = rtx_cost (x, outer, false);
+  c->speed = rtx_cost (x, outer, opno, true);
+  c->size = rtx_cost (x, outer, opno, false);
 }
 
 \f
@@ -3777,7 +3833,7 @@ address_cost (rtx x, enum machine_mode mode, addr_space_t as, bool speed)
 int
 default_address_cost (rtx x, bool speed)
 {
-  return rtx_cost (x, MEM, speed);
+  return rtx_cost (x, MEM, 0, speed);
 }
 \f
 
@@ -4268,6 +4324,11 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
        nonzero = -1;
       break;
 
+    case CLRSB:
+      /* This is at most the number of bits in the mode minus 1.  */
+      nonzero = ((unsigned HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
+      break;
+
     case PARITY:
       nonzero = 1;
       break;
@@ -4779,7 +4840,7 @@ insn_rtx_cost (rtx pat, bool speed)
   else
     return 0;
 
-  cost = rtx_cost (SET_SRC (set), SET, speed);
+  cost = set_src_cost (SET_SRC (set), speed);
   return cost > 0 ? cost : COSTS_N_INSNS (1);
 }