OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index c762fad..2fe0b7e 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
@@ -1267,7 +1267,15 @@ associate_trees (tree t1, tree t2, enum tree_code code, tree type)
          else if (TREE_CODE (t2) == NEGATE_EXPR)
            return build2 (MINUS_EXPR, type, fold_convert (type, t1),
                           fold_convert (type, TREE_OPERAND (t2, 0)));
+         else if (integer_zerop (t2))
+           return fold_convert (type, t1);
+       }
+      else if (code == MINUS_EXPR)
+       {
+         if (integer_zerop (t2))
+           return fold_convert (type, t1);
        }
+
       return build2 (code, type, fold_convert (type, t1),
                     fold_convert (type, t2));
     }
@@ -1451,7 +1459,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 +1898,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 +1919,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 +1945,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 +1960,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);
@@ -1978,6 +1986,11 @@ fold_convert (tree type, tree arg)
 tree
 non_lvalue (tree x)
 {
+  /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
+     us.  */
+  if (in_gimple_form)
+    return x;
+
   /* We only need to wrap lvalue tree codes.  */
   switch (TREE_CODE (x))
   {
@@ -1990,6 +2003,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:
@@ -2028,7 +2043,7 @@ int pedantic_lvalues;
 /* When pedantic, return an expr equal to X but certainly not valid as a
    pedantic lvalue.  Otherwise, return X.  */
 
-tree
+static tree
 pedantic_non_lvalue (tree x)
 {
   if (pedantic_lvalues)
@@ -2316,17 +2331,8 @@ truth_value_p (enum tree_code code)
 int
 operand_equal_p (tree arg0, tree arg1, unsigned int flags)
 {
-  /* If one is specified and the other isn't, they aren't equal and if
-     neither is specified, they are.
-
-     ??? This is temporary and is meant only to handle the cases of the
-     optional operands for COMPONENT_REF and ARRAY_REF.  */
-  if ((arg0 && !arg1) || (!arg0 && arg1))
-    return 0;
-  else if (!arg0 && !arg1)
-    return 1;
   /* If either is ERROR_MARK, they aren't equal.  */
-  else if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
+  if (TREE_CODE (arg0) == ERROR_MARK || TREE_CODE (arg1) == ERROR_MARK)
     return 0;
 
   /* If both types don't have the same signedness, then we can't consider
@@ -2418,6 +2424,17 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
   if (flags & OEP_ONLY_CONST)
     return 0;
 
+/* Define macros to test an operand from arg0 and arg1 for equality and a
+   variant that allows null and views null as being different from any
+   non-null value.  In the latter case, if either is null, the both
+   must be; otherwise, do the normal comparison.  */
+#define OP_SAME(N) operand_equal_p (TREE_OPERAND (arg0, N),    \
+                                   TREE_OPERAND (arg1, N), flags)
+
+#define OP_SAME_WITH_NULL(N)                           \
+  ((!TREE_OPERAND (arg0, N) || !TREE_OPERAND (arg1, N))        \
+   ? TREE_OPERAND (arg0, N) == TREE_OPERAND (arg1, N) : OP_SAME (N))
+
   switch (TREE_CODE_CLASS (TREE_CODE (arg0)))
     {
     case tcc_unary:
@@ -2438,15 +2455,12 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
          break;
        }
 
-      return operand_equal_p (TREE_OPERAND (arg0, 0),
-                             TREE_OPERAND (arg1, 0), flags);
+      return OP_SAME (0);
+
 
     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),
-                             TREE_OPERAND (arg1, 1), flags))
+      if (OP_SAME (0) && OP_SAME (1))
        return 1;
 
       /* For commutative ops, allow the other order.  */
@@ -2466,39 +2480,27 @@ 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),
-                                 TREE_OPERAND (arg1, 0), flags);
+         return OP_SAME (0);
 
        case ARRAY_REF:
        case ARRAY_RANGE_REF:
-         return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 2),
-                                     TREE_OPERAND (arg1, 2), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 3),
-                                     TREE_OPERAND (arg1, 3), flags));
-
+         /* Operands 2 and 3 may be null.  */
+         return (OP_SAME (0)
+                 && OP_SAME (1)
+                 && OP_SAME_WITH_NULL (2)
+                 && OP_SAME_WITH_NULL (3));
 
        case COMPONENT_REF:
