OSDN Git Service

PR 22429
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 383bd67..6f829ad 100644 (file)
@@ -2019,7 +2019,7 @@ fold_convert (tree type, tree arg)
       gcc_assert (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
       gcc_assert (INTEGRAL_TYPE_P (orig) || POINTER_TYPE_P (orig)
                  || TREE_CODE (orig) == VECTOR_TYPE);
-      return fold_build1 (NOP_EXPR, type, arg);
+      return fold_build1 (VIEW_CONVERT_EXPR, type, arg);
 
     case VOID_TYPE:
       return fold_build1 (CONVERT_EXPR, type, fold_ignored_result (arg));
@@ -3025,9 +3025,18 @@ invert_truthvalue (tree arg)
       return TREE_OPERAND (arg, 0);
 
     case COND_EXPR:
-      return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
-                    invert_truthvalue (TREE_OPERAND (arg, 1)),
-                    invert_truthvalue (TREE_OPERAND (arg, 2)));
+      {
+       tree arg1 = TREE_OPERAND (arg, 1);
+       tree arg2 = TREE_OPERAND (arg, 2);
+       /* A COND_EXPR may have a throw as one operand, which
+          then has void type.  Just leave void operands
+          as they are.  */
+       return build3 (COND_EXPR, type, TREE_OPERAND (arg, 0),
+                      VOID_TYPE_P (TREE_TYPE (arg1))
+                      ? arg1 : invert_truthvalue (arg1),
+                      VOID_TYPE_P (TREE_TYPE (arg2))
+                      ? arg2 : invert_truthvalue (arg2));
+      }
 
     case COMPOUND_EXPR:
       return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg, 0),
@@ -3340,11 +3349,11 @@ optimize_bit_field_compare (enum tree_code code, tree compare_type,
       TREE_THIS_VOLATILE (lhs) = 1;
     }
 
