OSDN Git Service

* expr.c (init_expr_once): Don't use start/end_sequence.
[pf3gnuchains/gcc-fork.git] / gcc / simplify-rtx.c
index 88ca32b..36bcc1a 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -43,7 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    virtual regs here because the simplify_*_operation routines are called
    by integrate.c, which is called before virtual register instantiation.
 
-   ?!? FIXED_BASE_PLUS_P and NONZERO_BASE_PLUS_P need to move into 
+   ?!? FIXED_BASE_PLUS_P and NONZERO_BASE_PLUS_P need to move into
    a header file so that their definitions can be shared with the
    simplification routines in simplify-rtx.c.  Until then, do not
    change these macros without also changing the copy in simplify-rtx.c.  */
@@ -101,11 +101,6 @@ static int simplify_plus_minus_op_data_cmp PARAMS ((const void *,
 static rtx simplify_plus_minus         PARAMS ((enum rtx_code,
                                                 enum machine_mode, rtx,
                                                 rtx, int));
-static void check_fold_consts          PARAMS ((PTR));
-static void simplify_unary_real                PARAMS ((PTR));
-static void simplify_binary_real       PARAMS ((PTR));
-static void simplify_binary_is2orm1    PARAMS ((PTR));
-
 \f
 /* Negate a CONST_INT rtx, truncating (because a conversion from a
    maximally negative number can overflow).  */
@@ -114,11 +109,11 @@ neg_const_int (mode, i)
      enum machine_mode mode;
      rtx i;
 {
-  return GEN_INT (trunc_int_for_mode (- INTVAL (i), mode));
+  return gen_int_mode (- INTVAL (i), mode);
 }
 
 \f
-/* Make a binary operation by properly ordering the operands and 
+/* Make a binary operation by properly ordering the operands and
    seeing if the expression folds.  */
 
 rtx
@@ -305,7 +300,7 @@ simplify_replace_rtx (x, old, new)
        rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
 
        return
-         simplify_gen_ternary (code, mode, 
+         simplify_gen_ternary (code, mode,
                                (op_mode != VOIDmode
                                 ? op_mode
                                 : GET_MODE (op0)),
@@ -341,65 +336,6 @@ simplify_replace_rtx (x, old, new)
   return x;
 }
 \f
-/* Subroutine of simplify_unary_operation, called via do_float_handler.
-   Handles simplification of unary ops on floating point values.  */
-struct simplify_unary_real_args
-{
-  rtx operand;
-  rtx result;
-  enum machine_mode mode;
-  enum rtx_code code;
-  bool want_integer;
-};
-#define REAL_VALUE_ABS(d_) \
-   (REAL_VALUE_NEGATIVE (d_) ? REAL_VALUE_NEGATE (d_) : (d_))
-
-static void
-simplify_unary_real (p)
-     PTR p;
-{
-  REAL_VALUE_TYPE d;
-
-  struct simplify_unary_real_args *args =
-    (struct simplify_unary_real_args *) p;
-
-  REAL_VALUE_FROM_CONST_DOUBLE (d, args->operand);
-
-  if (args->want_integer)
-    {
-      HOST_WIDE_INT i;
-
-      switch (args->code)
-       {
-       case FIX:               i = REAL_VALUE_FIX (d);           break;
-       case UNSIGNED_FIX:      i = REAL_VALUE_UNSIGNED_FIX (d);  break;
-       default:
-         abort ();
-       }
-      args->result = GEN_INT (trunc_int_for_mode (i, args->mode));
-    }
-  else
-    {
-      switch (args->code)
-       {
-       case SQRT:
-         /* We don't attempt to optimize this.  */
-         args->result = 0;
-         return;
-
-       case ABS:             d = REAL_VALUE_ABS (d);                   break;
-       case NEG:             d = REAL_VALUE_NEGATE (d);                break;
-       case FLOAT_TRUNCATE:  d = real_value_truncate (args->mode, d);  break;
-       case FLOAT_EXTEND:    /* All this does is change the mode.  */  break;
-       case FIX:             d = REAL_VALUE_RNDZINT (d);               break;
-       case UNSIGNED_FIX:    d = REAL_VALUE_UNSIGNED_RNDZINT (d);      break;
-       default:
-         abort ();
-       }
-      args->result = CONST_DOUBLE_FROM_REAL_VALUE (d, args->mode);
-    }
-}
-
 /* Try to simplify a unary operation CODE whose output mode is to be
    MODE with input operand OP whose mode was originally OP_MODE.
    Return zero if no simplification can be made.  */
@@ -638,16 +574,25 @@ simplify_unary_operation (code, mode, op, op_mode)
   else if (GET_CODE (trueop) == CONST_DOUBLE
           && GET_MODE_CLASS (mode) == MODE_FLOAT)
     {
-      struct simplify_unary_real_args args;
-      args.operand = trueop;
-      args.mode = mode;
-      args.code = code;
-      args.want_integer = false;
+      REAL_VALUE_TYPE d;
+      REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
 
-      if (do_float_handler (simplify_unary_real, (PTR) &args))
-       return args.result;
+      switch (code)
+       {
+       case SQRT:
+         /* We don't attempt to optimize this.  */
+         return 0;
 
-      return 0;
+       case ABS:             d = REAL_VALUE_ABS (d);                   break;
+       case NEG:             d = REAL_VALUE_NEGATE (d);                break;
+       case FLOAT_TRUNCATE:  d = real_value_truncate (mode, d);        break;
+       case FLOAT_EXTEND:    /* All this does is change the mode.  */  break;
+       case FIX:             d = REAL_VALUE_RNDZINT (d);               break;
+       case UNSIGNED_FIX:    d = REAL_VALUE_UNSIGNED_RNDZINT (d);      break;
+       default:
+         abort ();
+       }
+      return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
     }
 
   else if (GET_CODE (trueop) == CONST_DOUBLE
@@ -655,16 +600,17 @@ simplify_unary_operation (code, mode, op, op_mode)
           && GET_MODE_CLASS (mode) == MODE_INT
           && width <= HOST_BITS_PER_WIDE_INT && width > 0)
     {
-      struct simplify_unary_real_args args;
-      args.operand = trueop;
-      args.mode = mode;
-      args.code = code;
-      args.want_integer = true;
-
-      if (do_float_handler (simplify_unary_real, (PTR) &args))
-       return args.result;
-
-      return 0;
+      HOST_WIDE_INT i;
+      REAL_VALUE_TYPE d;
+      REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
+      switch (code)
+       {
+       case FIX:               i = REAL_VALUE_FIX (d);           break;
+       case UNSIGNED_FIX:      i = REAL_VALUE_UNSIGNED_FIX (d);  break;
+       default:
+         abort ();
+       }
+      return gen_int_mode (i, mode);
     }
 
   /* This was formerly used only for non-IEEE float.
@@ -731,7 +677,7 @@ simplify_unary_operation (code, mode, op, op_mode)
            return convert_memory_address (Pmode, op);
          break;
 #endif
-         
+
        default:
          break;
        }
@@ -740,64 +686,6 @@ simplify_unary_operation (code, mode, op, op_mode)
     }
 }
 \f
-/* Subroutine of simplify_binary_operation, called via do_float_handler.
-   Handles simplification of binary ops on floating point values.  */
-struct simplify_binary_real_args
-{
-  rtx trueop0, trueop1;
-  rtx result;
-  enum rtx_code code;
-  enum machine_mode mode;
-};
-
-static void
-simplify_binary_real (p)
-     PTR p;
-{
-  REAL_VALUE_TYPE f0, f1, value;
-  struct simplify_binary_real_args *args =
-    (struct simplify_binary_real_args *) p;
-
-  REAL_VALUE_FROM_CONST_DOUBLE (f0, args->trueop0);
-  REAL_VALUE_FROM_CONST_DOUBLE (f1, args->trueop1);
-  f0 = real_value_truncate (args->mode, f0);
-  f1 = real_value_truncate (args->mode, f1);
-
-#ifndef REAL_INFINITY
-  if (args->code == DIV && REAL_VALUES_EQUAL (f1, dconst0))
-    {
-      args->result = 0;
-      return;
-    }
-#endif
-  REAL_ARITHMETIC (value, rtx_to_tree_code (args->code), f0, f1);
-
-  value = real_value_truncate (args->mode, value);
-  args->result = CONST_DOUBLE_FROM_REAL_VALUE (value, args->mode);
-}
-
-/* Another subroutine called via do_float_handler.  This one tests
-   the floating point value given against 2. and -1.  */
-struct simplify_binary_is2orm1_args
-{
-  rtx value;
-  bool is_2;
-  bool is_m1;
-};
-
-static void
-simplify_binary_is2orm1 (p)
-     PTR p;
-{
-  REAL_VALUE_TYPE d;
-  struct simplify_binary_is2orm1_args *args =
-    (struct simplify_binary_is2orm1_args *) p;
-
-  REAL_VALUE_FROM_CONST_DOUBLE (d, args->value);
-  args->is_2 = REAL_VALUES_EQUAL (d, dconst2);
-  args->is_m1 = REAL_VALUES_EQUAL (d, dconstm1);
-}
-
 /* Simplify a binary operation CODE with result mode MODE, operating on OP0
    and OP1.  Return 0 if no simplification is possible.
 
@@ -837,15 +725,22 @@ simplify_binary_operation (code, mode, op0, op1)
       && GET_CODE (trueop1) == CONST_DOUBLE
       && mode == GET_MODE (op0) && mode == GET_MODE (op1))
     {
-      struct simplify_binary_real_args args;
-      args.trueop0 = trueop0;
-      args.trueop1 = trueop1;
-      args.mode = mode;
-      args.code = code;
-
-      if (do_float_handler (simplify_binary_real, (PTR) &args))
-       return args.result;
-      return 0;
+      REAL_VALUE_TYPE f0, f1, value;
+
+      REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
+      REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
+      f0 = real_value_truncate (mode, f0);
+      f1 = real_value_truncate (mode, f1);
+
+      if (code == DIV
+         && !MODE_HAS_INFINITIES (mode)
+         && REAL_VALUES_EQUAL (f1, dconst0))
+       return 0;
+
+      REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
+
+      value = real_value_truncate (mode, value);
+      return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
     }
 
   /* We can fold some multi-word operations.  */
@@ -1069,7 +964,7 @@ simplify_binary_operation (code, mode, op0, op1)
            }
 
          /* If one of the operands is a PLUS or a MINUS, see if we can
-            simplify this by the associative law. 
+            simplify this by the associative law.
             Don't use the associative law for floating point.
             The inaccuracy makes it nonassociative,
             and subtle programs can break if operations are associated.  */
@@ -1118,7 +1013,7 @@ simplify_binary_operation (code, mode, op0, op1)
 #endif
                return xop00;
            }
-         break;              
+         break;
 
        case MINUS:
          /* We can't assume x-x is 0 even with non-IEEE floating point,
@@ -1207,7 +1102,7 @@ simplify_binary_operation (code, mode, op0, op1)
            return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
 
          /* If one of the operands is a PLUS or a MINUS, see if we can
-            simplify this by the associative law. 
+            simplify this by the associative law.
             Don't use the associative law for floating point.
             The inaccuracy makes it nonassociative,
             and subtle programs can break if operations are associated.  */
@@ -1276,20 +1171,18 @@ simplify_binary_operation (code, mode, op0, op1)
              && ! rtx_equal_function_value_matters)
            return gen_rtx_ASHIFT (mode, op0, GEN_INT (val));
 
