OSDN Git Service

2010-04-26 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 7c79afb..b38ab2e 100644 (file)
@@ -1,6 +1,6 @@
 /* RTL simplification functions for GNU compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "regs.h"
 #include "hard-reg-set.h"
 #include "flags.h"
-#include "real.h"
 #include "insn-config.h"
 #include "recog.h"
 #include "function.h"
@@ -350,15 +349,14 @@ simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
   return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
 \f
-/* Replace all occurrences of OLD_RTX in X with FN (X', DATA), where X'
-   is an expression in X that is equal to OLD_RTX.  Canonicalize and
-   simplify the result.
-
-   If FN is null, assume FN (X', DATA) == copy_rtx (DATA).  */
+/* If FN is NULL, replace all occurrences of OLD_RTX in X with copy_rtx (DATA)
+   and simplify the result.  If FN is non-NULL, call this callback on each
+   X, if it returns non-NULL, replace X with its return value and simplify the
+   result.  */
 
 rtx
 simplify_replace_fn_rtx (rtx x, const_rtx old_rtx,
-                        rtx (*fn) (rtx, void *), void *data)
+                        rtx (*fn) (rtx, const_rtx, void *), void *data)
 {
   enum rtx_code code = GET_CODE (x);
   enum machine_mode mode = GET_MODE (x);
@@ -368,17 +366,14 @@ simplify_replace_fn_rtx (rtx x, const_rtx old_rtx,
   rtvec vec, newvec;
   int i, j;
 
-  /* If X is OLD_RTX, return FN (X, DATA), with a null FN.  Otherwise,
-     if this is an expression, try to build a new expression, substituting
-     recursively.  If we can't do anything, return our input.  */
-
-  if (rtx_equal_p (x, old_rtx))
+  if (__builtin_expect (fn != NULL, 0))
     {
-      if (fn)
-       return fn (x, data);
-      else
-       return copy_rtx ((rtx) data);
+      newx = fn (x, old_rtx, data);
+      if (newx)
+       return newx;
     }
+  else if (rtx_equal_p (x, old_rtx))
+    return copy_rtx ((rtx) data);
 
   switch (GET_RTX_CLASS (code))
     {
@@ -1486,10 +1481,10 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          d = t;
          break;
        case ABS:
-         d = REAL_VALUE_ABS (d);
+         d = real_value_abs (&d);
          break;
        case NEG:
-         d = REAL_VALUE_NEGATE (d);
+         d = real_value_negate (&d);
          break;
        case FLOAT_TRUNCATE:
          d = real_value_truncate (mode, d);
@@ -1774,44 +1769,42 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 
       if (SCALAR_INT_MODE_P (mode))
        {
-         HOST_WIDE_INT coeff0h = 0, coeff1h = 0;
-         unsigned HOST_WIDE_INT coeff0l = 1, coeff1l = 1;
+         double_int coeff0, coeff1;
          rtx lhs = op0, rhs = op1;
 
+         coeff0 = double_int_one;
+         coeff1 = double_int_one;
+
          if (GET_CODE (lhs) == NEG)
            {
-             coeff0l = -1;
-             coeff0h = -1;
+             coeff0 = double_int_minus_one;
              lhs = XEXP (lhs, 0);
            }
          else if (GET_CODE (lhs) == MULT
                   && CONST_INT_P (XEXP (lhs, 1)))
            {
-             coeff0l = INTVAL (XEXP (lhs, 1));
-             coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0;
+             coeff0 = shwi_to_double_int (INTVAL (XEXP (lhs, 1)));
              lhs = XEXP (lhs, 0);
            }
          else if (GET_CODE (lhs) == ASHIFT
                   && CONST_INT_P (XEXP (lhs, 1))
-                  && INTVAL (XEXP (lhs, 1)) >= 0
+                   && INTVAL (XEXP (lhs, 1)) >= 0
                   && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
            {
-             coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
-             coeff0h = 0;
+             coeff0 = double_int_setbit (double_int_zero,
+                                         INTVAL (XEXP (lhs, 1)));
              lhs = XEXP (lhs, 0);
            }
 
          if (GET_CODE (rhs) == NEG)
            {
-             coeff1l = -1;
-             coeff1h = -1;
+             coeff1 = double_int_minus_one;
              rhs = XEXP (rhs, 0);
            }
          else if (GET_CODE (rhs) == MULT
                   && CONST_INT_P (XEXP (rhs, 1)))
            {
-             coeff1l = INTVAL (XEXP (rhs, 1));
-             coeff1h = INTVAL (XEXP (rhs, 1)) < 0 ? -1 : 0;
+             coeff1 = shwi_to_double_int (INTVAL (XEXP (rhs, 1)));
              rhs = XEXP (rhs, 0);
            }
          else if (GET_CODE (rhs) == ASHIFT
@@ -1819,8 +1812,8 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
                   && INTVAL (XEXP (rhs, 1)) >= 0
                   && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
            {
-             coeff1l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1));
-             coeff1h = 0;
+             coeff1 = double_int_setbit (double_int_zero,
+                                         INTVAL (XEXP (rhs, 1)));
              rhs = XEXP (rhs, 0);
            }
 
@@ -1828,12 +1821,11 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
            {
              rtx orig = gen_rtx_PLUS (mode, op0, op1);
              rtx coeff;
-             unsigned HOST_WIDE_INT l;
-             HOST_WIDE_INT h;
+             double_int val;
              bool speed = optimize_function_for_speed_p (cfun);
 
-             add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h);
-             coeff = immed_double_const (l, h, mode);
+             val = double_int_add (coeff0, coeff1);
+             coeff = immed_double_int_const (val, mode);
 
              tem = simplify_gen_binary (MULT, mode, lhs, coeff);
              return rtx_cost (tem, SET, speed) <= rtx_cost (orig, SET, speed)
@@ -1957,21 +1949,21 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 
       if (SCALAR_INT_MODE_P (mode))
        {
-         HOST_WIDE_INT coeff0h = 0, negcoeff1h = -1;
-         unsigned HOST_WIDE_INT coeff0l = 1, negcoeff1l = -1;
+         double_int coeff0, negcoeff1;
          rtx lhs = op0, rhs = op1;
 
+         coeff0 = double_int_one;
+         negcoeff1 = double_int_minus_one;
+
          if (GET_CODE (lhs) == NEG)
            {
-             coeff0l = -1;
-             coeff0h = -1;
+             coeff0 = double_int_minus_one;
              lhs = XEXP (lhs, 0);
            }
          else if (GET_CODE (lhs) == MULT
                   && CONST_INT_P (XEXP (lhs, 1)))
            {
-             coeff0l = INTVAL (XEXP (lhs, 1));
-             coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0;
+             coeff0 = shwi_to_double_int (INTVAL (XEXP (lhs, 1)));
              lhs = XEXP (lhs, 0);
            }
          else if (GET_CODE (lhs) == ASHIFT
@@ -1979,22 +1971,20 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
                   && INTVAL (XEXP (lhs, 1)) >= 0
                   && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
            {
-             coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
-             coeff0h = 0;
+             coeff0 = double_int_setbit (double_int_zero,
+                                         INTVAL (XEXP (lhs, 1)));
              lhs = XEXP (lhs, 0);
            }
 
          if (GET_CODE (rhs) == NEG)
            {
-             negcoeff1l = 1;
-             negcoeff1h = 0;
+             negcoeff1 = double_int_one;
              rhs = XEXP (rhs, 0);
            }
          else if (GET_CODE (rhs) == MULT
                   && CONST_INT_P (XEXP (rhs, 1)))
            {
-             negcoeff1l = -INTVAL (XEXP (rhs, 1));
-             negcoeff1h = INTVAL (XEXP (rhs, 1)) <= 0 ? 0 : -1;
+             negcoeff1 = shwi_to_double_int (-INTVAL (XEXP (rhs, 1)));
              rhs = XEXP (rhs, 0);
            }
          else if (GET_CODE (rhs) == ASHIFT
@@ -2002,8 +1992,9 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
                   && INTVAL (XEXP (rhs, 1)) >= 0
                   && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
            {
-             negcoeff1l = -(((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1)));
-             negcoeff1h = -1;
+             negcoeff1 = double_int_setbit (double_int_zero,
+                                            INTVAL (XEXP (rhs, 1)));
+             negcoeff1 = double_int_neg (negcoeff1);
              rhs = XEXP (rhs, 0);
            }
 
@@ -2011,12 +2002,11 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
            {
              rtx orig = gen_rtx_MINUS (mode, op0, op1);
              rtx coeff;
-             unsigned HOST_WIDE_INT l;
-             HOST_WIDE_INT h;
+             double_int val;
              bool speed = optimize_function_for_speed_p (cfun);
 
-             add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h, &l, &h);
-             coeff = immed_double_const (l, h, mode);
+             val = double_int_add (coeff0, negcoeff1);
+             coeff = immed_double_int_const (val, mode);
 
              tem = simplify_gen_binary (MULT, mode, lhs, coeff);
              return rtx_cost (tem, SET, speed) <= rtx_cost (orig, SET, speed)