]> gcc.gnu.org Git - gcc.git/commitdiff
re PR tree-optimization/48571 (Missed data-dependence for (bogus?) reconstructed...
authorRichard Guenther <rguenther@suse.de>
Tue, 30 Aug 2011 14:06:00 +0000 (14:06 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 30 Aug 2011 14:06:00 +0000 (14:06 +0000)
2011-08-30  Richard Guenther  <rguenther@suse.de>

PR middle-end/48571
* gimple.h (maybe_fold_offset_to_address): Remove.
(maybe_fold_offset_to_reference): Likewise.
(maybe_fold_stmt_addition): Likewise.
(may_propagate_address_into_dereference): Likewise.
* tree-inline.c (remap_gimple_op_r): Do not reconstruct
array references.
* gimple-fold.c (canonicalize_constructor_val): Likewise.
Canonicalize invariant POINTER_PLUS_EXPRs to invariant MEM_REF
addresses instead.
(may_propagate_address_into_dereference): Remove.
(maybe_fold_offset_to_array_ref): Likewise.
(maybe_fold_offset_to_reference): Likewise.
(maybe_fold_offset_to_address): Likewise.
(maybe_fold_stmt_addition): Likewise.
(fold_gimple_assign): Do not reconstruct array references but
instead canonicalize invariant POINTER_PLUS_EXPRs to invariant
MEM_REF addresses.
(gimple_fold_stmt_to_constant_1): Likewise.
* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Likewise.
* gimplify.c (gimplify_conversion): Likewise.
(gimplify_expr): Likewise.

* gcc.c-torture/execute/pr48571-1.c: New testcase.
* gcc.dg/tree-ssa/ssa-ccp-25.c: Remove.
* gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise.
* gcc.dg/pr36902.c: XFAIL.

From-SVN: r178312

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple.h
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr48571-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr36902.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c [deleted file]
gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c [deleted file]
gcc/tree-inline.c
gcc/tree-ssa-forwprop.c

index 03db902f3cdcfb2cf3d243603479eebba59a9741..0313a8400cbe59f220dce4da9d0a767e0381449c 100644 (file)
@@ -1,3 +1,28 @@
+2011-08-30  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/48571
+       * gimple.h (maybe_fold_offset_to_address): Remove.
+       (maybe_fold_offset_to_reference): Likewise.
+       (maybe_fold_stmt_addition): Likewise.
+       (may_propagate_address_into_dereference): Likewise.
+       * tree-inline.c (remap_gimple_op_r): Do not reconstruct
+       array references.
+       * gimple-fold.c (canonicalize_constructor_val): Likewise.
+       Canonicalize invariant POINTER_PLUS_EXPRs to invariant MEM_REF
+       addresses instead.
+       (may_propagate_address_into_dereference): Remove.
+       (maybe_fold_offset_to_array_ref): Likewise.
+       (maybe_fold_offset_to_reference): Likewise.
+       (maybe_fold_offset_to_address): Likewise.
+       (maybe_fold_stmt_addition): Likewise.
+       (fold_gimple_assign): Do not reconstruct array references but
+       instead canonicalize invariant POINTER_PLUS_EXPRs to invariant
+       MEM_REF addresses.
+       (gimple_fold_stmt_to_constant_1): Likewise.
+       * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Likewise.
+       * gimplify.c (gimplify_conversion): Likewise.
+       (gimplify_expr): Likewise.
+
 2011-08-30  Ilya Tocar  <ilya.tocar@intel.com>
 
        * config/i386/fmaintrin.h: New.
index 19f34000654d6ce911370cef819f2f1bfef33583..72dc42a5bdc9f410e033f3c5fb06753d458a1038 100644 (file)
@@ -116,14 +116,17 @@ tree
 canonicalize_constructor_val (tree cval)
 {
   STRIP_NOPS (cval);
-  if (TREE_CODE (cval) == POINTER_PLUS_EXPR)
-    {
-      tree t = maybe_fold_offset_to_address (EXPR_LOCATION (cval),
-                                            TREE_OPERAND (cval, 0),
-                                            TREE_OPERAND (cval, 1),
-                                            TREE_TYPE (cval));
-      if (t)
-       cval = t;
+  if (TREE_CODE (cval) == POINTER_PLUS_EXPR
+      && TREE_CODE (TREE_OPERAND (cval, 1)) == INTEGER_CST)
+    {
+      tree ptr = TREE_OPERAND (cval, 0);
+      if (is_gimple_min_invariant (ptr))
+       cval = build1_loc (EXPR_LOCATION (cval),
+                          ADDR_EXPR, TREE_TYPE (ptr),
+                          fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (ptr)),
+                                       ptr,
+                                       fold_convert (ptr_type_node,
+                                                     TREE_OPERAND (cval, 1))));
     }
   if (TREE_CODE (cval) == ADDR_EXPR)
     {
@@ -173,384 +176,6 @@ get_symbol_constant_value (tree sym)
 }
 
 
-/* Return true if we may propagate the address expression ADDR into the
-   dereference DEREF and cancel them.  */
-
-bool
-may_propagate_address_into_dereference (tree addr, tree deref)
-{
-  gcc_assert (TREE_CODE (deref) == MEM_REF
-             && TREE_CODE (addr) == ADDR_EXPR);
-
-  /* Don't propagate if ADDR's operand has incomplete type.  */
-  if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_OPERAND (addr, 0))))
-    return false;
-
-  /* If the address is invariant then we do not need to preserve restrict
-     qualifications.  But we do need to preserve volatile qualifiers until
-     we can annotate the folded dereference itself properly.  */
-  if (is_gimple_min_invariant (addr)
-      && (!TREE_THIS_VOLATILE (deref)
-         || TYPE_VOLATILE (TREE_TYPE (addr))))
-    return useless_type_conversion_p (TREE_TYPE (deref),
-                                     TREE_TYPE (TREE_OPERAND (addr, 0)));
-
-  /* Else both the address substitution and the folding must result in
-     a valid useless type conversion sequence.  */
-  return (useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (deref, 0)),
-                                    TREE_TYPE (addr))
-         && useless_type_conversion_p (TREE_TYPE (deref),
-                                       TREE_TYPE (TREE_OPERAND (addr, 0))));
-}
-
-
-/* A subroutine of fold_stmt.  Attempts to fold *(A+O) to A[X].
-   BASE is an array type.  OFFSET is a byte displacement.
-
-   LOC is the location of the original expression.  */
-
-static tree
-maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset)
-{
-  tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
-  tree array_type, elt_type, elt_size;
-  tree domain_type;
-
-  /* If BASE is an ARRAY_REF, we can pick up another offset (this time
-     measured in units of the size of elements type) from that ARRAY_REF).
-     We can't do anything if either is variable.
-
-     The case we handle here is *(&A[N]+O).  */
-  if (TREE_CODE (base) == ARRAY_REF)
-    {
-      tree low_bound = array_ref_low_bound (base);
-
-      elt_offset = TREE_OPERAND (base, 1);
-      if (TREE_CODE (low_bound) != INTEGER_CST
-         || TREE_CODE (elt_offset) != INTEGER_CST)
-       return NULL_TREE;
-
-      elt_offset = int_const_binop (MINUS_EXPR, elt_offset, low_bound);
-      base = TREE_OPERAND (base, 0);
-    }
-
-  /* Ignore stupid user tricks of indexing non-array variables.  */
-  array_type = TREE_TYPE (base);
-  if (TREE_CODE (array_type) != ARRAY_TYPE)
-    return NULL_TREE;
-  elt_type = TREE_TYPE (array_type);
-
-  /* Use signed size type for intermediate computation on the index.  */
-  idx_type = ssizetype;
-
-  /* If OFFSET and ELT_OFFSET are zero, we don't care about the size of the
-     element type (so we can use the alignment if it's not constant).
-     Otherwise, compute the offset as an index by using a division.  If the
-     division isn't exact, then don't do anything.  */
-  elt_size = TYPE_SIZE_UNIT (elt_type);
-  if (!elt_size)
-    return NULL;
-  if (integer_zerop (offset))
-    {
-      if (TREE_CODE (elt_size) != INTEGER_CST)
-       elt_size = size_int (TYPE_ALIGN (elt_type));
-
-      idx = build_int_cst (idx_type, 0);
-    }
-  else
-    {
-      unsigned HOST_WIDE_INT lquo, lrem;
-      HOST_WIDE_INT hquo, hrem;
-      double_int soffset;
-
-      /* The final array offset should be signed, so we need
-        to sign-extend the (possibly pointer) offset here
-        and use signed division.  */
-      soffset = double_int_sext (tree_to_double_int (offset),
-                                TYPE_PRECISION (TREE_TYPE (offset)));
-      if (TREE_CODE (elt_size) != INTEGER_CST
-         || div_and_round_double (TRUNC_DIV_EXPR, 0,
-                                  soffset.low, soffset.high,
-                                  TREE_INT_CST_LOW (elt_size),
-                                  TREE_INT_CST_HIGH (elt_size),
-                                  &lquo, &hquo, &lrem, &hrem)
-         || lrem || hrem)
-       return NULL_TREE;
-
-      idx = build_int_cst_wide (idx_type, lquo, hquo);
-    }
-
-  /* Assume the low bound is zero.  If there is a domain type, get the
-     low bound, if any, convert the index into that type, and add the
-     low bound.  */
-  min_idx = build_int_cst (idx_type, 0);
-  domain_type = TYPE_DOMAIN (array_type);
-  if (domain_type)
-    {
-      idx_type = domain_type;
-      if (TYPE_MIN_VALUE (idx_type))
-       min_idx = TYPE_MIN_VALUE (idx_type);
-      else
-       min_idx = fold_convert (idx_type, min_idx);
-
-      if (TREE_CODE (min_idx) != INTEGER_CST)
-       return NULL_TREE;
-
-      elt_offset = fold_convert (idx_type, elt_offset);
-    }
-
-  if (!integer_zerop (min_idx))
-    idx = int_const_binop (PLUS_EXPR, idx, min_idx);
-  if (!integer_zerop (elt_offset))
-    idx = int_const_binop (PLUS_EXPR, idx, elt_offset);
-
-  /* Make sure to possibly truncate late after offsetting.  */
-  idx = fold_convert (idx_type, idx);
-
-  /* We don't want to construct access past array bounds. For example
-       char *(c[4]);
-       c[3][2];
-     should not be simplified into (*c)[14] or tree-vrp will
-     give false warnings.
-     This is only an issue for multi-dimensional arrays.  */
-  if (TREE_CODE (elt_type) == ARRAY_TYPE
-      && domain_type)
-    {
-      if (TYPE_MAX_VALUE (domain_type)
-         && TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST
-         && tree_int_cst_lt (TYPE_MAX_VALUE (domain_type), idx))
-       return NULL_TREE;
-      else if (TYPE_MIN_VALUE (domain_type)
-              && TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST
-              && tree_int_cst_lt (idx, TYPE_MIN_VALUE (domain_type)))
-       return NULL_TREE;
-      else if (compare_tree_int (idx, 0) < 0)
-       return NULL_TREE;
-    }
-
-  {
-    tree t = build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
-    SET_EXPR_LOCATION (t, loc);
-    return t;
-  }
-}
-
-
-/* Attempt to express (ORIG_TYPE)BASE+OFFSET as BASE[index].
-   LOC is the location of original expression.
-
-   Before attempting the conversion strip off existing ADDR_EXPRs.  */
-
-tree
-maybe_fold_offset_to_reference (location_t loc, tree base, tree offset,
-                               tree orig_type)
-{
-  tree ret;
-
-  STRIP_NOPS (base);
-  if (TREE_CODE (base) != ADDR_EXPR)
-    return NULL_TREE;
-
-  base = TREE_OPERAND (base, 0);
-  if (types_compatible_p (orig_type, TREE_TYPE (base))
-      && integer_zerop (offset))
-    return base;
-
-  ret = maybe_fold_offset_to_array_ref (loc, base, offset);
-  if (ret && types_compatible_p (orig_type, TREE_TYPE (ret)))
-    return ret;
-  return NULL_TREE;
-}
-
-/* Attempt to express (ORIG_TYPE)ADDR+OFFSET as (*ADDR)[index].
-   LOC is the location of the original expression.  */
-
-tree
-maybe_fold_offset_to_address (location_t loc, tree addr, tree offset,
-                             tree orig_type)
-{
-  tree base, ret;
-
-  STRIP_NOPS (addr);
-  if (TREE_CODE (addr) != ADDR_EXPR)
-    return NULL_TREE;
-  base = TREE_OPERAND (addr, 0);
-  ret = maybe_fold_offset_to_array_ref (loc, base, offset);
-  if (ret)
-    {
-      ret = build_fold_addr_expr (ret);
-      if (!useless_type_conversion_p (orig_type, TREE_TYPE (ret)))
-       return NULL_TREE;
-      SET_EXPR_LOCATION (ret, loc);
-    }
-
-  return ret;
-}
-
-
-/* A quaint feature extant in our address arithmetic is that there
-   can be hidden type changes here.  The type of the result need
-   not be the same as the type of the input pointer.
-
-   What we're after here is an expression of the form
-       (T *)(&array + const)
-   where array is OP0, const is OP1, RES_TYPE is T and
-   the cast doesn't actually exist, but is implicit in the
-   type of the POINTER_PLUS_EXPR.  We'd like to turn this into
-       &array[x]
-   which may be able to propagate further.  */
-
-tree
-maybe_fold_stmt_addition (location_t loc, tree res_type, tree op0, tree op1)
-{
-  tree ptd_type;
-  tree t;
-
-  /* The first operand should be an ADDR_EXPR.  */
-  if (TREE_CODE (op0) != ADDR_EXPR)
-    return NULL_TREE;
-  op0 = TREE_OPERAND (op0, 0);
-
-  /* It had better be a constant.  */
-  if (TREE_CODE (op1) != INTEGER_CST)
-    {
-      /* Or op0 should now be A[0] and the non-constant offset defined
-        via a multiplication by the array element size.  */
-      if (TREE_CODE (op0) == ARRAY_REF
-         /* As we will end up creating a variable index array access
-            in the outermost array dimension make sure there isn't
-            a more inner array that the index could overflow to.  */
-         && TREE_CODE (TREE_OPERAND (op0, 0)) != ARRAY_REF
-         && integer_zerop (TREE_OPERAND (op0, 1))
-         && TREE_CODE (op1) == SSA_NAME)
-       {
-         gimple offset_def = SSA_NAME_DEF_STMT (op1);
-         tree elsz = TYPE_SIZE_UNIT (TREE_TYPE (op0));
-         if (!host_integerp (elsz, 1)
-             || !is_gimple_assign (offset_def))
-           return NULL_TREE;
-
-         /* Do not build array references of something that we can't
-            see the true number of array dimensions for.  */
-         if (!DECL_P (TREE_OPERAND (op0, 0))
-             && !handled_component_p (TREE_OPERAND (op0, 0)))
-           return NULL_TREE;
-
-         if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
-             && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
-             && tree_int_cst_equal (gimple_assign_rhs2 (offset_def), elsz))
-           return build_fold_addr_expr
-                         (build4 (ARRAY_REF, TREE_TYPE (op0),
-                                  TREE_OPERAND (op0, 0),
-                                  gimple_assign_rhs1 (offset_def),
-                                  TREE_OPERAND (op0, 2),
-                                  TREE_OPERAND (op0, 3)));
-         else if (integer_onep (elsz)
-                  && gimple_assign_rhs_code (offset_def) != MULT_EXPR)
-           return build_fold_addr_expr
-                         (build4 (ARRAY_REF, TREE_TYPE (op0),
-                                  TREE_OPERAND (op0, 0),
-                                  op1,
-                                  TREE_OPERAND (op0, 2),
-                                  TREE_OPERAND (op0, 3)));
-       }
-      else if (TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
-              /* Dto.  */
-              && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) != ARRAY_TYPE
-              && TREE_CODE (op1) == SSA_NAME)
-       {
-         gimple offset_def = SSA_NAME_DEF_STMT (op1);
-         tree elsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (op0)));
-         if (!host_integerp (elsz, 1)
-             || !is_gimple_assign (offset_def))
-           return NULL_TREE;
-
-         /* Do not build array references of something that we can't
-            see the true number of array dimensions for.  */
-         if (!DECL_P (op0)
-             && !handled_component_p (op0))
-           return NULL_TREE;
-
-         if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
-             && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
-             && tree_int_cst_equal (gimple_assign_rhs2 (offset_def), elsz))
-           return build_fold_addr_expr
-                         (build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (op0)),
-                                  op0, gimple_assign_rhs1 (offset_def),
-                                  integer_zero_node, NULL_TREE));
-         else if (integer_onep (elsz)
-                  && gimple_assign_rhs_code (offset_def) != MULT_EXPR)
-           return build_fold_addr_expr
-                         (build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (op0)),
-                                  op0, op1,
-                                  integer_zero_node, NULL_TREE));
-       }
-
-      return NULL_TREE;
-    }
-
-  /* If the first operand is an ARRAY_REF, expand it so that we can fold
-     the offset into it.  */
-  while (TREE_CODE (op0) == ARRAY_REF)
-    {
-      tree array_obj = TREE_OPERAND (op0, 0);
-      tree array_idx = TREE_OPERAND (op0, 1);
-      tree elt_type = TREE_TYPE (op0);
-      tree elt_size = TYPE_SIZE_UNIT (elt_type);
-      tree min_idx;
-
-      if (TREE_CODE (array_idx) != INTEGER_CST)
-       break;
-      if (TREE_CODE (elt_size) != INTEGER_CST)
-       break;
-
-      /* Un-bias the index by the min index of the array type.  */
-      min_idx = TYPE_DOMAIN (TREE_TYPE (array_obj));
-      if (min_idx)
-       {
-         min_idx = TYPE_MIN_VALUE (min_idx);
-         if (min_idx)
-           {
-             if (TREE_CODE (min_idx) != INTEGER_CST)
-               break;
-
-             array_idx = fold_convert (TREE_TYPE (min_idx), array_idx);
-             if (!integer_zerop (min_idx))
-               array_idx = int_const_binop (MINUS_EXPR, array_idx,
-                                            min_idx);
-           }
-       }
-
-      /* Convert the index to a byte offset.  */
-      array_idx = fold_convert (sizetype, array_idx);
-      array_idx = int_const_binop (MULT_EXPR, array_idx, elt_size);
-
-      /* Update the operands for the next round, or for folding.  */
-      op1 = int_const_binop (PLUS_EXPR,
-                            array_idx, op1);
-      op0 = array_obj;
-    }
-
-  ptd_type = TREE_TYPE (res_type);
-  /* If we want a pointer to void, reconstruct the reference from the
-     array element type.  A pointer to that can be trivially converted
-     to void *.  This happens as we fold (void *)(ptr p+ off).  */
-  if (VOID_TYPE_P (ptd_type)
-      && TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE)
-    ptd_type = TREE_TYPE (TREE_TYPE (op0));
-
-  /* At which point we can try some of the same things as for indirects.  */
-  t = maybe_fold_offset_to_array_ref (loc, op0, op1);
-  if (t)
-    {
-      t = build_fold_addr_expr (t);
-      if (!useless_type_conversion_p (res_type, TREE_TYPE (t)))
-       return NULL_TREE;
-      SET_EXPR_LOCATION (t, loc);
-    }
-
-  return t;
-}
 
 /* Subroutine of fold_stmt.  We perform several simplifications of the
    memory reference tree EXPR and make sure to re-gimplify them properly
@@ -783,41 +408,14 @@ fold_gimple_assign (gimple_stmt_iterator *si)
            if (valid_gimple_rhs_p (result))
              return result;
          }
-       else if (CONVERT_EXPR_CODE_P (subcode)
-                && POINTER_TYPE_P (gimple_expr_type (stmt))
-                && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
-         {
-           tree type = gimple_expr_type (stmt);
-           tree t = maybe_fold_offset_to_address (loc,
-                                                  gimple_assign_rhs1 (stmt),
-                                                  integer_zero_node, type);
-           if (t)
-             return t;
-         }
       }
       break;
 
     case GIMPLE_BINARY_RHS:
-      /* Try to fold pointer addition.  */
-      if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
-       {
-         tree type = TREE_TYPE (gimple_assign_rhs1 (stmt));
-         if (TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
-           {
-             type = build_pointer_type (TREE_TYPE (TREE_TYPE (type)));
-             if (!useless_type_conversion_p
-                   (TREE_TYPE (gimple_assign_lhs (stmt)), type))
-               type = TREE_TYPE (gimple_assign_rhs1 (stmt));
-           }
-         result = maybe_fold_stmt_addition (gimple_location (stmt),
-                                            type,
-                                            gimple_assign_rhs1 (stmt),
-                                            gimple_assign_rhs2 (stmt));
-       }
       /* Try to canonicalize for boolean-typed X the comparisons
         X == 0, X == 1, X != 0, and X != 1.  */
-      else if (gimple_assign_rhs_code (stmt) == EQ_EXPR
-               || gimple_assign_rhs_code (stmt) == NE_EXPR)
+      if (gimple_assign_rhs_code (stmt) == EQ_EXPR
+         || gimple_assign_rhs_code (stmt) == NE_EXPR)
         {
          tree lhs = gimple_assign_lhs (stmt);
          tree op1 = gimple_assign_rhs1 (stmt);
@@ -2945,29 +2543,20 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree))
               /* Handle unary operators that can appear in GIMPLE form.
                  Note that we know the single operand must be a constant,
                  so this should almost always return a simplified RHS.  */