-         return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 2),
-                                     TREE_OPERAND (arg1, 2), flags));
-
+         /* Handle operand 2 the same as for ARRAY_REF.  */
+         return OP_SAME (0) && OP_SAME (1) && OP_SAME_WITH_NULL (2);
 
        case BIT_FIELD_REF:
-         return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags)
-                 && operand_equal_p (TREE_OPERAND (arg0, 2),
-                                     TREE_OPERAND (arg1, 2), flags));
+         return OP_SAME (0) && OP_SAME (1) && OP_SAME (2);
+
        default:
          return 0;
        }
@@ -2508,33 +2510,28 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
        {
        case ADDR_EXPR:
        case TRUTH_NOT_EXPR:
-         return operand_equal_p (TREE_OPERAND (arg0, 0),
-                                 TREE_OPERAND (arg1, 0), flags);
+         return OP_SAME (0);
 
        case TRUTH_ANDIF_EXPR:
        case TRUTH_ORIF_EXPR:
-         return operand_equal_p (TREE_OPERAND (arg0, 0),
-                                 TREE_OPERAND (arg1, 0), flags)
-                && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                    TREE_OPERAND (arg1, 1), flags);
+         return OP_SAME (0) && OP_SAME (1);
 
        case TRUTH_AND_EXPR:
        case TRUTH_OR_EXPR:
        case TRUTH_XOR_EXPR:
+         if (OP_SAME (0) && OP_SAME (1))
+           return 1;
+
+         /* Otherwise take into account this is a commutative operation.  */
          return (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                  TREE_OPERAND (arg1, 0), flags)
+                                  TREE_OPERAND (arg1, 1), flags)
                  && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                     TREE_OPERAND (arg1, 1), flags))
-                || (operand_equal_p (TREE_OPERAND (arg0, 0),
-                                     TREE_OPERAND (arg1, 1), flags)
-                    && operand_equal_p (TREE_OPERAND (arg0, 1),
-                                        TREE_OPERAND (arg1, 0), flags));
+                                     TREE_OPERAND (arg1, 0), flags));
 
        case CALL_EXPR:
          /* If the CALL_EXPRs call different functions, then they
             clearly can not be equal.  */
-         if (! operand_equal_p (TREE_OPERAND (arg0, 0),
-                                TREE_OPERAND (arg1, 0), flags))
+         if (!OP_SAME (0))
            return 0;
 
          {
@@ -2580,6 +2577,9 @@ operand_equal_p (tree arg0, tree arg1, unsigned int flags)
     default:
       return 0;
     }
+
+#undef OP_SAME
+#undef OP_SAME_WITH_NULL
 }
 \f
 /* Similar to operand_equal_p, but see if ARG0 might have been made by
@@ -3306,7 +3306,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 +3332,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,
@@ -3407,13 +3407,10 @@ static int
 simple_operand_p (tree exp)
 {
   /* Strip any conversions that don't change the machine mode.  */
