OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 57a7248..69db6c2 100644 (file)
@@ -1544,13 +1544,18 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
 /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new
    constant.  We assume ARG1 and ARG2 have the same data type, or at least
-   are the same kind of constant and the same machine mode.
+   are the same kind of constant and the same machine mode.  Return zero if
+   combining the constants is not allowed in the current operating mode.
 
    If NOTRUNC is nonzero, do not truncate the result to fit the data type.  */
 
 static tree
 const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 {
+  /* Sanity check for the recursive cases.  */
+  if (!arg1 || !arg2)
+    return NULL_TREE;
+
   STRIP_NOPS (arg1);
   STRIP_NOPS (arg2);
 
@@ -1613,7 +1618,6 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
 
       /* Don't constant fold this floating point operation if
         the result has overflowed and flag_trapping_math.  */
-
       if (flag_trapping_math
          && MODE_HAS_INFINITIES (mode)
          && REAL_VALUE_ISINF (result)
@@ -1625,7 +1629,6 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
         result may dependent upon the run-time rounding mode and
         flag_rounding_math is set, or if GCC's software emulation
         is unable to accurately represent the result.  */
-      
       if ((flag_rounding_math
           || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
               && !flag_unsafe_math_optimizations))
@@ -1649,78 +1652,61 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
       tree i1 = TREE_IMAGPART (arg1);
       tree r2 = TREE_REALPART (arg2);
       tree i2 = TREE_IMAGPART (arg2);
-      tree t;
+      tree real, imag;
 
       switch (code)
        {
        case PLUS_EXPR:
-         t = build_complex (type,
-                            const_binop (PLUS_EXPR, r1, r2, notrunc),
-                            const_binop (PLUS_EXPR, i1, i2, notrunc));
-         break;
-
        case MINUS_EXPR:
-         t = build_complex (type,
-                            const_binop (MINUS_EXPR, r1, r2, notrunc),
-                            const_binop (MINUS_EXPR, i1, i2, notrunc));
+         real = const_binop (code, r1, r2, notrunc);
+         imag = const_binop (code, i1, i2, notrunc);
          break;
 
        case MULT_EXPR:
-         t = build_complex (type,
-                            const_binop (MINUS_EXPR,
-                                         const_binop (MULT_EXPR,
-                                                      r1, r2, notrunc),
-                                         const_binop (MULT_EXPR,
-                                                      i1, i2, notrunc),
-                                         notrunc),
-                            const_binop (PLUS_EXPR,
-                                         const_binop (MULT_EXPR,
-                                                      r1, i2, notrunc),
-                                         const_binop (MULT_EXPR,
-                                                      i1, r2, notrunc),
-                                         notrunc));
+         real = const_binop (MINUS_EXPR,
+                             const_binop (MULT_EXPR, r1, r2, notrunc),
+                             const_binop (MULT_EXPR, i1, i2, notrunc),
+                             notrunc);
+         imag = const_binop (PLUS_EXPR,
+                             const_binop (MULT_EXPR, r1, i2, notrunc),
+                             const_binop (MULT_EXPR, i1, r2, notrunc),
+                             notrunc);
          break;
 
        case RDIV_EXPR:
          {
-           tree t1, t2, real, imag;
            tree magsquared
              = const_binop (PLUS_EXPR,
                             const_binop (MULT_EXPR, r2, r2, notrunc),
                             const_binop (MULT_EXPR, i2, i2, notrunc),
                             notrunc);
-
-           t1 = const_binop (PLUS_EXPR,
-                             const_binop (MULT_EXPR, r1, r2, notrunc),
-                             const_binop (MULT_EXPR, i1, i2, notrunc),
-                             notrunc);
-           t2 = const_binop (MINUS_EXPR,
-                             const_binop (MULT_EXPR, i1, r2, notrunc),
-                             const_binop (MULT_EXPR, r1, i2, notrunc),
-                             notrunc);
+           tree t1
+             = const_binop (PLUS_EXPR,
+                            const_binop (MULT_EXPR, r1, r2, notrunc),
+                            const_binop (MULT_EXPR, i1, i2, notrunc),
+                            notrunc);
+           tree t2
+             = const_binop (MINUS_EXPR,
+                            const_binop (MULT_EXPR, i1, r2, notrunc),
+                            const_binop (MULT_EXPR, r1, i2, notrunc),
+                            notrunc);
 
            if (INTEGRAL_TYPE_P (TREE_TYPE (r1)))
-             {
-               real = const_binop (TRUNC_DIV_EXPR, t1, magsquared, notrunc);
-               imag = const_binop (TRUNC_DIV_EXPR, t2, magsquared, notrunc);
-             }
-           else
-             {
-               real = const_binop (RDIV_EXPR, t1, magsquared, notrunc);
-               imag = const_binop (RDIV_EXPR, t2, magsquared, notrunc);
-               if (!real || !imag)
-                 return NULL_TREE;
-             }
+             code = TRUNC_DIV_EXPR;
 
-           t = build_complex (type, real, imag);
+           real = const_binop (code, t1, magsquared, notrunc);
+           imag = const_binop (code, t2, magsquared, notrunc);
          }
          break;
 
        default:
          return NULL_TREE;
        }
-      return t;
+
+      if (real && imag)
+       return build_complex (type, real, imag);
     }
+
   return NULL_TREE;
 }
 