-              tree lhs = gimple_assign_lhs (stmt);
+             tree lhs = gimple_assign_lhs (stmt);
               tree op0 = (*valueize) (gimple_assign_rhs1 (stmt));
 
              /* Conversions are useless for CCP purposes if they are
                 value-preserving.  Thus the restrictions that
-                useless_type_conversion_p places for pointer type conversions
-                do not apply here.  Substitution later will only substitute to
-                allowed places.  */
+                useless_type_conversion_p places for restrict qualification
+                of pointer types should not apply here.
+                Substitution later will only substitute to allowed places.  */
              if (CONVERT_EXPR_CODE_P (subcode)
                  && POINTER_TYPE_P (TREE_TYPE (lhs))
-                 && POINTER_TYPE_P (TREE_TYPE (op0)))
-               {
-                 tree tem;
-                 /* Try to re-construct array references on-the-fly.  */
-                 if (!useless_type_conversion_p (TREE_TYPE (lhs),
-                                                 TREE_TYPE (op0))
-                     && ((tem = maybe_fold_offset_to_address
-                          (loc,
-                           op0, integer_zero_node, TREE_TYPE (lhs)))
-                         != NULL_TREE))
-                   return tem;
-                 return op0;
-               }
+                 && POINTER_TYPE_P (TREE_TYPE (op0))
+                 && (TYPE_ADDR_SPACE (TREE_TYPE (lhs))
+                     == TYPE_ADDR_SPACE (TREE_TYPE (op0))))
+               return op0;
 
               return
                fold_unary_ignore_overflow_loc (loc, subcode,
index 27b20482876acf9455abede717b4865cbcad3a8e..7f831dffcaf042b7858b1f8180e36cac293ee736 100644 (file)
@@ -5069,12 +5069,8 @@ void gimplify_and_update_call_from_tree (gimple_stmt_iterator *, tree);
 tree gimple_fold_builtin (gimple);
 bool fold_stmt (gimple_stmt_iterator *);
 bool fold_stmt_inplace (gimple);
-tree maybe_fold_offset_to_address (location_t, tree, tree, tree);
-tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
-tree maybe_fold_stmt_addition (location_t, tree, tree, tree);
 tree get_symbol_constant_value (tree);
 tree canonicalize_constructor_val (tree);
-bool may_propagate_address_into_dereference (tree, tree);
 extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, 
                                        enum tree_code, tree, tree);
 extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,