+         /* x*2 is x+x and x*(-1) is -x */
          if (GET_CODE (trueop1) == CONST_DOUBLE
-             && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT)
+             && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
+             && GET_MODE (op0) == mode)
            {
-             struct simplify_binary_is2orm1_args args;
-
-             args.value = trueop1;
-             if (! do_float_handler (simplify_binary_is2orm1, (PTR) &args))
-               return 0;
+             REAL_VALUE_TYPE d;
+             REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
 
-             /* x*2 is x+x and x*(-1) is -x */
-             if (args.is_2 && GET_MODE (op0) == mode)
+             if (REAL_VALUES_EQUAL (d, dconst2))
                return gen_rtx_PLUS (mode, op0, copy_rtx (op0));
 
-             else if (args.is_m1 && GET_MODE (op0) == mode)
+             if (REAL_VALUES_EQUAL (d, dconstm1))
                return gen_rtx_NEG (mode, op0);
            }
          break;
@@ -1387,7 +1280,7 @@ simplify_binary_operation (code, mode, op0, op1)
              if (! REAL_VALUES_EQUAL (d, dconst0))
                {
                  REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
-                 return gen_rtx_MULT (mode, op0, 
+                 return gen_rtx_MULT (mode, op0,
                                       CONST_DOUBLE_FROM_REAL_VALUE (d, mode));
                }
            }