@@ -2497,6 +2483,11 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
   if (TYPE_UNSIGNED (TREE_TYPE (arg0)) != TYPE_UNSIGNED (TREE_TYPE (arg1)))
     return 0;
 
+  /* If both types don't have the same precision, then it is not safe
+     to strip NOPs.  */
+  if (TYPE_PRECISION (TREE_TYPE (arg0)) != TYPE_PRECISION (TREE_TYPE (arg1)))
+    return 0;
+
   STRIP_NOPS (arg0);
   STRIP_NOPS (arg1);
 
@@ -6736,7 +6727,7 @@ fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1)
   else
     {
       arg00 = arg0;
-      arg01 = fold_convert (type, integer_one_node);
+      arg01 = build_one_cst (type);
     }
   if (TREE_CODE (arg1) == MULT_EXPR)
     {
@@ -6746,7 +6737,7 @@ fold_plusminus_mult_expr (enum tree_code code, tree type, tree arg0, tree arg1)
   else
     {
       arg10 = arg1;
-      arg11 = fold_convert (type, integer_one_node);
+      arg11 = build_one_cst (type);
     }
   same = NULL_TREE;
 
@@ -6929,12 +6920,13 @@ static int
 native_encode_vector (tree expr, unsigned char *ptr, int len)
 {
   int i, size, offset, count;
-  tree elem, elements;
+  tree itype, elem, elements;
 
-  size = 0;
   offset = 0;
   elements = TREE_VECTOR_CST_ELTS (expr);
   count = TYPE_VECTOR_SUBPARTS (TREE_TYPE (expr));
+  itype = TREE_TYPE (TREE_TYPE (expr));
+  size = GET_MODE_SIZE (TYPE_MODE (itype));
   for (i = 0; i < count; i++)
     {
       if (elements)
@@ -6947,18 +6939,15 @@ native_encode_vector (tree expr, unsigned char *ptr, int len)
 
       if (elem)
        {
-         size = native_encode_expr (elem, ptr+offset, len-offset);
-         if (size == 0)
+         if (native_encode_expr (elem, ptr+offset, len-offset) != size)
            return 0;
        }
-      else if (size != 0)
+      else
        {
          if (offset + size > len)
            return 0;
          memset (ptr+offset, 0, size);
        }
-      else
-       return 0;
       offset += size;
     }
   return offset;
@@ -8863,12 +8852,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       /* (-A) * (-B) -> A * B  */
       if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1))
        return fold_build2 (MULT_EXPR, type,
-                           TREE_OPERAND (arg0, 0),
-                           negate_expr (arg1));
+                           fold_convert (type, TREE_OPERAND (arg0, 0)),
+                           fold_convert (type, negate_expr (arg1)));
       if (TREE_CODE (arg1) == NEGATE_EXPR && negate_expr_p (arg0))
        return fold_build2 (MULT_EXPR, type,
-                           negate_expr (arg0),
-                           TREE_OPERAND (arg1, 0));
+                           fold_convert (type, negate_expr (arg0)),
+                           fold_convert (type, TREE_OPERAND (arg1, 0)));
 
       if (! FLOAT_TYPE_P (type))
        {
@@ -10300,7 +10289,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
          && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
                                      ? MINUS_EXPR : PLUS_EXPR,
-                                     arg1, TREE_OPERAND (arg0, 1), 0))
+                                     fold_convert (TREE_TYPE (arg0), arg1),
+                                     TREE_OPERAND (arg0, 1), 0))
          && ! TREE_CONSTANT_OVERFLOW (tem))
        return fold_build2 (code, type, TREE_OPERAND (arg0, 0), tem);