-  rhs = fold (const_binop (BIT_AND_EXPR,
-                          const_binop (LSHIFT_EXPR,
-                                       fold_convert (unsigned_type, rhs),
-                                       size_int (lbitpos), 0),
-                          mask, 0));
+  rhs = const_binop (BIT_AND_EXPR,
+                    const_binop (LSHIFT_EXPR,
+                                 fold_convert (unsigned_type, rhs),
+                                 size_int (lbitpos), 0),
+                    mask, 0);
 
   return build2 (code, compare_type,
                 build2 (BIT_AND_EXPR, unsigned_type, lhs, mask),
@@ -3929,6 +3938,15 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
   tree etype = TREE_TYPE (exp);
   tree value;
 
+#ifdef HAVE_canonicalize_funcptr_for_compare
+  /* Disable this optimization for function pointer expressions
+     on targets that require function pointer canonicalization.  */
+  if (HAVE_canonicalize_funcptr_for_compare
+      && TREE_CODE (etype) == POINTER_TYPE
+      && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
+    return NULL_TREE;
+#endif
+
   if (! in_p)
     {
       value = build_range_check (type, exp, 1, low, high);
@@ -3996,7 +4014,8 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
     }
 
   value = const_binop (MINUS_EXPR, high, low, 0);
-  if (value != 0 && TREE_OVERFLOW (value) && ! TYPE_UNSIGNED (etype))
+  if (value != 0 && (!flag_wrapv || TREE_OVERFLOW (value))
+      && ! TYPE_UNSIGNED (etype))
     {
       tree utype, minv, maxv;
 
@@ -4007,6 +4026,11 @@ build_range_check (tree type, tree exp, int in_p, tree low, tree high)
        case INTEGER_TYPE:
        case ENUMERAL_TYPE:
        case CHAR_TYPE:
+         /* There is no requirement that LOW be within the range of ETYPE
+            if the latter is a subtype.  It must, however, be within the base
+            type of ETYPE.  So be sure we do the subtraction in that type.  */
+         if (TREE_TYPE (etype))
+           etype = TREE_TYPE (etype);
          utype = lang_hooks.types.unsigned_type (etype);
          maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
          maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
@@ -6241,8 +6265,6 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
     return NULL_TREE;
 
   arg1_unw = get_unwidened (arg1, shorter_type);
-  if (!arg1_unw)
-    return NULL_TREE;
 
   /* If possible, express the comparison in the shorter mode.  */
   if ((code == EQ_EXPR || code == NE_EXPR
@@ -6255,7 +6277,9 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
     return fold_build2 (code, type, arg0_unw,
                       fold_convert (shorter_type, arg1_unw));
 
-  if (TREE_CODE (arg1_unw) != INTEGER_CST)
+  if (TREE_CODE (arg1_unw) != INTEGER_CST
+      || TREE_CODE (shorter_type) != INTEGER_TYPE
+      || !int_fits_type_p (arg1_unw, shorter_type))
     return NULL_TREE;
 
   /* If we are comparing with the integer that does not fit into the range
@@ -6459,7 +6483,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
                                                     TREE_OPERAND (pos, 1)),
                                       fold_convert (itype, delta));
 
-  return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
+  return fold_build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
 }
 
 
@@ -7104,26 +7128,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       return fold_convert (type, tem);
     }
 
-  if (TREE_CODE_CLASS (code) == tcc_comparison
-          && TREE_CODE (arg0) == COMPOUND_EXPR)
-    return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                  fold_build2 (code, type, TREE_OPERAND (arg0, 1), arg1));
-  else if (TREE_CODE_CLASS (code) == tcc_comparison
-          && TREE_CODE (arg1) == COMPOUND_EXPR)
-    return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
-                  fold_build2 (code, type, arg0, TREE_OPERAND (arg1, 1)));
-  else if (TREE_CODE_CLASS (code) == tcc_binary
-          || TREE_CODE_CLASS (code) == tcc_comparison)
+  if (TREE_CODE_CLASS (code) == tcc_binary
+      || TREE_CODE_CLASS (code) == tcc_comparison)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
-                      fold_build2 (code, type, TREE_OPERAND (arg0, 1),
-                                   arg1));
+                      fold_build2 (code, type,
+                                   TREE_OPERAND (arg0, 1), op1));
       if (TREE_CODE (arg1) == COMPOUND_EXPR
          && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
                       fold_build2 (code, type,
-                                   arg0, TREE_OPERAND (arg1, 1)));
+                                   op0, TREE_OPERAND (arg1, 1)));
 
       if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
@@ -7296,13 +7312,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            {
              tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
              if (tem)
-               return fold_convert (type, fold (tem));
+               return fold_convert (type, tem);
            }
          else if (TREE_CODE (arg1) == ADDR_EXPR)
            {
              tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
              if (tem)
-               return fold_convert (type, fold (tem));
+               return fold_convert (type, tem);
            }
        }
       else
@@ -7721,7 +7737,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        {
          tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
          if (tem)
-           return fold_convert (type, fold (tem));
+           return fold_convert (type, tem);
        }
 
       if (flag_unsafe_math_optimizations
@@ -9276,7 +9292,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                  return omit_one_operand (type, integer_one_node, arg0);
 
                case GT_EXPR:
-                 return fold_build2 (NE_EXPR, type, arg0, arg1);
+                 return fold_build2 (NE_EXPR, type, op0, op1);
 
                default:
                  break;
@@ -9310,10 +9326,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                    tree st0, st1;
                    st0 = lang_hooks.types.signed_type (TREE_TYPE (arg0));
                    st1 = lang_hooks.types.signed_type (TREE_TYPE (arg1));
-                   return fold
-                     (build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
-                              type, fold_convert (st0, arg0),
-                              fold_convert (st1, integer_zero_node)));
+                   return fold_build2 (code == LE_EXPR ? GE_EXPR: LT_EXPR,
+                                       type, fold_convert (st0, arg0),
+                                       build_int_cst (st1, 0));
                  }
              }
          }
@@ -9998,7 +10013,8 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
 
       /* If the second operand is simpler than the third, swap them
         since that produces better jump optimization results.  */
-      if (tree_swap_operands_p (op1, op2, false))
+      if (truth_value_p (TREE_CODE (arg0))
+         && tree_swap_operands_p (op1, op2, false))
        {
          /* See if this can be inverted.  If it can't, possibly because
             it was a floating-point inequality comparison, don't do
@@ -10107,13 +10123,7 @@ fold_ternary (enum tree_code code, tree type, tree op0, tree op1, tree op2)
       if (TREE_CODE (op0) == ADDR_EXPR
          && TREE_CODE (TREE_OPERAND (op0, 0)) == FUNCTION_DECL
          && DECL_BUILT_IN (TREE_OPERAND (op0, 0)))
-       {
-         tree fndecl = TREE_OPERAND (op0, 0);
-         tree arglist = op1;
-         tree tmp = fold_builtin (fndecl, arglist, false);
-         if (tmp)
-           return tmp;
-       }
+       return fold_builtin (TREE_OPERAND (op0, 0), op1, false);
       return NULL_TREE;
 
     case BIT_FIELD_REF:
@@ -10275,14 +10285,14 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
 {
   void **slot;
   enum tree_code code;
-  char buf[sizeof (struct tree_decl_non_common)];
+  char buf[sizeof (struct tree_function_decl)];
   int i, len;
   
 recursive_label:
 
   gcc_assert ((sizeof (struct tree_exp) + 5 * sizeof (tree)
-              <= sizeof (struct tree_decl_non_common))
-             && sizeof (struct tree_type) <= sizeof (struct tree_decl_non_common));
+              <= sizeof (struct tree_function_decl))
+             && sizeof (struct tree_type) <= sizeof (struct tree_function_decl));
   if (expr == NULL)
     return;
   slot = htab_find_slot (ht, expr, INSERT);
@@ -10373,13 +10383,18 @@ recursive_label:
       fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht);
       fold_checksum_tree (DECL_NAME (expr), ctx, ht);
       fold_checksum_tree (DECL_CONTEXT (expr), ctx, ht);
-      fold_checksum_tree (DECL_ARGUMENTS (expr), ctx, ht);
-      fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht);
       fold_checksum_tree (DECL_INITIAL (expr), ctx, ht);
       fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht);
-      fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
       fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
-      fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_WITH_VIS))
+       fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
+         
+      if (CODE_CONTAINS_STRUCT (TREE_CODE (expr), TS_DECL_NON_COMMON))
+       {
+         fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
+         fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht);
+         fold_checksum_tree (DECL_ARGUMENT_FLD (expr), ctx, ht);
+       }
       break;
     case tcc_type:
       if (TREE_CODE (expr) == ENUMERAL_TYPE)
@@ -10569,33 +10584,65 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
 }
 
 /* Perform constant folding and related simplification of initializer
-   expression EXPR.  This behaves identically to "fold" but ignores
+   expression EXPR.  These behave identically to "fold_buildN" but ignore
    potential run-time traps and exceptions that fold must preserve.  */
 
+#define START_FOLD_INIT \
+  int saved_signaling_nans = flag_signaling_nans;\
+  int saved_trapping_math = flag_trapping_math;\
+  int saved_rounding_math = flag_rounding_math;\
+  int saved_trapv = flag_trapv;\
+  flag_signaling_nans = 0;\
+  flag_trapping_math = 0;\
+  flag_rounding_math = 0;\
+  flag_trapv = 0
+
+#define END_FOLD_INIT \
+  flag_signaling_nans = saved_signaling_nans;\
+  flag_trapping_math = saved_trapping_math;\
+  flag_rounding_math = saved_rounding_math;\
+  flag_trapv = saved_trapv
+
 tree
-fold_initializer (tree expr)
+fold_build1_initializer (enum tree_code code, tree type, tree op)
 {
-  int saved_signaling_nans = flag_signaling_nans;
-  int saved_trapping_math = flag_trapping_math;
-  int saved_rounding_math = flag_rounding_math;
-  int saved_trapv = flag_trapv;
   tree result;
+  START_FOLD_INIT;
 
-  flag_signaling_nans = 0;
-  flag_trapping_math = 0;
-  flag_rounding_math = 0;
-  flag_trapv = 0;
+  result = fold_build1 (code, type, op);
 
-  result = fold (expr);
+  END_FOLD_INIT;
+  return result;
+}
+
+tree
+fold_build2_initializer (enum tree_code code, tree type, tree op0, tree op1)
+{
+  tree result;
+  START_FOLD_INIT;
+
+  result = fold_build2 (code, type, op0, op1);
+
+  END_FOLD_INIT;
+  return result;
+}
 
-  flag_signaling_nans = saved_signaling_nans;
-  flag_trapping_math = saved_trapping_math;
-  flag_rounding_math = saved_rounding_math;
-  flag_trapv = saved_trapv;
+tree
+fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
+                        tree op2)
+{
+  tree result;
+  START_FOLD_INIT;
 
+  result = fold_build3 (code, type, op0, op1, op2);
+
+  END_FOLD_INIT;
   return result;
 }
 
+#undef START_FOLD_INIT
+#undef END_FOLD_INIT
+
 /* Determine if first argument is a multiple of second argument.  Return 0 if
    it is not, or we cannot easily determined it to be.
 
@@ -10780,6 +10827,15 @@ tree_expr_nonnegative_p (tree t)
        }
       return 0;
 
+    case BIT_AND_EXPR:
+    case MAX_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
+            || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case MIN_EXPR:
+    case RDIV_EXPR:
     case TRUNC_DIV_EXPR:
     case CEIL_DIV_EXPR:
     case FLOOR_DIV_EXPR:
@@ -10791,19 +10847,21 @@ tree_expr_nonnegative_p (tree t)
     case CEIL_MOD_EXPR:
     case FLOOR_MOD_EXPR:
     case ROUND_MOD_EXPR:
+    case SAVE_EXPR:
+    case NON_LVALUE_EXPR:
+    case FLOAT_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
 
-    case RDIV_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
+      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
 
-    case BIT_AND_EXPR:
+    case BIND_EXPR:
+      return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1)));
+
+    case COND_EXPR:
       return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
-            || tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case BIT_IOR_EXPR:
-    case BIT_XOR_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-            && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
+            && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
 
     case NOP_EXPR:
       {
@@ -10832,28 +10890,6 @@ tree_expr_nonnegative_p (tree t)
       }
       break;
 
-    case COND_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1))
-       && tree_expr_nonnegative_p (TREE_OPERAND (t, 2));
-    case COMPOUND_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case MIN_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-       && tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case MAX_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0))
-       || tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case MODIFY_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
-    case BIND_EXPR:
-      return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1)));
-    case SAVE_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case NON_LVALUE_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-    case FLOAT_EXPR:
-      return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
-
     case TARGET_EXPR:
       {
        tree temp = TARGET_EXPR_SLOT (t);
@@ -11736,10 +11772,10 @@ ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
        toffset2 = fold_convert (type, toffset2);
 
       tdiff = fold_build2 (MINUS_EXPR, type, toffset1, toffset2);
-      if (!host_integerp (tdiff, 0))
+      if (!cst_and_fits_in_hwi (tdiff))
        return false;
 
-      *diff = tree_low_cst (tdiff, 0);
+      *diff = int_cst_value (tdiff);
     }
   else if (toffset1 || toffset2)
     {