@@ -1427,14 +1320,14 @@ simplify_binary_operation (code, mode, op0, op1)
          break;
 
        case SMIN:
-         if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT 
+         if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
              && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1)
              && ! side_effects_p (op0))
            return op1;
          else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
            return op0;
          break;
-          
+
        case SMAX:
          if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
              && ((unsigned HOST_WIDE_INT) INTVAL (trueop1)
@@ -1451,7 +1344,7 @@ simplify_binary_operation (code, mode, op0, op1)
          else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
            return op0;
          break;
-           
+
        case UMAX:
          if (trueop1 == constm1_rtx && ! side_effects_p (op0))
            return op1;
@@ -1469,7 +1362,7 @@ simplify_binary_operation (code, mode, op0, op1)
        default:
          abort ();
        }
-      
+
       return 0;
     }
 
@@ -1656,9 +1549,9 @@ simplify_binary_operation (code, mode, op0, op1)
 
    Rather than test for specific case, we do this by a brute-force method
    and do all possible simplifications until no more changes occur.  Then
-   we rebuild the operation. 
+   we rebuild the operation.
 
-   If FORCE is true, then always generate the rtx.  This is used to 
+   If FORCE is true, then always generate the rtx.  This is used to
    canonicalize stuff emitted from simplify_gen_binary.  Note that this
    can still fail if the rtx is too complex.  It won't fail just because
    the result is not 'simpler' than the input, however.  */
@@ -1695,7 +1588,7 @@ simplify_plus_minus (code, mode, op0, op1, force)
   int i, j;
 
   memset ((char *) ops, 0, sizeof ops);
-  
+
   /* Set up the two operands and then expand them until nothing has been
      changed.  If we run out of room in our array, give up; this should
      almost never happen.  */
@@ -1819,7 +1712,7 @@ simplify_plus_minus (code, mode, op0, op1, force)
 
                tem = simplify_binary_operation (ncode, mode, lhs, rhs);
 
-               /* Reject "simplifications" that just wrap the two 
+               /* Reject "simplifications" that just wrap the two
                   arguments in a CONST.  Failure to do so can result
                   in infinite recursion with simplify_binary_operation
                   when it calls us to simplify CONST operations.  */
@@ -1891,7 +1784,7 @@ simplify_plus_minus (code, mode, op0, op1, force)
      is also an improvement, so accept it.  */
   if (!force
       && (n_ops + n_consts > input_ops
-          || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
+         || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
     return NULL_RTX;
 
   /* Put a non-negated operand first.  If there aren't any, make all
@@ -1923,35 +1816,6 @@ simplify_plus_minus (code, mode, op0, op1, force)
   return negate ? gen_rtx_NEG (mode, result) : result;
 }
 
-struct cfc_args
-{
-  rtx op0, op1;                        /* Input */
-  int equal, op0lt, op1lt;     /* Output */
-  int unordered;
-};
-
-static void
-check_fold_consts (data)
-  PTR data;
-{
-  struct cfc_args *args = (struct cfc_args *) data;
-  REAL_VALUE_TYPE d0, d1;
-
-  /* We may possibly raise an exception while reading the value.  */
-  args->unordered = 1;
-  REAL_VALUE_FROM_CONST_DOUBLE (d0, args->op0);
-  REAL_VALUE_FROM_CONST_DOUBLE (d1, args->op1);
-
-  /* Comparisons of Inf versus Inf are ordered.  */
-  if (REAL_VALUE_ISNAN (d0)
-      || REAL_VALUE_ISNAN (d1))
-    return;
-  args->equal = REAL_VALUES_EQUAL (d0, d1);
-  args->op0lt = REAL_VALUES_LESS (d0, d1);
-  args->op1lt = REAL_VALUES_LESS (d1, d0);
-  args->unordered = 0;
-}
-
 /* Like simplify_binary_operation except used for relational operators.
    MODE is the mode of the operands, not that of the result.  If MODE
    is VOIDmode, both operands must also be VOIDmode and we compare the
@@ -2035,17 +1899,13 @@ simplify_relational_operation (code, mode, op0, op1)
           && GET_CODE (trueop1) == CONST_DOUBLE
           && GET_MODE_CLASS (GET_MODE (trueop0)) == MODE_FLOAT)
     {
-      struct cfc_args args;
+      REAL_VALUE_TYPE d0, d1;
 
-      /* Setup input for check_fold_consts() */
-      args.op0 = trueop0;
-      args.op1 = trueop1;
-      
-      
-      if (!do_float_handler (check_fold_consts, (PTR) &args))
-       args.unordered = 1;
+      REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0);
+      REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1);
 
-      if (args.unordered)
+      /* Comparisons are unordered iff at least one of the values is NaN.  */
+      if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1))
        switch (code)
          {
          case UNEQ:
@@ -2068,10 +1928,9 @@ simplify_relational_operation (code, mode, op0, op1)
            return 0;
          }
 
-      /* Receive output from check_fold_consts() */
-      equal = args.equal;
-      op0lt = op0ltu = args.op0lt;
-      op1lt = op1ltu = args.op1lt;
+      equal = REAL_VALUES_EQUAL (d0, d1);
+      op0lt = op0ltu = REAL_VALUES_LESS (d0, d1);
+      op1lt = op1ltu = REAL_VALUES_LESS (d1, d0);
     }
 
   /* Otherwise, see if the operands are both integers.  */
@@ -2096,7 +1955,7 @@ simplify_relational_operation (code, mode, op0, op1)
          l0u = l0s = INTVAL (trueop0);
          h0u = h0s = HWI_SIGN_EXTEND (l0s);
        }
-         
+
       if (GET_CODE (trueop1) == CONST_DOUBLE)
        {
          l1u = l1s = CONST_DOUBLE_LOW (trueop1);
@@ -2185,7 +2044,7 @@ simplify_relational_operation (code, mode, op0, op1)
              && INTEGRAL_MODE_P (mode))
            return const0_rtx;
          break;
-         
+
        default:
          break;
        }
@@ -2329,7 +2188,7 @@ simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
            {
              HOST_WIDE_INT t = INTVAL (op1);
              HOST_WIDE_INT f = INTVAL (op2);
-             
+
              if (t == STORE_FLAG_VALUE && f == 0)
                code = GET_CODE (op0);
              else if (t == 0 && f == STORE_FLAG_VALUE)
@@ -2429,7 +2288,7 @@ simplify_subreg (outermode, op, innermode, byte)
          val = part ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op);
          offset %= HOST_BITS_PER_WIDE_INT;
 
-         /* We've already picked the word we want from a double, so 
+         /* We've already picked the word we want from a double, so
             pretend this is actually an integer.  */
          innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
 
@@ -2694,7 +2553,7 @@ simplify_gen_subreg (outermode, op, innermode, byte)
     maintain and improve.  It's totally silly that when we add a
     simplification that it needs to be added to 4 places (3 for RTL
     simplification and 1 for tree simplification.  */
-          
+
 rtx
 simplify_rtx (x)
      rtx x;
@@ -2738,7 +2597,7 @@ simplify_rtx (x)
     case 'x':
       /* The only case we try to handle is a SUBREG.  */
       if (code == SUBREG)
-        return simplify_gen_subreg (mode, SUBREG_REG (x),
+       return simplify_gen_subreg (mode, SUBREG_REG (x),
                                    GET_MODE (SUBREG_REG (x)),
                                    SUBREG_BYTE (x));
       return NULL;