-  while ((TREE_CODE (exp) == NOP_EXPR
-         || TREE_CODE (exp) == CONVERT_EXPR)
-        && (TYPE_MODE (TREE_TYPE (exp))
-            == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
-    exp = TREE_OPERAND (exp, 0);
+  STRIP_NOPS (exp);
 
   return (CONSTANT_CLASS_P (exp)
+         || TREE_CODE (exp) == SSA_NAME
          || (DECL_P (exp)
              && ! TREE_ADDRESSABLE (exp)
              && ! TREE_THIS_VOLATILE (exp)
@@ -3553,7 +3550,7 @@ make_range (tree exp, int *pin_p, tree *plow, tree *phigh)
 
       if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)))
        {
-         if (first_rtl_op (code) > 0)
+         if (TREE_CODE_LENGTH (code) > 0)
            arg0 = TREE_OPERAND (exp, 0);
          if (TREE_CODE_CLASS (code) == tcc_comparison
              || TREE_CODE_CLASS (code) == tcc_unary
@@ -4375,8 +4372,8 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
 
 
 \f
-#ifndef RANGE_TEST_NON_SHORT_CIRCUIT
-#define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
+#ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
+#define LOGICAL_OP_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
 #endif
 
 /* EXP is some logical combination of boolean tests.  See if we can
@@ -4414,7 +4411,7 @@ fold_range_test (tree exp)
   /* On machines where the branch cost is expensive, if this is a
      short-circuited branch and the underlying object on both sides
      is the same, make a non-short-circuit operation.  */
-  else if (RANGE_TEST_NON_SHORT_CIRCUIT
+  else if (LOGICAL_OP_NON_SHORT_CIRCUIT
           && lhs != 0 && rhs != 0
           && (TREE_CODE (exp) == TRUTH_ANDIF_EXPR
               || TREE_CODE (exp) == TRUTH_ORIF_EXPR)
@@ -4636,7 +4633,8 @@ fold_truthop (enum tree_code code, tree truth_type, tree lhs, tree rhs)
                               ll_arg, rl_arg),
                       fold_convert (TREE_TYPE (ll_arg), integer_zero_node));
 
-      return build2 (code, truth_type, lhs, rhs);
+      if (LOGICAL_OP_NON_SHORT_CIRCUIT)
+       return build2 (code, truth_type, lhs, rhs);
     }
 
   /* See if the comparisons can be merged.  Then get all the parameters for
@@ -5129,7 +5127,21 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type)
        return t1;
       break;
 
-    case NEGATE_EXPR:  case ABS_EXPR:
+    case ABS_EXPR:
+      /* If widening the type changes it from signed to unsigned, then we
+         must avoid building ABS_EXPR itself as unsigned.  */
+      if (TYPE_UNSIGNED (ctype) && !TYPE_UNSIGNED (type))
+        {
+          tree cstype = (*lang_hooks.types.signed_type) (ctype);
+          if ((t1 = extract_muldiv (op0, c, code, cstype)) != 0)
+            {
+              t1 = fold (build1 (tcode, cstype, fold_convert (cstype, t1)));
+              return fold_convert (ctype, t1);
+            }
+          break;
+        }
+      /* FALLTHROUGH */
+    case NEGATE_EXPR:
       if ((t1 = extract_muldiv (op0, c, code, wide_type)) != 0)
        return fold (build1 (tcode, ctype, fold_convert (ctype, t1)));
       break;
@@ -5716,6 +5728,9 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
     }
   else
     {
+      /* A negative divisor reverses the relational operators.  */
+      code = swap_tree_comparison (code);
+
       tmp = int_const_binop (PLUS_EXPR, arg01, integer_one_node, 0);
       switch (tree_int_cst_sgn (arg1))
        {
@@ -5861,7 +5876,8 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
         operations as unsigned.  If we must use the AND, we have a choice.
         Normally unsigned is faster, but for some machines signed is.  */
 #ifdef LOAD_EXTEND_OP
-      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND ? 0 : 1);
+      ops_unsigned = (LOAD_EXTEND_OP (operand_mode) == SIGN_EXTEND 
+                     && !flag_syntax_only) ? 0 : 1;
 #else
       ops_unsigned = 1;
 #endif
@@ -5898,7 +5914,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)
@@ -5948,15 +5964,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
@@ -5969,6 +5976,251 @@ tree_swap_operands_p (tree arg0, tree arg1, bool reorder)
   return 0;
 }
 
+/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where
+   ARG0 is extended to a wider type.  */
+
+static tree
+fold_widened_comparison (enum tree_code code, tree type, tree arg0, tree arg1)
+{
+  tree arg0_unw = get_unwidened (arg0, NULL_TREE);
+  tree arg1_unw;
+  tree shorter_type, outer_type;
+  tree min, max;
+  bool above, below;
+
+  if (arg0_unw == arg0)
+    return NULL_TREE;
+  shorter_type = TREE_TYPE (arg0_unw);
+  
+  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
+       || 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
+             && int_fits_type_p (arg1_unw, shorter_type))))
+    return fold (build (code, type, arg0_unw,
+                       fold_convert (shorter_type, arg1_unw)));
+
+  if (TREE_CODE (arg1_unw) != INTEGER_CST)
+    return NULL_TREE;
+
+  /* If we are comparing with the integer that does not fit into the range
+     of the shorter type, the result is known.  */
+  outer_type = TREE_TYPE (arg1_unw);
+  min = lower_bound_in_type (outer_type, shorter_type);
+  max = upper_bound_in_type (outer_type, shorter_type);
+
+  above = integer_nonzerop (fold_relational_const (LT_EXPR, type,
+                                                  max, arg1_unw));
+  below = integer_nonzerop (fold_relational_const (LT_EXPR, type,
+                                                  arg1_unw, min));
+
+  switch (code)
+    {
+    case EQ_EXPR:
+      if (above || below)
+       return omit_one_operand (type, integer_zero_node, arg0);
+      break;
+
+    case NE_EXPR:
+      if (above || below)
+       return omit_one_operand (type, integer_one_node, arg0);
+      break;
+
+    case LT_EXPR:
+    case LE_EXPR:
+      if (above)
+       return omit_one_operand (type, integer_one_node, arg0);
+      else if (below)
+       return omit_one_operand (type, integer_zero_node, arg0);
+
+    case GT_EXPR:
+    case GE_EXPR:
+      if (above)
+       return omit_one_operand (type, integer_zero_node, arg0);
+      else if (below)
+       return omit_one_operand (type, integer_one_node, arg0);
+
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
+
+/* Fold comparison ARG0 CODE ARG1 (with result in TYPE), where for
+   ARG0 just the signedness is changed.  */
+
+static tree
+fold_sign_changed_comparison (enum tree_code code, tree type,
+                             tree arg0, tree arg1)
+{
+  tree arg0_inner, tmp;
+  tree inner_type, outer_type;
+
+  if (TREE_CODE (arg0) != NOP_EXPR)
+    return NULL_TREE;
+
+  outer_type = TREE_TYPE (arg0);
+  arg0_inner = TREE_OPERAND (arg0, 0);
+  inner_type = TREE_TYPE (arg0_inner);
+
+  if (TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
+    return NULL_TREE;
+
+  if (TREE_CODE (arg1) != INTEGER_CST
+      && !(TREE_CODE (arg1) == NOP_EXPR
+          && TREE_TYPE (TREE_OPERAND (arg1, 0)) == inner_type))
+    return NULL_TREE;
+
+  if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
+      && code != NE_EXPR
+      && code != EQ_EXPR)
+    return NULL_TREE;
+
+  if (TREE_CODE (arg1) == INTEGER_CST)
+    {
+      tmp = build_int_cst_wide (inner_type,
+                               TREE_INT_CST_LOW (arg1),
+                               TREE_INT_CST_HIGH (arg1));
+      arg1 = force_fit_type (tmp, 0,
+                            TREE_OVERFLOW (arg1),
+                            TREE_CONSTANT_OVERFLOW (arg1));
+    }
+  else
+    arg1 = fold_convert (inner_type, arg1);
+
+  return fold (build (code, type, arg0_inner, arg1));
+}
+
+/* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
+   step of the array.  TYPE is the type of the expression.  ADDR is the address.
+   MULT is the multiplicative expression.  If the function succeeds, the new
+   address expression is returned.  Otherwise NULL_TREE is returned.  */
+
+static tree
+try_move_mult_to_index (tree type, enum tree_code code, tree addr, tree mult)
+{
+  tree s, delta, step;
+  tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
+  tree ref = TREE_OPERAND (addr, 0), pref;
+  tree ret, pos;
+  tree itype;
+
+  STRIP_NOPS (arg0);
+  STRIP_NOPS (arg1);
+  
+  if (TREE_CODE (arg0) == INTEGER_CST)
+    {
+      s = arg0;
+      delta = arg1;
+    }
+  else if (TREE_CODE (arg1) == INTEGER_CST)
+    {
+      s = arg1;
+      delta = arg0;
+    }
+  else
+    return NULL_TREE;
+
+  for (;; ref = TREE_OPERAND (ref, 0))
+    {
+      if (TREE_CODE (ref) == ARRAY_REF)
+       {
+         step = array_ref_element_size (ref);
+
+         if (TREE_CODE (step) != INTEGER_CST)
+           continue;
+
+         itype = TREE_TYPE (step);
+
+         /* If the type sizes do not match, we might run into problems
+            when one of them would overflow.  */
+         if (TYPE_PRECISION (itype) != TYPE_PRECISION (type))
+           continue;
+
+         if (!operand_equal_p (step, fold_convert (itype, s), 0))
+           continue;
+
+         delta = fold_convert (itype, delta);
+         break;
+       }
+
+      if (!handled_component_p (ref))
+       return NULL_TREE;
+    }
+
+  /* We found the suitable array reference.  So copy everything up to it,
+     and replace the index.  */
+
+  pref = TREE_OPERAND (addr, 0);
+  ret = copy_node (pref);
+  pos = ret;
+
+  while (pref != ref)
+    {
+      pref = TREE_OPERAND (pref, 0);
+      TREE_OPERAND (pos, 0) = copy_node (pref);
+      pos = TREE_OPERAND (pos, 0);
+    }
+
+  TREE_OPERAND (pos, 1) = fold (build2 (code, itype,
+                                       TREE_OPERAND (pos, 1),
+                                       delta));
+
+  return build1 (ADDR_EXPR, type, ret);
+}
+
+
+/* Fold A < X && A + 1 > Y to A < X && A >= Y.  Normally A + 1 > Y
+   means A >= Y && A != MAX, but in this case we know that
+   A < X <= MAX.  INEQ is A + 1 > Y, BOUND is A < X.  */
+
+static tree
+fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound)
+{
+  tree a, typea, type = TREE_TYPE (ineq), a1, diff, y;
+
+  if (TREE_CODE (bound) == LT_EXPR)
+    a = TREE_OPERAND (bound, 0);
+  else if (TREE_CODE (bound) == GT_EXPR)
+    a = TREE_OPERAND (bound, 1);
+  else
+    return NULL_TREE;
+
+  typea = TREE_TYPE (a);
+  if (!INTEGRAL_TYPE_P (typea)
+      && !POINTER_TYPE_P (typea))
+    return NULL_TREE;
+
+  if (TREE_CODE (ineq) == LT_EXPR)
+    {
+      a1 = TREE_OPERAND (ineq, 1);
+      y = TREE_OPERAND (ineq, 0);
+    }
+  else if (TREE_CODE (ineq) == GT_EXPR)
+    {
+      a1 = TREE_OPERAND (ineq, 0);
+      y = TREE_OPERAND (ineq, 1);
+    }
+  else
+    return NULL_TREE;
+
+  if (TREE_TYPE (a1) != typea)
+    return NULL_TREE;
+
+  diff = fold (build2 (MINUS_EXPR, typea, a1, a));
+  if (!integer_onep (diff))
+    return NULL_TREE;
+
+  return fold (build2 (GE_EXPR, type, a, y));
+}
+
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
    and application of the associative law.
