OSDN Git Service

* gcc.c-torture/compile/20001226-1.x: Only xfail for Xtensa
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 0998a93..db41564 100644 (file)
@@ -1376,21 +1376,21 @@ size_int_wide (number, kind)
 
 /* Likewise, but the desired type is specified explicitly.  */
 
+static GTY (()) tree new_const;
+static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+     htab_t size_htab;
+
 tree
 size_int_type_wide (number, type)
      HOST_WIDE_INT number;
      tree type;
 {
-  static htab_t size_htab = 0;
-  static tree new_const = 0;
   PTR *slot;
 
   if (size_htab == 0)
     {
       size_htab = htab_create (1024, size_htab_hash, size_htab_eq, NULL);
-      ggc_add_deletable_htab (size_htab, NULL, NULL);
       new_const = make_node (INTEGER_CST);
-      ggc_add_tree_root (&new_const, 1);
     }
 
   /* Adjust NEW_CONST to be the constant we want.  If it's already in the
@@ -5370,6 +5370,14 @@ fold (expr)
             so we can do this anyway.  */
          if (real_onep (arg1))
            return non_lvalue (convert (type, arg0));
+
+         /* Transform x * -1.0 into -x.  This should be safe for NaNs,
+            signed zeros and signed infinities, but is currently
+            restricted to "unsafe math optimizations" just in case.  */
+         if (flag_unsafe_math_optimizations
+             && real_minus_onep (arg1))
+           return fold (build1 (NEGATE_EXPR, type, arg0));
+
          /* x*2 is x+x */
          if (! wins && real_twop (arg1)
              && (*lang_hooks.decls.global_bindings_p) () == 0
@@ -5806,6 +5814,20 @@ fold (expr)
     case GT_EXPR:
     case LE_EXPR:
     case GE_EXPR:
+      /* If one arg is a real or integer constant, put it last.  */
+      if ((TREE_CODE (arg0) == INTEGER_CST
+          && TREE_CODE (arg1) != INTEGER_CST)
+         || (TREE_CODE (arg0) == REAL_CST
+             && TREE_CODE (arg0) != REAL_CST))
+       {
+         TREE_OPERAND (t, 0) = arg1;
+         TREE_OPERAND (t, 1) = arg0;
+         arg0 = TREE_OPERAND (t, 0);
+         arg1 = TREE_OPERAND (t, 1);
+         code = swap_tree_comparison (code);
+         TREE_SET_CODE (t, code);
+       }
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
          /* (-a) CMP (-b) -> b CMP a  */
@@ -5827,18 +5849,21 @@ fold (expr)
              && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
            return fold (build (code, type, arg0,
                                build_real (TREE_TYPE (arg1), dconst0)));
-       }
 
-      /* If one arg is a constant integer, put it last.  */
-      if (TREE_CODE (arg0) == INTEGER_CST
-         && TREE_CODE (arg1) != INTEGER_CST)
-       {
-         TREE_OPERAND (t, 0) = arg1;
-         TREE_OPERAND (t, 1) = arg0;
-         arg0 = TREE_OPERAND (t, 0);
-         arg1 = TREE_OPERAND (t, 1);
-         code = swap_tree_comparison (code);
-         TREE_SET_CODE (t, code);
+         /* If this is a comparison of a real constant with a PLUS_EXPR
+            or a MINUS_EXPR of a real constant, we can convert it into a
+            comparison with a revised real constant as long as no overflow
+            occurs when unsafe_math_optimizations are enabled.  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg1) == REAL_CST
+             && (TREE_CODE (arg0) == PLUS_EXPR
+                 || TREE_CODE (arg0) == MINUS_EXPR)
+             && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+             && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+                                         ? MINUS_EXPR : PLUS_EXPR,
+                                         arg1, TREE_OPERAND (arg0, 1), 0))
+             && ! TREE_CONSTANT_OVERFLOW (tem))
+           return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
        }
 
       /* Convert foo++ == CONST into ++foo == CONST + INCR.
@@ -7228,3 +7253,5 @@ rtl_expr_nonnegative_p (r)
       return 0;
     }
 }
+
+#include "gt-fold-const.h"