index a22b5d3121f6057a96fbaa2a0684105e1e540b1f..d7bc818dfb98701f295d6e036defb8e46f6214f3 100644 (file)
@@ -1799,7 +1799,6 @@ canonicalize_addr_expr (tree *expr_p)
 static enum gimplify_status
 gimplify_conversion (tree *expr_p)
 {
-  tree tem;
   location_t loc = EXPR_LOCATION (*expr_p);
   gcc_assert (CONVERT_EXPR_P (*expr_p));
 
@@ -1810,17 +1809,6 @@ gimplify_conversion (tree *expr_p)
   if (tree_ssa_useless_type_conversion (*expr_p))
     *expr_p = TREE_OPERAND (*expr_p, 0);
 
-  /* Attempt to avoid NOP_EXPR by producing reference to a subtype.
-     For example this fold (subclass *)&A into &A->subclass avoiding
-     a need for statement.  */
-  if (CONVERT_EXPR_P (*expr_p)
-      && POINTER_TYPE_P (TREE_TYPE (*expr_p))
-      && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))
-      && (tem = maybe_fold_offset_to_address
-         (EXPR_LOCATION (*expr_p), TREE_OPERAND (*expr_p, 0),
-          integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE)
-    *expr_p = tem;
-
   /* If we still have a conversion at the toplevel,
      then canonicalize some constructs.  */
   if (CONVERT_EXPR_P (*expr_p))
@@ -7302,36 +7290,33 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          goto expr_3;
 
        case POINTER_PLUS_EXPR:
-          /* Convert ((type *)A)+offset into &A->field_of_type_and_offset.
-            The second is gimple immediate saving a need for extra statement.
-          */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (*expr_p))))
-           {
-             *expr_p = tmp;
-             ret = GS_OK;
-             break;
-           }
-         /* Convert (void *)&a + 4 into (void *)&a[1].  */
-         if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR
-             && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
-             && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p,
-                                                                       0),0)))
-             && (tmp = maybe_fold_offset_to_address
-                 (EXPR_LOCATION (*expr_p),
-                  TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0),
-                  TREE_OPERAND (*expr_p, 1),
-                  TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),
-                                           0)))))
-            {
-               *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp);
-              ret = GS_OK;
-              break;
-            }
-          /* FALLTHRU */
+         {
+           enum gimplify_status r0, r1;
+           r0 = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           r1 = gimplify_expr (&TREE_OPERAND (*expr_p, 1), pre_p,
+                               post_p, is_gimple_val, fb_rvalue);
+           recalculate_side_effects (*expr_p);
+           ret = MIN (r0, r1);
+           /* Convert &X + CST to invariant &MEM[&X, CST].  Do this
+              after gimplifying operands - this is similar to how
+              it would be folding all gimplified stmts on creation
+              to have them canonicalized, which is what we eventually
+              should do anyway.  */
+           if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST
+               && is_gimple_min_invariant (TREE_OPERAND (*expr_p, 0)))
+             {
+               *expr_p = build_fold_addr_expr_with_type_loc
+                  (input_location,
+                   fold_build2 (MEM_REF, TREE_TYPE (TREE_TYPE (*expr_p)),
+                                TREE_OPERAND (*expr_p, 0),
+                                fold_convert (ptr_type_node,
+                                              TREE_OPERAND (*expr_p, 1))),
+                   TREE_TYPE (*expr_p));
+               ret = MIN (ret, GS_OK);
+             }
+           break;
+         }
 
        default:
          switch (TREE_CODE_CLASS (TREE_CODE (*expr_p)))
