OSDN Git Service

Revert accidental commit.
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 4599a69..7306863 100644 (file)
@@ -2097,7 +2097,16 @@ pedantic_non_lvalue_loc (location_t loc, tree x)
 {
   if (pedantic_lvalues)
     return non_lvalue_loc (loc, x);
-  protected_set_expr_location (x, loc);
+
+  if (CAN_HAVE_LOCATION_P (x)
+      && EXPR_LOCATION (x) != loc
+      && !(TREE_CODE (x) == SAVE_EXPR
+          || TREE_CODE (x) == TARGET_EXPR
+          || TREE_CODE (x) == BIND_EXPR))
+    {
+      x = copy_node (x);
+      SET_EXPR_LOCATION (x, loc);
+    }
   return x;
 }
 \f
@@ -2635,6 +2644,14 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
        case TRUTH_ORIF_EXPR:
          return OP_SAME (0) && OP_SAME (1);
 
+       case FMA_EXPR:
+       case WIDEN_MULT_PLUS_EXPR:
+       case WIDEN_MULT_MINUS_EXPR:
+         if (!OP_SAME (2))
+           return 0;
+         /* The multiplcation operands are commutative.  */
+         /* FALLTHRU */
+
        case TRUTH_AND_EXPR:
        case TRUTH_OR_EXPR:
        case TRUTH_XOR_EXPR:
@@ -2648,6 +2665,8 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
                                      TREE_OPERAND (arg1, 0), flags));
 
        case COND_EXPR:
+       case VEC_COND_EXPR:
+       case DOT_PROD_EXPR:
          return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
 
        default:
@@ -8228,7 +8247,7 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
 
     case IMAGPART_EXPR:
       if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert_loc (loc, type, integer_zero_node);
+       return build_zero_cst (type);
       if (TREE_CODE (arg0) == COMPLEX_EXPR)
        return omit_one_operand_loc (loc, type, TREE_OPERAND (arg0, 1),
                                 TREE_OPERAND (arg0, 0));
@@ -9283,7 +9302,7 @@ fold_mult_zconjz (location_t loc, tree type, tree expr)
                     fold_build2_loc (loc, MULT_EXPR, itype, rpart, rpart),
                     fold_build2_loc (loc, MULT_EXPR, itype, ipart, ipart));
   return fold_build2_loc (loc, COMPLEX_EXPR, type, tem,
-                     fold_convert_loc (loc, itype, integer_zero_node));
+                         build_zero_cst (itype));
 }
 
 
@@ -10275,7 +10294,7 @@ fold_binary_loc (location_t loc,
 
       if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type)))
          && operand_equal_p (arg0, arg1, 0))
-       return fold_convert_loc (loc, type, integer_zero_node);
+       return build_zero_cst (type);
 
       /* A - B -> A + (-B) if B is easily negatable.  */
       if (negate_expr_p (arg1)
@@ -10662,7 +10681,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg1);
        }
@@ -10671,7 +10690,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg0);
        }
@@ -10801,7 +10820,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg0) == BIT_NOT_EXPR
          && operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg1);
        }
@@ -10810,7 +10829,7 @@ fold_binary_loc (location_t loc,
       if (TREE_CODE (arg1) == BIT_NOT_EXPR
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        {
-         t1 = fold_convert_loc (loc, type, integer_zero_node);
+         t1 = build_zero_cst (type);
          t1 = fold_unary_loc (loc, BIT_NOT_EXPR, type, t1);
          return omit_one_operand_loc (loc, type, t1, arg0);
        }
@@ -13281,10 +13300,10 @@ contains_label_p (tree st)
 
 tree
 fold_ternary_loc (location_t loc, enum tree_code code, tree type,
-             tree op0, tree op1, tree op2)
+                 tree op0, tree op1, tree op2)
 {
   tree tem;
-  tree arg0 = NULL_TREE, arg1 = NULL_TREE;
+  tree arg0 = NULL_TREE, arg1 = NULL_TREE, arg2 = NULL_TREE;
   enum tree_code_class kind = TREE_CODE_CLASS (code);
 
   gcc_assert (IS_EXPR_CODE_CLASS (kind)
@@ -13312,6 +13331,12 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       STRIP_NOPS (arg1);
     }
 
+  if (op2)
+    {
+      arg2 = op2;
+      STRIP_NOPS (arg2);
+    }
+
   switch (code)
     {
     case COMPONENT_REF:
@@ -13598,7 +13623,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
              if (elements)
                return TREE_VALUE (elements);
              else
-               return fold_convert_loc (loc, type, integer_zero_node);
+               return build_zero_cst (type);
            }
        }
 
@@ -13610,6 +13635,17 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
 
       return NULL_TREE;
 
+    case FMA_EXPR:
+      /* For integers we can decompose the FMA if possible.  */
+      if (TREE_CODE (arg0) == INTEGER_CST
+         && TREE_CODE (arg1) == INTEGER_CST)
+       return fold_build2_loc (loc, PLUS_EXPR, type,
+                               const_binop (MULT_EXPR, arg0, arg1), arg2);
+      if (integer_zerop (arg2))
+       return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
+
+      return fold_fma (loc, type, arg0, arg1, arg2);
+
     default:
       return NULL_TREE;
     } /* switch (code) */
