tree.def (PAREN_EXPR): New tree code.
[gcc.git] / gcc / fold-const.c
index 22350b98bf4189d747c6e42f7c40fe3231fd2656..1ecd2255e4aa78ed97cdfe5ad71b43b1d5bf4309 100644 (file)
@@ -134,7 +134,6 @@ static tree extract_muldiv_1 (tree, tree, enum tree_code, tree, bool *);
 static tree fold_binary_op_with_conditional_arg (enum tree_code, tree,
                                                 tree, tree,
                                                 tree, tree, int);
-static bool fold_real_zero_addition_p (const_tree, const_tree, int);
 static tree fold_mathfn_compare (enum built_in_function, enum tree_code,
                                 tree, tree, tree);
 static tree fold_inf_compare (enum tree_code, tree, tree, tree);
@@ -1492,7 +1491,7 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
       || TREE_CODE (in) == FIXED_CST)
     *litp = in;
   else if (TREE_CODE (in) == code
-          || (! FLOAT_TYPE_P (TREE_TYPE (in))
+          || ((! FLOAT_TYPE_P (TREE_TYPE (in)) || flag_associative_math)
               && ! SAT_FIXED_POINT_TYPE_P (TREE_TYPE (in))
               /* We can associate addition and subtraction together (even
                  though the C standard doesn't say so) for integers because
@@ -2122,8 +2121,22 @@ fold_convert_const_int_from_int (tree type, const_tree arg1)
   t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
                             TREE_INT_CST_HIGH (arg1),
                             /* Don't set the overflow when
-                               converting a pointer  */
-                            !POINTER_TYPE_P (TREE_TYPE (arg1)),
+                               converting from a pointer,  */
+                            !POINTER_TYPE_P (TREE_TYPE (arg1))
+                            /* or to a sizetype with same signedness
+                               and the precision is unchanged.
+                               ???  sizetype is always sign-extended,
+                               but its signedness depends on the
+                               frontend.  Thus we see spurious overflows
+                               here if we do not check this.  */
+                            && !((TYPE_PRECISION (TREE_TYPE (arg1))
+                                  == TYPE_PRECISION (type))
+                                 && (TYPE_UNSIGNED (TREE_TYPE (arg1))
+                                     == TYPE_UNSIGNED (type))
+                                 && ((TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
+                                      && TYPE_IS_SIZETYPE (TREE_TYPE (arg1)))
+                                     || (TREE_CODE (type) == INTEGER_TYPE
+                                         && TYPE_IS_SIZETYPE (type)))),
                             (TREE_INT_CST_HIGH (arg1) < 0
                              && (TYPE_UNSIGNED (type)
                                  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
@@ -6412,7 +6425,7 @@ fold_binary_op_with_conditional_arg (enum tree_code code,
    X - 0 is not the same as X because 0 - 0 is -0.  In other rounding
    modes, X + 0 is not the same as X because -0 + 0 is 0.  */
 
-static bool
+bool
 fold_real_zero_addition_p (const_tree type, const_tree addend, int negate)
 {
   if (!real_zerop (addend))
@@ -7031,12 +7044,14 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
   if (TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (shorter_type))
     return NULL_TREE;
 
-  arg1_unw = get_unwidened (arg1, shorter_type);
+  arg1_unw = get_unwidened (arg1, NULL_TREE);
 
   /* If possible, express the comparison in the shorter mode.  */
   if ((code == EQ_EXPR || code == NE_EXPR
        || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
       && (TREE_TYPE (arg1_unw) == shorter_type
+         || (TYPE_PRECISION (shorter_type)
+             >= TYPE_PRECISION (TREE_TYPE (arg1_unw)))
          || (TREE_CODE (arg1_unw) == INTEGER_CST
              && (TREE_CODE (shorter_type) == INTEGER_TYPE
                  || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
@@ -8012,6 +8027,14 @@ fold_unary (enum tree_code code, tree type, tree op0)
 
   switch (code)
     {
+    case PAREN_EXPR:
+      /* Re-association barriers around constants and other re-association
+        barriers can be removed.  */
+      if (CONSTANT_CLASS_P (op0)
+         || TREE_CODE (op0) == PAREN_EXPR)
+       return fold_convert (type, op0);
+      return NULL_TREE;
+
     case NOP_EXPR:
     case FLOAT_EXPR:
     case CONVERT_EXPR: