OSDN Git Service

PR c++/17868
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 0dd0248..7de102f 100644 (file)
@@ -209,7 +209,7 @@ force_fit_type (tree t, int overflowable,
   int sign_extended_type;
 
   gcc_assert (TREE_CODE (t) == INTEGER_CST);
-  
+
   low = TREE_INT_CST_LOW (t);
   high = TREE_INT_CST_HIGH (t);
 
@@ -267,7 +267,7 @@ force_fit_type (tree t, int overflowable,
       || low != TREE_INT_CST_LOW (t) || high != TREE_INT_CST_HIGH (t))
     {
       t = build_int_cst_wide (TREE_TYPE (t), low, high);
-      
+
       if (overflowed
          || overflowable < 0
          || (overflowable > 0 && sign_extended_type))
@@ -282,7 +282,7 @@ force_fit_type (tree t, int overflowable,
          TREE_CONSTANT_OVERFLOW (t) = 1;
        }
     }
-  
+
   return t;
 }
 \f
@@ -1451,7 +1451,7 @@ int_const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
                        | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2),
                        TREE_CONSTANT_OVERFLOW (arg1)
                        | TREE_CONSTANT_OVERFLOW (arg2));
-  
+
   return t;
 }
 
@@ -1890,7 +1890,7 @@ fold_convert (tree type, tree arg)
       gcc_assert (TREE_CODE (orig) == VECTOR_TYPE
                  && tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (orig)));
       return fold (build1 (NOP_EXPR, type, arg));
-      
+
     case REAL_TYPE:
       if (TREE_CODE (arg) == INTEGER_CST)
        {
@@ -1911,19 +1911,19 @@ fold_convert (tree type, tree arg)
        case BOOLEAN_TYPE: case ENUMERAL_TYPE:
        case POINTER_TYPE: case REFERENCE_TYPE:
          return fold (build1 (FLOAT_EXPR, type, arg));
-         
+
        case REAL_TYPE:
          return fold (build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR,
                               type, arg));
-         
+
        case COMPLEX_TYPE:
          tem = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
          return fold_convert (type, tem);
-         
+
        default:
          gcc_unreachable ();
        }
-      
+
     case COMPLEX_TYPE:
       switch (TREE_CODE (orig))
        {
@@ -1937,14 +1937,14 @@ fold_convert (tree type, tree arg)
        case COMPLEX_TYPE:
          {
            tree rpart, ipart;
-           
+
            if (TREE_CODE (arg) == COMPLEX_EXPR)
              {
                rpart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 0));
                ipart = fold_convert (TREE_TYPE (type), TREE_OPERAND (arg, 1));
                return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
              }
-           
+
            arg = save_expr (arg);
            rpart = fold (build1 (REALPART_EXPR, TREE_TYPE (orig), arg));
            ipart = fold (build1 (IMAGPART_EXPR, TREE_TYPE (orig), arg));
@@ -1952,11 +1952,11 @@ fold_convert (tree type, tree arg)
            ipart = fold_convert (TREE_TYPE (type), ipart);
            return fold (build2 (COMPLEX_EXPR, type, rpart, ipart));
          }
-         
+
        default:
          gcc_unreachable ();
        }
-      
+
     case VECTOR_TYPE:
       if (integer_zerop (arg))
        return build_zero_vector (type);
@@ -1990,6 +1990,8 @@ non_lvalue (tree x)
 
   case COMPONENT_REF:
   case INDIRECT_REF:
+  case ALIGN_INDIRECT_REF:
+  case MISALIGNED_INDIRECT_REF:
   case ARRAY_REF:
   case ARRAY_RANGE_REF:
   case BIT_FIELD_REF:
@@ -2281,7 +2283,7 @@ combine_comparisons (enum tree_code code, enum tree_code lcode,
 static int
 truth_value_p (enum tree_code code)
 {
-  return (TREE_CODE_CLASS (code) == '<'
+  return (TREE_CODE_CLASS (code) == tcc_comparison
          || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
          || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
          || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR);
@@ -2420,7 +2422,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
 
   switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
     {
-    case '1':
+    case tcc_unary:
       /* Two conversions are equal only if signedness and modes match.  */
       switch (TREE_CODE (arg0))
         {
@@ -2441,8 +2443,8 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
       return operand_equal_p (TREE_OPERAND (arg0, 0),
                              TREE_OPERAND (arg1, 0), flags);
 
-    case '<':
-    case '2':
+    case tcc_comparison:
+    case tcc_binary:
       if (operand_equal_p (TREE_OPERAND (arg0, 0),
                           TREE_OPERAND (arg1, 0), flags)
          && operand_equal_p (TREE_OPERAND (arg0, 1),
@@ -2456,7 +2458,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
              && operand_equal_p (TREE_OPERAND (arg0, 1),
                                  TREE_OPERAND (arg1, 0), flags));
 
-    case 'r':
+    case tcc_reference:
       /* If either of the pointer (or reference) expressions we are
         dereferencing contain a side effect, these cannot be equal.  */
       if (TREE_SIDE_EFFECTS (arg0)
@@ -2466,6 +2468,8 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
       switch (TREE_CODE (arg0))
        {
        case INDIRECT_REF:
+       case ALIGN_INDIRECT_REF:
+       case MISALIGNED_INDIRECT_REF:
        case REALPART_EXPR:
        case IMAGPART_EXPR:
          return operand_equal_p (TREE_OPERAND (arg0, 0),
@@ -2503,7 +2507,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
          return 0;
        }
 
-    case 'e':
+    case tcc_expression:
       switch (TREE_CODE (arg0))
        {
        case ADDR_EXPR:
@@ -2570,7 +2574,7 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
          return 0;
        }
 
-    case 'd':
+    case tcc_declaration:
       /* Consider __builtin_sqrt equal to sqrt.  */
       return (TREE_CODE (arg0) == FUNCTION_DECL
              && DECL_BUILT_IN (arg0) && DECL_BUILT_IN (arg1)
@@ -2652,17 +2656,17 @@ static int
 twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
 {
   enum tree_code code = TREE_CODE (arg);
-  char class = TREE_CODE_CLASS (code);
+  enum tree_code_class class = TREE_CODE_CLASS (code);
 
-  /* We can handle some of the 'e' cases here.  */
-  if (class == 'e' && code == TRUTH_NOT_EXPR)
-    class = '1';
-  else if (class == 'e'
+  /* We can handle some of the tcc_expression cases here.  */
+  if (class == tcc_expression && code == TRUTH_NOT_EXPR)
+    class = tcc_unary;
+  else if (class == tcc_expression
           && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR
               || code == COMPOUND_EXPR))
-    class = '2';
+    class = tcc_binary;
 
-  else if (class == 'e' && code == SAVE_EXPR
+  else if (class == tcc_expression && code == SAVE_EXPR
           && ! TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
     {
       /* If we've already found a CVAL1 or CVAL2, this expression is
@@ -2670,24 +2674,24 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
       if (*cval1 || *cval2)
        return 0;
 
-      class = '1';
+      class = tcc_unary;
       *save_p = 1;
     }
 
   switch (class)
     {
-    case '1':
+    case tcc_unary:
       return twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p);
 
-    case '2':
+    case tcc_binary:
       return (twoval_comparison_p (TREE_OPERAND (arg, 0), cval1, cval2, save_p)
              && twoval_comparison_p (TREE_OPERAND (arg, 1),
                                      cval1, cval2, save_p));
 
-    case 'c':
+    case tcc_constant:
       return 1;
 
-    case 'e':
+    case tcc_expression:
       if (code == COND_EXPR)
        return (twoval_comparison_p (TREE_OPERAND (arg, 0),
                                     cval1, cval2, save_p)
@@ -2697,7 +2701,7 @@ twoval_comparison_p (tree arg, tree *cval1, tree *cval2, int *save_p)
                                        cval1, cval2, save_p));
       return 0;
 
-    case '<':
+    case tcc_comparison:
       /* First see if we can handle the first operand, then the second.  For
         the second operand, we know *CVAL1 can't be zero.  It must be that
         one side of the comparison is each of the values; test for the
@@ -2745,30 +2749,30 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
 {
   tree type = TREE_TYPE (arg);
   enum tree_code code = TREE_CODE (arg);
-  char class = TREE_CODE_CLASS (code);
+  enum tree_code_class class = TREE_CODE_CLASS (code);
 
-  /* We can handle some of the 'e' cases here.  */
-  if (class == 'e' && code == TRUTH_NOT_EXPR)
-    class = '1';
-  else if (class == 'e'
+  /* We can handle some of the tcc_expression cases here.  */
+  if (class == tcc_expression && code == TRUTH_NOT_EXPR)
+    class = tcc_unary;
+  else if (class == tcc_expression
           && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR))
-    class = '2';
+    class = tcc_binary;
 
   switch (class)
     {
-    case '1':
+    case tcc_unary:
       return fold (build1 (code, type,
                           eval_subst (TREE_OPERAND (arg, 0),
                                       old0, new0, old1, new1)));
 
-    case '2':
+    case tcc_binary:
       return fold (build2 (code, type,
                           eval_subst (TREE_OPERAND (arg, 0),
                                       old0, new0, old1, new1),
                           eval_subst (TREE_OPERAND (arg, 1),
                                       old0, new0, old1, new1)));
 
-    case 'e':
+    case tcc_expression:
       switch (code)
        {
        case SAVE_EXPR:
@@ -2790,7 +2794,7 @@ eval_subst (tree arg, tree old0, tree new0, tree old1, tree new1)
        }
       /* Fall through - ???  */
 
-    case '<':
+    case tcc_comparison:
       {
        tree arg0 = TREE_OPERAND (arg, 0);
        tree arg1 = TREE_OPERAND (arg, 1);
@@ -2890,7 +2894,7 @@ invert_truthvalue (tree arg)
      floating-point non-equality comparisons, in which case we just
      enclose a TRUTH_NOT_EXPR around what we have.  */
 
-  if (TREE_CODE_CLASS (code) == '<')
+  if (TREE_CODE_CLASS (code) == tcc_comparison)
     {
       tree op_type = TREE_TYPE (TREE_OPERAND (arg, 0));
       if (FLOAT_TYPE_P (op_type)
@@ -3306,7 +3310,7 @@ decode_field_reference (tree exp, HOST_WIDE_INT *pbitsize,
 
   mask = build_int_cst (unsigned_type, -1);
   mask = force_fit_type (mask, 0, false, false);
-  
+
   mask = const_binop (LSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
   mask = const_binop (RSHIFT_EXPR, mask, size_int (precision - *pbitsize), 0);
 
@@ -3332,7 +3336,7 @@ all_ones_mask_p (tree mask, int size)
 
   tmask = build_int_cst (lang_hooks.types.signed_type (type), -1);
   tmask = force_fit_type (tmask, 0, false, false);
-  
+
   return
     tree_int_cst_equal (mask,
                        const_binop (RSHIFT_EXPR,
@@ -3413,7 +3417,7 @@ simple_operand_p (tree exp)
             == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
     exp = TREE_OPERAND (exp, 0);
 
-  return (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c'
+  return (CONSTANT_CLASS_P (exp)
          || (DECL_P (exp)
              && ! TREE_ADDRESSABLE (exp)
              && ! TREE_THIS_VOLATILE (exp)
@@ -3484,7 +3488,7 @@ range_binop (enum tree_code code, tree type, tree arg0, int upper0_p,
       return TREE_CODE (tem) == INTEGER_CST ? tem : 0;
     }
 
-  if (TREE_CODE_CLASS (code) != '<')
+  if (TREE_CODE_CLASS (code) != tcc_comparison)
     return 0;
 
   /* Set SGN[01] to -1 if ARG[01] is a lower bound, 1 for upper, and 0
@@ -3555,13 +3559,13 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
        {
          if (first_rtl_op (code) > 0)
            arg0 = TREE_OPERAND (exp, 0);
-         if (TREE_CODE_CLASS (code) == '<'
-             || TREE_CODE_CLASS (code) == '1'
-             || TREE_CODE_CLASS (code) == '2')
+         if (TREE_CODE_CLASS (code) == tcc_comparison
+             || TREE_CODE_CLASS (code) == tcc_unary
+             || TREE_CODE_CLASS (code) == tcc_binary)
            arg0_type = TREE_TYPE (arg0);
-         if (TREE_CODE_CLASS (code) == '2'
-             || TREE_CODE_CLASS (code) == '<'
-             || (TREE_CODE_CLASS (code) == 'e'
+         if (TREE_CODE_CLASS (code) == tcc_binary
+             || TREE_CODE_CLASS (code) == tcc_comparison
+             || (TREE_CODE_CLASS (code) == tcc_expression
                  && TREE_CODE_LENGTH (code) > 1))
            arg1 = TREE_OPERAND (exp, 1);
        }
@@ -4192,7 +4196,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
        tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
        return negate_expr (fold_convert (type, tem));
       default:
-       gcc_assert (TREE_CODE_CLASS (comp_code) == '<');
+       gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
        break;
       }
 
@@ -4296,7 +4300,7 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
            return pedantic_non_lvalue (fold_convert (type, arg1));
          break;
        default:
-         gcc_assert (TREE_CODE_CLASS (comp_code) == '<');
+         gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
          break;
        }
     }
@@ -4569,7 +4573,8 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
       rcode = NE_EXPR;
     }
 
-  if (TREE_CODE_CLASS (lcode) != '<' || TREE_CODE_CLASS (rcode) != '<')
+  if (TREE_CODE_CLASS (lcode) != tcc_comparison
+      || TREE_CODE_CLASS (rcode) != tcc_comparison)
     return 0;
 
   ll_arg = TREE_OPERAND (lhs, 0);
@@ -4897,12 +4902,12 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
     {
       if (wanted_code == NE_EXPR)
        {
-         warning ("`or' of unmatched not-equal tests is always 1");
+         warning ("%<or%> of unmatched not-equal tests is always 1");
          return constant_boolean_node (true, truth_type);
        }
       else
        {
-         warning ("`and' of mutually exclusive equal-tests is always 0");
+         warning ("%<and%> of mutually exclusive equal-tests is always 0");
          return constant_boolean_node (false, truth_type);
        }
     }
@@ -5073,10 +5078,10 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
   if (integer_zerop (c))
     return NULL_TREE;
 
-  if (TREE_CODE_CLASS (tcode) == '1')
+  if (TREE_CODE_CLASS (tcode) == tcc_unary)
     op0 = TREE_OPERAND (t, 0);
 
-  if (TREE_CODE_CLASS (tcode) == '2')
+  if (TREE_CODE_CLASS (tcode) == tcc_binary)
     op0 = TREE_OPERAND (t, 0), op1 = TREE_OPERAND (t, 1);
 
   /* Note that we need not handle conditional operations here since fold
@@ -5094,10 +5099,10 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
 
     case CONVERT_EXPR:  case NON_LVALUE_EXPR:  case NOP_EXPR:
       /* If op0 is an expression ...  */
-      if ((TREE_CODE_CLASS (TREE_CODE (op0)) == '<'
-          || TREE_CODE_CLASS (TREE_CODE (op0)) == '1'
-          || TREE_CODE_CLASS (TREE_CODE (op0)) == '2'
-          || TREE_CODE_CLASS (TREE_CODE (op0)) == 'e')
+      if ((COMPARISON_CLASS_P (op0)
+          || UNARY_CLASS_P (op0)
+          || BINARY_CLASS_P (op0)
+          || EXPRESSION_CLASS_P (op0))
          /* ... and is unsigned, and its type is smaller than ctype,
             then we cannot pass through as widening.  */
          && ((TYPE_UNSIGNED (TREE_TYPE (op0))
@@ -5897,7 +5902,7 @@ static bool
 reorder_operands_p (tree arg0, tree arg1)
 {
   if (! flag_evaluation_order)
-    return true;
+      return true;
   if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
     return true;
   return ! TREE_SIDE_EFFECTS (arg0)
@@ -5947,15 +5952,6 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
   if (DECL_P (arg0))
     return 1;
 
-  if (reorder && flag_evaluation_order
-      && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
-    return 0;
-
-  if (DECL_P (arg1))
-    return 0;
-  if (DECL_P (arg0))
-    return 1;
-
   /* It is preferable to swap two SSA_NAME to ensure a canonical form
      for commutative and comparison operators.  Ensuring a canonical
      form allows the optimizers to find additional redundancies without
@@ -5990,14 +5986,14 @@ fold (tree expr)
   tree tem;
   tree arg0 = NULL_TREE, arg1 = NULL_TREE;
   enum tree_code code = TREE_CODE (t);
-  int kind = TREE_CODE_CLASS (code);
+  enum tree_code_class kind = TREE_CODE_CLASS (code);
 
   /* WINS will be nonzero when the switch is done
      if all operands are constant.  */
   int wins = 1;
 
   /* Return right away if a constant.  */
-  if (kind == 'c')
+  if (kind == tcc_constant)
     return t;
 
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
@@ -6046,7 +6042,7 @@ fold (tree expr)
             of the arguments so that their form can be studied.  In any
             cases, the appropriate type conversions should be put back in
             the tree that will get out of the constant folder.  */
-         if (kind == '<')
+         if (kind == tcc_comparison)
            STRIP_SIGN_NOPS (op);
          else
            STRIP_NOPS (op);
@@ -6118,7 +6114,7 @@ fold (tree expr)
       return tem;
     }
 
-  if (TREE_CODE_CLASS (code) == '1')
+  if (TREE_CODE_CLASS (code) == tcc_unary)
     {
       if (TREE_CODE (arg0) == COMPOUND_EXPR)
        return build2 (COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
@@ -6165,7 +6161,7 @@ fold (tree expr)
                                  TREE_OPERAND (TREE_OPERAND (tem, 2), 0)));
          return tem;
        }
-      else if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+      else if (COMPARISON_CLASS_P (arg0))
        {
          if (TREE_CODE (type) == BOOLEAN_TYPE)
            {
@@ -6181,16 +6177,16 @@ fold (tree expr)
                                               integer_zero_node))));
        }
    }
-  else if (TREE_CODE_CLASS (code) == '<'
+  else 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) == '<'
+  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) == '2'
-          || TREE_CODE_CLASS (code) == '<')
+  else 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),
@@ -6202,8 +6198,7 @@ fold (tree expr)
                       fold (build2 (code, type,
                                     arg0, TREE_OPERAND (arg1, 1))));
 
-      if (TREE_CODE (arg0) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg0)) == '<')
+      if (TREE_CODE (arg0) == COND_EXPR || COMPARISON_CLASS_P (arg0))
        {
          tem = fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
                                                     /*cond_first_p=*/1);
@@ -6211,8 +6206,7 @@ fold (tree expr)
            return tem;
        }
 
-      if (TREE_CODE (arg1) == COND_EXPR
-         || TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
+      if (TREE_CODE (arg1) == COND_EXPR || COMPARISON_CLASS_P (arg1))
        {
          tem = fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
                                                     /*cond_first_p=*/0);
@@ -6382,7 +6376,7 @@ fold (tree expr)
       /* Convert (T1)((T2)X op Y) into (T1)X op Y, for pointer types T1 and
         T2 being pointers to types of the same size.  */
       if (POINTER_TYPE_P (TREE_TYPE (t))
-         && TREE_CODE_CLASS (TREE_CODE (arg0)) == '2'
+         && BINARY_CLASS_P (arg0)
          && TREE_CODE (TREE_OPERAND (arg0, 0)) == NOP_EXPR
          && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 0))))
        {
@@ -6683,7 +6677,7 @@ fold (tree expr)
                                   TREE_OPERAND (arg0, 0),
                                   build_real (type, c1)));
            }
-          /* Convert a + (b*c + d*e) into (a + b*c) + d*e */
+          /* Convert a + (b*c + d*e) into (a + b*c) + d*e */
           if (flag_unsafe_math_optimizations
               && TREE_CODE (arg1) == PLUS_EXPR
               && TREE_CODE (arg0) != MULT_EXPR)
@@ -6698,7 +6692,7 @@ fold (tree expr)
                   return fold (build2 (PLUS_EXPR, type, tree0, tree11));
                 }
             }
-          /* Convert (b*c + d*e) + a into b*c + (d*e +a) */
+          /* Convert (b*c + d*e) + a into b*c + (d*e +a) */
           if (flag_unsafe_math_optimizations
               && TREE_CODE (arg0) == PLUS_EXPR
               && TREE_CODE (arg1) != MULT_EXPR)
@@ -6966,6 +6960,18 @@ fold (tree expr)
              || (INTEGRAL_TYPE_P (type) && flag_wrapv && !flag_trapv)))
        return fold (build2 (PLUS_EXPR, type, arg0, negate_expr (arg1)));
 
+      /* Try folding difference of addresses.  */
+      {
+       HOST_WIDE_INT diff;
+
+       if (TREE_CODE (arg0) == ADDR_EXPR
+           && TREE_CODE (arg1) == ADDR_EXPR
+           && ptr_difference_const (TREE_OPERAND (arg0, 0),
+                                    TREE_OPERAND (arg1, 0),
+                                    &diff))
+         return build_int_cst_type (type, diff);
+      }
+
       if (TREE_CODE (arg0) == MULT_EXPR
          && TREE_CODE (arg1) == MULT_EXPR
          && (INTEGRAL_TYPE_P (type) || flag_unsafe_math_optimizations))
@@ -8279,6 +8285,7 @@ fold (tree expr)
               && (t1 = get_unwidened (arg1, TREE_TYPE (tem))) != 0
               && (TREE_TYPE (t1) == TREE_TYPE (tem)
                   || (TREE_CODE (t1) == INTEGER_CST
+                      && TREE_CODE (TREE_TYPE (tem)) == INTEGER_TYPE
                       && int_fits_type_p (t1, TREE_TYPE (tem)))))
        return fold (build2 (code, type, tem,
                             fold_convert (TREE_TYPE (tem), t1)));
@@ -8393,11 +8400,11 @@ fold (tree expr)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree dandnotc
-           = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                           arg1, build1 (BIT_NOT_EXPR,
-                                         TREE_TYPE (TREE_OPERAND (arg0, 1)),
-                                         TREE_OPERAND (arg0, 1))));
+         tree notc = fold (build1 (BIT_NOT_EXPR,
+                                   TREE_TYPE (TREE_OPERAND (arg0, 1)),
+                                   TREE_OPERAND (arg0, 1)));
+         tree dandnotc = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                                       arg1, notc));
          tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
          if (integer_nonzerop (dandnotc))
            return omit_one_operand (type, rslt, arg0);
@@ -8410,10 +8417,9 @@ fold (tree expr)
          && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
        {
-         tree candnotd
-           = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
-                           TREE_OPERAND (arg0, 1),
-                           build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1)));
+         tree notd = fold (build1 (BIT_NOT_EXPR, TREE_TYPE (arg1), arg1));
+         tree candnotd = fold (build2 (BIT_AND_EXPR, TREE_TYPE (arg0),
+                                       TREE_OPERAND (arg0, 1), notd));
          tree rslt = code == EQ_EXPR ? integer_zero_node : integer_one_node;
          if (integer_nonzerop (candnotd))
            return omit_one_operand (type, rslt, arg0);
@@ -8760,7 +8766,7 @@ fold (tree expr)
         for reasons given above each one.
 
          Also try swapping the arguments and inverting the conditional.  */
-      if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+      if (COMPARISON_CLASS_P (arg0)
          && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
                                             arg1, TREE_OPERAND (arg0, 1))
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
@@ -8772,14 +8778,14 @@ fold (tree expr)
            return tem;
        }
 
-      if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+      if (COMPARISON_CLASS_P (arg0)
          && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
                                             TREE_OPERAND (t, 2),
                                             TREE_OPERAND (arg0, 1))
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
        {
          tem = invert_truthvalue (arg0);
-         if (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
+         if (COMPARISON_CLASS_P (tem))
            {
              tem = fold_cond_expr_with_comparison (type, tem,
                                                    TREE_OPERAND (t, 2),
@@ -9043,14 +9049,15 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     return;
   *slot = expr;
   code = TREE_CODE (expr);
-  if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
+  if (TREE_CODE_CLASS (code) == tcc_declaration
+      && DECL_ASSEMBLER_NAME_SET_P (expr))
     {
       /* Allow DECL_ASSEMBLER_NAME to be modified.  */
       memcpy (buf, expr, tree_size (expr));
       expr = (tree) buf;
       SET_DECL_ASSEMBLER_NAME (expr, NULL);
     }
-  else if (TREE_CODE_CLASS (code) == 't'
+  else if (TREE_CODE_CLASS (code) == tcc_type
           && (TYPE_POINTER_TO (expr) || TYPE_REFERENCE_TO (expr)
               || TYPE_CACHED_VALUES_P (expr)))
     {
@@ -9064,11 +9071,12 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     }
   md5_process_bytes (expr, tree_size (expr), ctx);
   fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
-  if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
+  if (TREE_CODE_CLASS (code) != tcc_type
+      && TREE_CODE_CLASS (code) != tcc_declaration)
     fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
   switch (TREE_CODE_CLASS (code))
     {
-    case 'c':
+    case tcc_constant:
       switch (code)
        {
        case STRING_CST:
@@ -9086,7 +9094,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
          break;
        }
       break;
-    case 'x':
+    case tcc_exceptional:
       switch (code)
        {
        case TREE_LIST:
@@ -9101,17 +9109,17 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
          break;
        }
       break;
-    case 'e':
-    case 'r':
-    case '<':
-    case '1':
-    case '2':
-    case 's':
+    case tcc_expression:
+    case tcc_reference:
+    case tcc_comparison:
+    case tcc_unary:
+    case tcc_binary:
+    case tcc_statement:
       len = first_rtl_op (code);
       for (i = 0; i < len; ++i)
        fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
       break;
-    case 'd':
+    case tcc_declaration:
       fold_checksum_tree (DECL_SIZE (expr), ctx, ht);
       fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht);
       fold_checksum_tree (DECL_NAME (expr), ctx, ht);
@@ -9124,7 +9132,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
       fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
       fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
       break;
-    case 't':
+    case tcc_type:
       if (TREE_CODE (expr) == ENUMERAL_TYPE)
         fold_checksum_tree (TYPE_VALUES (expr), ctx, ht);
       fold_checksum_tree (TYPE_SIZE (expr), ctx, ht);
@@ -9551,7 +9559,7 @@ tree_expr_nonnegative_p (tree t)
 
 /* Return true when T is an address and is known to be nonzero.
    For floating point we further ensure that T is not denormal.
-   Similar logic is present in nonzero_address in rtlanal.h  */
+   Similar logic is present in nonzero_address in rtlanal.h.  */
 
 static bool
 tree_expr_nonzero_p (tree t)
@@ -9618,7 +9626,7 @@ tree_expr_nonzero_p (tree t)
          return !DECL_WEAK (base);
 
        /* Constants are never weak.  */
-       if (TREE_CODE_CLASS (TREE_CODE (base)) == 'c')
+       if (CONSTANT_CLASS_P (base))
          return true;
 
        return false;
@@ -10270,7 +10278,7 @@ fold_negate_const (tree arg0, tree type)
                            TREE_CONSTANT_OVERFLOW (arg0));
        break;
       }
-      
+
     case REAL_CST:
       t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
       break;
@@ -10278,7 +10286,7 @@ fold_negate_const (tree arg0, tree type)
     default:
       gcc_unreachable ();
     }
-  
+
   return t;
 }
 
@@ -10316,18 +10324,18 @@ fold_abs_const (tree arg0, tree type)
                              TREE_CONSTANT_OVERFLOW (arg0));
        }
       break;
-      
+
     case REAL_CST:
       if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg0)))
        t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
       else
        t =  arg0;
       break;
-      
+
     default:
       gcc_unreachable ();
     }
-  
+
   return t;
 }
 
@@ -10340,13 +10348,13 @@ fold_not_const (tree arg0, tree type)
   tree t = NULL_TREE;
 
   gcc_assert (TREE_CODE (arg0) == INTEGER_CST);
-  
+
   t = build_int_cst_wide (type,
                          ~ TREE_INT_CST_LOW (arg0),
                          ~ TREE_INT_CST_HIGH (arg0));
   t = force_fit_type (t, 0, TREE_OVERFLOW (arg0),
                      TREE_CONSTANT_OVERFLOW (arg0));
-  
+
   return t;
 }
 
@@ -10464,7 +10472,9 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
   if (TREE_CODE (t) == WITH_SIZE_EXPR)
     t = TREE_OPERAND (t, 0);
 
-  if (TREE_CODE (t) == INDIRECT_REF)
+  /* Note: doesn't apply to ALIGN_INDIRECT_REF */
+  if (TREE_CODE (t) == INDIRECT_REF
+      || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
     {
       t = TREE_OPERAND (t, 0);
       if (TREE_TYPE (t) != ptrtype)
@@ -10542,12 +10552,12 @@ fold_ignored_result (tree t)
   for (;;)
     switch (TREE_CODE_CLASS (TREE_CODE (t)))
       {
-      case '1':
+      case tcc_unary:
        t = TREE_OPERAND (t, 0);
        break;
 
-      case '2':
-      case '<':
+      case tcc_binary:
+      case tcc_comparison:
        if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 1)))
          t = TREE_OPERAND (t, 0);
        else if (!TREE_SIDE_EFFECTS (TREE_OPERAND (t, 0)))