@@ -6026,7 +6278,7 @@ fold (tree expr)
     }
   else if (IS_EXPR_CODE_CLASS (kind))
     {
-      int len = first_rtl_op (code);
+      int len = TREE_CODE_LENGTH (code);
       int i;
       for (i = 0; i < len; i++)
        {
@@ -6153,10 +6405,11 @@ fold (tree expr)
              && ! VOID_TYPE_P (TREE_OPERAND (tem, 2))
              && (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))
                  == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 2), 0)))
-             && ! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
-                   && (INTEGRAL_TYPE_P
-                       (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
-                   && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD))
+             && (! (INTEGRAL_TYPE_P (TREE_TYPE (tem))
+                    && (INTEGRAL_TYPE_P
+                        (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (tem, 1), 0))))
+                    && TYPE_PRECISION (TREE_TYPE (tem)) <= BITS_PER_WORD)
+                 || flag_syntax_only))
            tem = build1 (code, type,
                          build3 (COND_EXPR,
                                  TREE_TYPE (TREE_OPERAND
@@ -6363,6 +6616,7 @@ fold (tree expr)
              change = (cst == 0);
 #ifdef LOAD_EXTEND_OP
              if (change
+                 && !flag_syntax_only
                  && (LOAD_EXTEND_OP (TYPE_MODE (TREE_TYPE (and0)))
                      == ZERO_EXTEND))
                {
@@ -6510,17 +6764,21 @@ fold (tree expr)
          /* Reassociate (plus (plus (mult) (foo)) (mult)) as
             (plus (plus (mult) (mult)) (foo)) so that we can
             take advantage of the factoring cases below.  */
-         if ((TREE_CODE (arg0) == PLUS_EXPR
+         if (((TREE_CODE (arg0) == PLUS_EXPR
+               || TREE_CODE (arg0) == MINUS_EXPR)
               && TREE_CODE (arg1) == MULT_EXPR)
-             || (TREE_CODE (arg1) == PLUS_EXPR
+             || ((TREE_CODE (arg1) == PLUS_EXPR
+                  || TREE_CODE (arg1) == MINUS_EXPR)
                  && TREE_CODE (arg0) == MULT_EXPR))
            {
              tree parg0, parg1, parg, marg;
+             enum tree_code pcode;
 
-             if (TREE_CODE (arg0) == PLUS_EXPR)
+             if (TREE_CODE (arg1) == MULT_EXPR)
                parg = arg0, marg = arg1;
              else
                parg = arg1, marg = arg0;
+             pcode = TREE_CODE (parg);
              parg0 = TREE_OPERAND (parg, 0);
              parg1 = TREE_OPERAND (parg, 1);
              STRIP_NOPS (parg0);
@@ -6528,7 +6786,7 @@ fold (tree expr)
 
              if (TREE_CODE (parg0) == MULT_EXPR
                  && TREE_CODE (parg1) != MULT_EXPR)
-               return fold (build2 (PLUS_EXPR, type,
+               return fold (build2 (pcode, type,
                                     fold (build2 (PLUS_EXPR, type,
                                                   fold_convert (type, parg0),
                                                   fold_convert (type, marg))),
@@ -6536,10 +6794,11 @@ fold (tree expr)
              if (TREE_CODE (parg0) != MULT_EXPR
                  && TREE_CODE (parg1) == MULT_EXPR)
                return fold (build2 (PLUS_EXPR, type,
-                                    fold (build2 (PLUS_EXPR, type,
-                                                  fold_convert (type, parg1),
-                                                  fold_convert (type, marg))),
-                                    fold_convert (type, parg0)));
+                                    fold_convert (type, parg0),
+                                    fold (build2 (pcode, type,
+                                                  fold_convert (type, marg),
+                                                  fold_convert (type,
+                                                                parg1)))));
            }
 
          if (TREE_CODE (arg0) == MULT_EXPR && TREE_CODE (arg1) == MULT_EXPR)
@@ -6601,9 +6860,28 @@ fold (tree expr)
              if (same)
                return fold (build2 (MULT_EXPR, type,
                                     fold (build2 (PLUS_EXPR, type,
-                                                  alt0, alt1)),
+                                                  fold_convert (type, alt0),
+                                                  fold_convert (type, alt1))),
                                     same));
            }
+
+         /* 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.  */
+         if (TREE_CODE (arg0) == ADDR_EXPR
+             && TREE_CODE (arg1) == MULT_EXPR)
+           {
+             tem = try_move_mult_to_index (type, PLUS_EXPR, arg0, arg1);
+             if (tem)
+               return fold (tem);
+           }
+         else if (TREE_CODE (arg1) == ADDR_EXPR
+                  && TREE_CODE (arg0) == MULT_EXPR)
+           {
+             tem = try_move_mult_to_index (type, PLUS_EXPR, arg1, arg0);
+             if (tem)
+               return fold (tem);
+           }
        }
       else
        {
@@ -6682,7 +6960,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)
@@ -6697,7 +6975,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)
@@ -6969,17 +7247,26 @@ fold (tree expr)
       {
        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))
+       if ((TREE_CODE (arg0) == ADDR_EXPR
+            || TREE_CODE (arg1) == ADDR_EXPR)
+           && ptr_difference_const (arg0, arg1, &diff))
          return build_int_cst_type (type, diff);
       }
+         
+      /* 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.  */
+      if (TREE_CODE (arg0) == ADDR_EXPR
+         && TREE_CODE (arg1) == MULT_EXPR)
+       {
+         tem = try_move_mult_to_index (type, MINUS_EXPR, arg0, arg1);
+         if (tem)
+           return fold (tem);
+       }
 
       if (TREE_CODE (arg0) == MULT_EXPR
          && TREE_CODE (arg1) == MULT_EXPR
-         && (INTEGRAL_TYPE_P (type) || flag_unsafe_math_optimizations))
+         && (!FLOAT_TYPE_P (type) || flag_unsafe_math_optimizations))
        {
           /* (A * C) - (B * C) -> (A-B) * C.  */
          if (operand_equal_p (TREE_OPERAND (arg0, 1),
@@ -7779,6 +8066,22 @@ fold (tree expr)
          && operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
        return omit_one_operand (type, integer_zero_node, arg0);
 
+      /* A < X && A + 1 > Y ==> A < X && A >= Y.  Normally A + 1 > Y
+        means A >= Y && A != MAX, but in this case we know that
+        A < X <= MAX.  */
+
+      if (!TREE_SIDE_EFFECTS (arg0)
+         && !TREE_SIDE_EFFECTS (arg1))
+       {
+         tem = fold_to_nonsharp_ineq_using_bound (arg0, arg1);
+         if (tem)
+           return fold (build2 (code, type, tem, arg1));
+
+         tem = fold_to_nonsharp_ineq_using_bound (arg1, arg0);
+         if (tem)
+           return fold (build2 (code, type, arg0, tem));
+       }
+
     truth_andor:
       /* We only do these simplifications if we are optimizing.  */
       if (!optimize)
@@ -8129,9 +8432,8 @@ fold (tree expr)
       /* Comparisons with the highest or lowest possible integer of
         the specified size will have known values.
 
-        This is quite similar to fold_relational_hi_lo; however, my
-        attempts to share the code have been nothing but trouble.
-        I give up for now.  */
+        This is quite similar to fold_relational_hi_lo, however,
+        attempts to share the code have been nothing but trouble.  */
       {
        int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
 
@@ -8278,22 +8580,21 @@ fold (tree expr)
        return fold (build2 (code, type,
                             TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)));
 
-      /* If we are widening one operand of an integer comparison,
-        see if the other operand is similarly being widened.  Perhaps we
-        can do the comparison in the narrower type.  */
       else if (TREE_CODE (TREE_TYPE (arg0)) == INTEGER_TYPE
-              && TREE_CODE (arg0) == NOP_EXPR
-              && (tem = get_unwidened (arg0, NULL_TREE)) != arg0
-              && (code == EQ_EXPR || code == NE_EXPR
-                  || TYPE_UNSIGNED (TREE_TYPE (arg0))
-                     == TYPE_UNSIGNED (TREE_TYPE (tem)))
-              && (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)));
+              && TREE_CODE (arg0) == NOP_EXPR)
+       {
+         /* If we are widening one operand of an integer comparison,
+            see if the other operand is similarly being widened.  Perhaps we
+            can do the comparison in the narrower type.  */
+         tem = fold_widened_comparison (code, type, arg0, arg1);
+         if (tem)
+           return tem;
+
+         /* Or if we are changing signedness.  */
+         tem = fold_sign_changed_comparison (code, type, arg0, arg1);
+         if (tem)
+           return tem;
+       }
 
       /* If this is comparing a constant with a MIN_EXPR or a MAX_EXPR of a
         constant, we can simplify it.  */
@@ -8405,11 +8706,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);
@@ -8422,10 +8723,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);
@@ -9121,7 +9421,7 @@ fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
     case tcc_unary:
     case tcc_binary:
     case tcc_statement:
-      len = first_rtl_op (code);
+      len = TREE_CODE_LENGTH (code);
       for (i = 0; i < len; ++i)
        fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
       break;
@@ -9565,7 +9865,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)
@@ -9810,11 +10110,10 @@ fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p,
                            fold_convert (st0, op0),
                            fold_convert (st1, integer_zero_node));
 
-             retval
-               = nondestructive_fold_binary_to_constant (TREE_CODE (exp),
-                                                         TREE_TYPE (exp),
-                                                         TREE_OPERAND (exp, 0),
-                                                         TREE_OPERAND (exp, 1));
+             retval = fold_binary_to_constant (TREE_CODE (exp),
+                                               TREE_TYPE (exp),
+                                               TREE_OPERAND (exp, 0),
+                                               TREE_OPERAND (exp, 1));
 
              /* If we are in gimple form, then returning EXP would create
                 non-gimple expressions.  Clearing it is safe and insures
@@ -9845,8 +10144,7 @@ fold_relational_hi_lo (enum tree_code *code_p, const tree type, tree *op0_p,
    simpler than the generic fold routine.  */
 
 tree
-nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
-                                       tree op0, tree op1)
+fold_binary_to_constant (enum tree_code code, tree type, tree op0, tree op1)
 {
   int wins = 1;
   tree subop0;
@@ -10140,8 +10438,7 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
    the generic fold routine.  */
 
 tree
-nondestructive_fold_unary_to_constant (enum tree_code code, tree type,
-                                      tree op0)
+fold_unary_to_constant (enum tree_code code, tree type, tree op0)
 {
   /* Make sure we have a suitable constant argument.  */
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
@@ -10284,7 +10581,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;
@@ -10292,7 +10589,7 @@ fold_negate_const (tree arg0, tree type)
     default:
       gcc_unreachable ();
     }
-  
+
   return t;
 }
 
