OSDN Git Service

* config/m32r/m32r.c (m32r_encode_section_info): Use gcc_assert
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index e928025..140f940 100644 (file)
@@ -6149,7 +6149,8 @@ fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
        || TYPE_UNSIGNED (TREE_TYPE (arg0)) == TYPE_UNSIGNED (shorter_type))
       && (TREE_TYPE (arg1_unw) == shorter_type
          || (TREE_CODE (arg1_unw) == INTEGER_CST
-             && TREE_CODE (shorter_type) == INTEGER_TYPE
+             && (TREE_CODE (shorter_type) == INTEGER_TYPE
+                 || TREE_CODE (shorter_type) == BOOLEAN_TYPE)
              && int_fits_type_p (arg1_unw, shorter_type))))
     return fold_build2 (code, type, arg0_unw,
                       fold_convert (shorter_type, arg1_unw));
@@ -7841,7 +7842,28 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            && ptr_difference_const (arg0, arg1, &diff))
          return build_int_cst_type (type, diff);
       }
-         
+
+      /* Fold &a[i] - &a[j] to i-j.  */
+      if (TREE_CODE (arg0) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == ARRAY_REF
+         && TREE_CODE (arg1) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg1, 0)) == ARRAY_REF)
+        {
+         tree aref0 = TREE_OPERAND (arg0, 0);
+         tree aref1 = TREE_OPERAND (arg1, 0);
+         if (operand_equal_p (TREE_OPERAND (aref0, 0),
+                              TREE_OPERAND (aref1, 0), 0))
+           {
+             tree op0 = fold_convert (type, TREE_OPERAND (aref0, 1));
+             tree op1 = fold_convert (type, TREE_OPERAND (aref1, 1));
+             tree esz = array_ref_element_size (aref0);
+             tree diff = build2 (MINUS_EXPR, type, op0, op1);
+             return fold_build2 (MULT_EXPR, type, diff,
+                                 fold_convert (type, esz));
+                                 
+           }
+       }
+
       /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
         of the array.  Loop optimizer sometimes produce this type of
         expressions.  */
@@ -8835,10 +8857,20 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
     case LT_EXPR:
     case GT_EXPR:
     case LE_EXPR:
-    case GE_EXPR:
+    case GE_EXPR:      
       /* If one arg is a real or integer constant, put it last.  */
       if (tree_swap_operands_p (arg0, arg1, true))
        return fold_build2 (swap_tree_comparison (code), type, op1, op0);
+       
+      /* bool_var != 0 becomes bool_var. */
+      if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_zerop (arg1)
+          && code == NE_EXPR)
+        return non_lvalue (fold_convert (type, arg0));
+       
+      /* bool_var == 1 becomes bool_var. */
+      if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE && integer_onep (arg1)
+          && code == EQ_EXPR)
+        return non_lvalue (fold_convert (type, arg0));
 
       /* If this is an equality comparison of the address of a non-weak
         object against zero, then we know the result.  */
@@ -9687,6 +9719,27 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
            return t1;
        }
 
+      /* Fold a comparison of the address of COMPONENT_REFs with the same
+         type and component to a comparison of the address of the base
+        object.  In short, &x->a OP &y->a to x OP y and
+         &x->a OP &y.a to x OP &y  */
+      if (TREE_CODE (arg0) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg0, 0)) == COMPONENT_REF
+         && TREE_CODE (arg1) == ADDR_EXPR
+         && TREE_CODE (TREE_OPERAND (arg1, 0)) == COMPONENT_REF)
+        {
+         tree cref0 = TREE_OPERAND (arg0, 0);
+         tree cref1 = TREE_OPERAND (arg1, 0);
+         if (TREE_OPERAND (cref0, 1) == TREE_OPERAND (cref1, 1))
+           {
+             tree op0 = TREE_OPERAND (cref0, 0);
+             tree op1 = TREE_OPERAND (cref1, 0);
+             return fold_build2 (code, type,
+                                 build_fold_addr_expr (op0),
+                                 build_fold_addr_expr (op1));
+           }
+       }
+
       /* If this is a comparison of complex values and either or both sides
         are a COMPLEX_EXPR or COMPLEX_CST, it is best to split up the
         comparisons and join them with a TRUTH_ANDIF_EXPR or TRUTH_ORIF_EXPR.
@@ -9843,6 +9896,10 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
        return build_complex (type, arg0, arg1);
       return NULL_TREE;
 
+    case ASSERT_EXPR:
+      /* An ASSERT_EXPR should never be passed to fold_binary.  */
+      gcc_unreachable ();
+
     default:
       return NULL_TREE;
     } /* switch (code) */
@@ -10126,21 +10183,6 @@ fold (tree expr)
     case CONST_DECL:
       return fold (DECL_INITIAL (t));
 
-    case ASSERT_EXPR:
-      {
-       /* Given ASSERT_EXPR <Y, COND>, return Y if COND can be folded
-          to boolean_true_node.  If COND folds to boolean_false_node,
-          return ASSERT_EXPR <Y, 0>.  Otherwise, return the original
-          expression.  */
-       tree c = fold (ASSERT_EXPR_COND (t));
-       if (c == boolean_true_node)
-         return ASSERT_EXPR_VAR (t);
-       else if (c == boolean_false_node)
-         return build (ASSERT_EXPR, TREE_TYPE (t), ASSERT_EXPR_VAR (t), c);
-       else
-         return t;
-      }
-
     default:
       return t;
     } /* switch (code) */