@@ -15643,53 +15679,59 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
        }
     }
 
-  /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
   if (TREE_CODE (sub) == POINTER_PLUS_EXPR
       && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
     {
       tree op00 = TREE_OPERAND (sub, 0);
       tree op01 = TREE_OPERAND (sub, 1);
-      tree op00type;
 
       STRIP_NOPS (op00);
-      op00type = TREE_TYPE (op00);
-      if (TREE_CODE (op00) == ADDR_EXPR
-          && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE
-          && type == TREE_TYPE (TREE_TYPE (op00type)))
+      if (TREE_CODE (op00) == ADDR_EXPR)
        {
-         HOST_WIDE_INT offset = tree_low_cst (op01, 0);
-         tree part_width = TYPE_SIZE (type);
-         unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
-         unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
-         tree index = bitsize_int (indexi);
-
-         if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type)))
-           return fold_build3_loc (loc,
-                               BIT_FIELD_REF, type, TREE_OPERAND (op00, 0),
-                               part_width, index);
+         tree op00type;
+         op00 = TREE_OPERAND (op00, 0);
+         op00type = TREE_TYPE (op00);
 
-       }
-    }
+         /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
+         if (TREE_CODE (op00type) == VECTOR_TYPE
+             && type == TREE_TYPE (op00type))
+           {
+             HOST_WIDE_INT offset = tree_low_cst (op01, 0);
+             tree part_width = TYPE_SIZE (type);
+             unsigned HOST_WIDE_INT part_widthi = tree_low_cst (part_width, 0)/BITS_PER_UNIT;
+             unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
+             tree index = bitsize_int (indexi);
 
+             if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type))
+               return fold_build3_loc (loc,
+                                       BIT_FIELD_REF, type, op00,
+                                       part_width, index);
 
-  /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
-  if (TREE_CODE (sub) == POINTER_PLUS_EXPR
-      && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
-    {
-      tree op00 = TREE_OPERAND (sub, 0);
-      tree op01 = TREE_OPERAND (sub, 1);
-      tree op00type;
-
-      STRIP_NOPS (op00);
-      op00type = TREE_TYPE (op00);
-      if (TREE_CODE (op00) == ADDR_EXPR
-         && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE
-         && type == TREE_TYPE (TREE_TYPE (op00type)))
-       {
-         tree size = TYPE_SIZE_UNIT (type);
-         if (tree_int_cst_equal (size, op01))
-           return fold_build1_loc (loc, IMAGPART_EXPR, type,
-                               TREE_OPERAND (op00, 0));
+           }
+         /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
+         else if (TREE_CODE (op00type) == COMPLEX_TYPE
+                  && type == TREE_TYPE (op00type))
+           {
+             tree size = TYPE_SIZE_UNIT (type);
+             if (tree_int_cst_equal (size, op01))
+               return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
+           }
+         /* ((foo *)&fooarray)[1] => fooarray[1] */
+         else if (TREE_CODE (op00type) == ARRAY_TYPE
+                  && type == TREE_TYPE (op00type))
+           {
+             tree type_domain = TYPE_DOMAIN (op00type);
+             tree min_val = size_zero_node;
+             if (type_domain && TYPE_MIN_VALUE (type_domain))
+               min_val = TYPE_MIN_VALUE (type_domain);
+             op01 = size_binop_loc (loc, EXACT_DIV_EXPR, op01,
+                                    TYPE_SIZE_UNIT (type));
+             op01 = size_binop_loc (loc, PLUS_EXPR, op01, min_val);
+             op0 = build4 (ARRAY_REF, type, op00, op01,
+                           NULL_TREE, NULL_TREE);
+             SET_EXPR_LOCATION (op0, loc);
+             return op0;
+           }
        }
     }