@@ -10330,18 +10627,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;
 }
 
@@ -10354,13 +10651,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;
 }
 
@@ -10468,6 +10765,21 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
   return constant_boolean_node (result, type);
 }
 
+/* Build an expression for the a clean point containing EXPR with type TYPE.
+   Don't build a cleanup point expression for EXPR which don't have side
+   effects.  */
+
+tree
+fold_build_cleanup_point_expr (tree type, tree expr)
+{
+  /* If the expression does not have side effects then we don't have to wrap
+     it with a cleanup point expression.  */
+  if (!TREE_SIDE_EFFECTS (expr))
+    return expr;
+  
+  return build1 (CLEANUP_POINT_EXPR, type, expr);
+}
+
 /* Build an expression for the address of T.  Folds away INDIRECT_REF to
    avoid confusing the gimplify process.  */
 
@@ -10478,7 +10790,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)
@@ -10488,9 +10802,7 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
     {
       tree base = t;
 
-      while (handled_component_p (base)
-            || TREE_CODE (base) == REALPART_EXPR
-            || TREE_CODE (base) == IMAGPART_EXPR)
+      while (handled_component_p (base))
        base = TREE_OPERAND (base, 0);
       if (DECL_P (base))
        TREE_ADDRESSABLE (base) = 1;
@@ -10624,7 +10936,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);
@@ -10668,7 +10980,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);
     }