index 55d74a9dddfa01acb74e2c2e0b95462865baea3f..2449a63ac63b7a5205c09ed5e13573945313a69d 100644 (file)
@@ -1,3 +1,11 @@
+2011-08-30  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/48571
+       * gcc.c-torture/execute/pr48571-1.c: New testcase.
+       * gcc.dg/tree-ssa/ssa-ccp-25.c: Remove.
+       * gcc.dg/tree-ssa/ssa-ccp-26.c: Likewise.
+       * gcc.dg/pr36902.c: XFAIL.
+
 2011-08-30  Ilya Tocar <ilya.tocar@intel.com>
 
        * gcc.target/i386/fma-check.h: New.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr48571-1.c b/gcc/testsuite/gcc.c-torture/execute/pr48571-1.c
new file mode 100644 (file)
index 0000000..063058e
--- /dev/null
@@ -0,0 +1,28 @@
+unsigned int c[624];
+void __attribute__((noinline))
+bar (void)
+{
+  unsigned int i;
+  /* Obfuscated c[i] = c[i-1] * 2.  */
+  for (i = 1; i < 624; ++i)
+    *(unsigned int *)((void *)c + (__SIZE_TYPE__)i * 4)
+       = 2 * *(unsigned int *)((void *)c + ((__SIZE_TYPE__)i +
+                                            ((__SIZE_TYPE__)-4)/4) * 4);
+}
+extern void abort (void);
+int
+main()
+{
+  unsigned int i, j;
+  for (i = 0; i < 624; ++i)
+    c[i] = 1;
+  bar();
+  j = 1;
+  for (i = 0; i < 624; ++i)
+    {
+      if (c[i] != j)
+       abort ();
+      j = j * 2;
+    }
+  return 0;
+}
index 43a2d14f981f18ad252a806a4cda3bf69e28f786..a065124ae71642946ce0a61ad84c465f884914bb 100644 (file)
@@ -44,7 +44,7 @@ foo2(unsigned char * to, const unsigned char * from, int n)
       *to = *from;
       break;
     case 5:
-      to[4] = from [4]; /* { dg-warning "array subscript is above array bounds" } */
+      to[4] = from [4]; /* { dg-warning "array subscript is above array bounds" "" { xfail *-*-* } } */
       break;
     }
   return to;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c
deleted file mode 100644 (file)
index 7912a57..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-ccp1 -fdump-tree-forwprop1" } */
-
-int a[256];
-int foo(int i)
-{
-  int *p = &a[0];
-  return *(p + i);
-}
-
-/* { dg-final { scan-tree-dump "&a\\\[\[iD\]\\\." "ccp1" } } */
-/* { dg-final { scan-tree-dump "= .*&a\\\]\\\[\[iD\]\\\." "forwprop1" } } */
-/* { dg-final { cleanup-tree-dump "ccp1" } } */
-/* { dg-final { cleanup-tree-dump "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c
deleted file mode 100644 (file)
index c0a5481..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-forwprop1" } */
-
-int a[256];
-int foo(int i)
-{
-  return (a + 1)[i];
-}
-
-/* { dg-final { scan-tree-dump "=.*&a\\\]\\\[D\\\." "forwprop1" } } */
-/* { dg-final { cleanup-tree-dump "forwprop1" } } */
index e9daff63cc351045a3b9487cdc6fbd7fddc3acbb..741e8e4d005ccb6e86079849f24c5b8bee487b1e 100644 (file)
@@ -853,43 +853,14 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
          tree ptr = TREE_OPERAND (*tp, 0);
          tree type = remap_type (TREE_TYPE (*tp), id);
          tree old = *tp;
