OSDN Git Service

PR fortran/38718
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 1a1a80f..ab3942f 100644 (file)
@@ -119,10 +119,10 @@ static int simple_operand_p (const_tree);
 static tree range_binop (enum tree_code, tree, tree, int, tree, int);
 static tree range_predecessor (tree);
 static tree range_successor (tree);
-static tree make_range (tree, int *, tree *, tree *, bool *);
-static tree build_range_check (tree, tree, int, tree, tree);
-static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
-                        tree);
+extern tree make_range (tree, int *, tree *, tree *, bool *);
+extern tree build_range_check (tree, tree, int, tree, tree);
+extern bool merge_ranges (int *, tree *, tree *, int, tree, tree, int,
+                         tree, tree);
 static tree fold_range_test (enum tree_code, tree, tree, tree);
 static tree fold_cond_expr_with_comparison (tree, tree, tree, tree);
 static tree unextend (tree, int, int, tree);
@@ -2643,9 +2643,10 @@ fold_convert (tree type, tree arg)
        case POINTER_TYPE: case REFERENCE_TYPE:
        case REAL_TYPE:
        case FIXED_POINT_TYPE:
-         return build2 (COMPLEX_EXPR, type,
-                        fold_convert (TREE_TYPE (type), arg),
-                        fold_convert (TREE_TYPE (type), integer_zero_node));
+         return fold_build2 (COMPLEX_EXPR, type,
+                             fold_convert (TREE_TYPE (type), arg),
+                             fold_convert (TREE_TYPE (type),
+                                           integer_zero_node));
        case COMPLEX_TYPE:
          {
            tree rpart, ipart;
@@ -4414,7 +4415,7 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
    because signed overflow is undefined; otherwise, do not change
    *STRICT_OVERFLOW_P.  */
 
-static tree
+tree
 make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
            bool *strict_overflow_p)
 {
@@ -4706,7 +4707,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh,
    type, TYPE, return an expression to test if EXP is in (or out of, depending
    on IN_P) the range.  Return 0 if the test couldn't be created.  */
 
-static tree
+tree
 build_range_check (tree type, tree exp, int in_p, tree low, tree high)
 {
   tree etype = TREE_TYPE (exp), value;
@@ -4877,7 +4878,7 @@ range_successor (tree val)
 /* Given two ranges, see if we can merge them into one.  Return 1 if we
    can, 0 if we can't.  Set the output range into the specified parameters.  */
 
-static int
+bool
 merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
              tree high0, int in1_p, tree low1, tree high1)
 {
@@ -7999,6 +8000,13 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
       if (TREE_TYPE (t) != ptrtype)
        t = build1 (NOP_EXPR, ptrtype, t);
     }
+  else if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
+    {
+      t = build_fold_addr_expr (TREE_OPERAND (t, 0));
+
+      if (TREE_TYPE (t) != ptrtype)
+       t = fold_convert (ptrtype, t);
+    }
   else
     t = build1 (ADDR_EXPR, ptrtype, t);
 
@@ -10168,8 +10176,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                && TREE_INT_CST_HIGH (tree11) == 0
                && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
                    == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
-             return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
-                            code0 == LSHIFT_EXPR ? tree01 : tree11);
+             return fold_convert (type,
+                                  build2 (LROTATE_EXPR,
+                                          TREE_TYPE (TREE_OPERAND (arg0, 0)),
+                                          TREE_OPERAND (arg0, 0),
+                                          code0 == LSHIFT_EXPR
+                                          ? tree01 : tree11));
            else if (code11 == MINUS_EXPR)
              {
                tree tree110, tree111;
@@ -10183,10 +10195,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                              (TREE_TYPE (TREE_OPERAND
                                                          (arg0, 0))))
                    && operand_equal_p (tree01, tree111, 0))
-                 return build2 ((code0 == LSHIFT_EXPR
-                                 ? LROTATE_EXPR
-                                 : RROTATE_EXPR),
-                                type, TREE_OPERAND (arg0, 0), tree01);
+                 return fold_convert (type,
+                                      build2 ((code0 == LSHIFT_EXPR
+                                               ? LROTATE_EXPR
+                                               : RROTATE_EXPR),
+                                              TREE_TYPE (TREE_OPERAND (arg0, 0)),
+                                              TREE_OPERAND (arg0, 0), tree01));
              }
            else if (code01 == MINUS_EXPR)
              {
@@ -10201,10 +10215,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                                              (TREE_TYPE (TREE_OPERAND
                                                          (arg0, 0))))
                    && operand_equal_p (tree11, tree011, 0))
-                 return build2 ((code0 != LSHIFT_EXPR
-                                 ? LROTATE_EXPR
-                                 : RROTATE_EXPR),
-                                type, TREE_OPERAND (arg0, 0), tree11);
+                 return fold_convert (type,
+                                      build2 ((code0 != LSHIFT_EXPR
+                                               ? LROTATE_EXPR
+                                               : RROTATE_EXPR),
+                                              TREE_TYPE (TREE_OPERAND (arg0, 0)),
+                                              TREE_OPERAND (arg0, 0), tree11));
              }
          }
       }
@@ -11375,6 +11391,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
              if (prec < HOST_BITS_PER_WIDE_INT
                  || newmask == ~(unsigned HOST_WIDE_INT) 0)
                {
+                 tree newmaskt;
+
                  if (shift_type != TREE_TYPE (arg0))
                    {
                      tem = fold_build2 (TREE_CODE (arg0), shift_type,
@@ -11385,9 +11403,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                    }
                  else
                    tem = op0;
-                 return fold_build2 (BIT_AND_EXPR, type, tem,
-                                     build_int_cst_type (TREE_TYPE (op1),
-                                                         newmask));
+                 newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
+                 if (!tree_int_cst_equal (newmaskt, arg1))
+                   return fold_build2 (BIT_AND_EXPR, type, tem, newmaskt);
                }
            }
        }