@@ -10683,23 +10995,49 @@ round_down (tree value, int divisor)
   return value;
 }
 
+/* Returns the pointer to the base of the object addressed by EXP and
+   extracts the information about the offset of the access, storing it
+   to PBITPOS and POFFSET.  */
+
+static tree
+split_address_to_core_and_offset (tree exp,
+                                 HOST_WIDE_INT *pbitpos, tree *poffset)
+{
+  tree core;
+  enum machine_mode mode;
+  int unsignedp, volatilep;
+  HOST_WIDE_INT bitsize;
+
+  if (TREE_CODE (exp) == ADDR_EXPR)
+    {
+      core = get_inner_reference (TREE_OPERAND (exp, 0), &bitsize, pbitpos,
+                                 poffset, &mode, &unsignedp, &volatilep);
+
+      if (TREE_CODE (core) == INDIRECT_REF)
+       core = TREE_OPERAND (core, 0);
+    }
+  else
+    {
+      core = exp;
+      *pbitpos = 0;
+      *poffset = NULL_TREE;
+    }
+
+  return core;
+}
+
 /* Returns true if addresses of E1 and E2 differ by a constant, false
-   otherwise.  If they do, &E1 - &E2 is stored in *DIFF.  */
+   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);
+
+  core1 = split_address_to_core_and_offset (e1, &bitpos1, &toffset1);
+  core2 = split_address_to_core_and_offset (e2, &bitpos2, &toffset2);
 
   if (bitpos1 % BITS_PER_UNIT != 0
       || bitpos2 % BITS_PER_UNIT != 0