-         tree tem;
 
          /* We need to re-canonicalize MEM_REFs from inline substitutions
             that can happen when a pointer argument is an ADDR_EXPR.
             Recurse here manually to allow that.  */
          walk_tree (&ptr, remap_gimple_op_r, data, NULL);
-         if ((tem = maybe_fold_offset_to_reference (EXPR_LOCATION (*tp),
-                                                    ptr,
-                                                    TREE_OPERAND (*tp, 1),
-                                                    type))
-             && TREE_THIS_VOLATILE (tem) == TREE_THIS_VOLATILE (old))
-           {
-             tree *tem_basep = &tem;
-             while (handled_component_p (*tem_basep))
-               tem_basep = &TREE_OPERAND (*tem_basep, 0);
-             if (TREE_CODE (*tem_basep) == MEM_REF)
-               *tem_basep
-                   = build2 (MEM_REF, TREE_TYPE (*tem_basep),
-                             TREE_OPERAND (*tem_basep, 0),
-                             fold_convert (TREE_TYPE (TREE_OPERAND (*tp, 1)),
-                                           TREE_OPERAND (*tem_basep, 1)));
-             else
-               *tem_basep
-                   = build2 (MEM_REF, TREE_TYPE (*tem_basep),
-                             build_fold_addr_expr (*tem_basep),
-                             build_int_cst
-                             (TREE_TYPE (TREE_OPERAND (*tp, 1)), 0));
-             *tp = tem;
-             TREE_THIS_VOLATILE (*tem_basep) = TREE_THIS_VOLATILE (old);
-             TREE_THIS_NOTRAP (*tem_basep) = TREE_THIS_NOTRAP (old);
-           }
-         else
-           {
-             *tp = fold_build2 (MEM_REF, type,
-                                ptr, TREE_OPERAND (*tp, 1));
-             TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old);
-           }
+         *tp = fold_build2 (MEM_REF, type,
+                            ptr, TREE_OPERAND (*tp, 1));
+         TREE_THIS_NOTRAP (*tp) = TREE_THIS_NOTRAP (old);
          TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
          TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
          *walk_subtrees = 0;