@@ -10556,7 +10566,7 @@ fold_ignored_result (tree t)
          return t;
        break;
 
-      case 'e':
+      case tcc_expression:
        switch (TREE_CODE (t))
          {
          case COMPOUND_EXPR:
@@ -10610,7 +10620,7 @@ round_up (tree value, int divisor)
   if (divisor == (divisor & -divisor))
     {
       tree t;
-      
+
       t = build_int_cst (TREE_TYPE (value), divisor - 1);
       value = size_binop (PLUS_EXPR, value, t);
       t = build_int_cst (TREE_TYPE (value), -divisor);
@@ -10654,7 +10664,7 @@ round_down (tree value, int divisor)
   if (divisor == (divisor & -divisor))
     {
       tree t;
-      
+
       t = build_int_cst (TREE_TYPE (value), -divisor);
       value = size_binop (BIT_AND_EXPR, value, t);
     }
@@ -10668,3 +10678,51 @@ round_down (tree value, int divisor)
 
   return value;
 }
+
+/* Returns true if addresses of E1 and E2 differ by a constant, false
+   otherwise.  If they do, &E1 - &E2 is stored in *DIFF.  */
+
+bool
+ptr_difference_const (tree e1, tree e2, HOST_WIDE_INT *diff)
+{
+  tree core1, core2;
+  HOST_WIDE_INT bitsize1, bitsize2;
+  HOST_WIDE_INT bitpos1, bitpos2;
+  tree toffset1, toffset2, tdiff, type;
+  enum machine_mode mode1, mode2;
+  int unsignedp1, unsignedp2, volatilep1, volatilep2;
+
+  core1 = get_inner_reference (e1, &bitsize1, &bitpos1, &toffset1, &mode1,
+                              &unsignedp1, &volatilep1);
+  core2 = get_inner_reference (e2, &bitsize2, &bitpos2, &toffset2, &mode2,
+                              &unsignedp2, &volatilep2);
+
+  if (bitpos1 % BITS_PER_UNIT != 0
+      || bitpos2 % BITS_PER_UNIT != 0
+      || !operand_equal_p (core1, core2, 0))
+    return false;
+
+  if (toffset1 && toffset2)
+    {
+      type = TREE_TYPE (toffset1);
+      if (type != TREE_TYPE (toffset2))
+       toffset2 = fold_convert (type, toffset2);
+
+      tdiff = fold (build2 (MINUS_EXPR, type, toffset1, toffset2));
+      if (!host_integerp (tdiff, 0))
+       return false;
+
+      *diff = tree_low_cst (tdiff, 0);
+    }
+  else if (toffset1 || toffset2)
+    {
+      /* If only one of the offsets is non-constant, the difference cannot
+        be a constant.  */
+      return false;
+    }
+  else
+    *diff = 0;
+
+  *diff += (bitpos1 - bitpos2) / BITS_PER_UNIT;
+  return true;
+}