index 00121796613c5d9841d08a847f306990b37e9519..7dd5e08ac6d14e77f168c7ac9671caaa4584f77c 100644 (file)
@@ -1002,31 +1002,21 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
     return false;
 
   rhs2 = gimple_assign_rhs2 (use_stmt);
-  /* Try to optimize &x[C1] p+ C2 where C2 is a multiple of the size
-     of the elements in X into &x[C1 + C2/element size].  */
+  /* Optimize &x[C1] p+ C2 to  &x p+ C3 with C3 = C1 * element_size + C2.  */
   if (TREE_CODE (rhs2) == INTEGER_CST)
     {
-      tree new_rhs = maybe_fold_stmt_addition (gimple_location (use_stmt),
-                                              TREE_TYPE (def_rhs),
-                                              def_rhs, rhs2);
-      if (new_rhs)
-       {
-         tree type = TREE_TYPE (gimple_assign_lhs (use_stmt));
-         new_rhs = unshare_expr (new_rhs);
-         if (!useless_type_conversion_p (type, TREE_TYPE (new_rhs)))
-           {
-             if (!is_gimple_min_invariant (new_rhs))
-               new_rhs = force_gimple_operand_gsi (use_stmt_gsi, new_rhs,
-                                                   true, NULL_TREE,
-                                                   true, GSI_SAME_STMT);
-             new_rhs = fold_convert (type, new_rhs);
-           }
-         gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs);
-         use_stmt = gsi_stmt (*use_stmt_gsi);
-         update_stmt (use_stmt);
-         tidy_after_forward_propagate_addr (use_stmt);
-         return true;
-       }
+      tree new_rhs = build1_loc (gimple_location (use_stmt),
+                                ADDR_EXPR, TREE_TYPE (def_rhs),
+                                fold_build2 (MEM_REF,
+                                             TREE_TYPE (TREE_TYPE (def_rhs)),
+                                             unshare_expr (def_rhs),
+                                             fold_convert (ptr_type_node,
+                                                           rhs2)));
+      gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs);
+      use_stmt = gsi_stmt (*use_stmt_gsi);
+      update_stmt (use_stmt);
+      tidy_after_forward_propagate_addr (use_stmt);
+      return true;
     }
 
   /* Try to optimize &x[0] p+ OFFSET where OFFSET is defined by
This page took 0.163228 seconds and 5 git commands to generate.