[PATCH][mem-ref2] Even more array-ref folding

Richard Guenther rguenther@suse.de
Sat Jun 19 21:27:00 GMT 2010


This fixes the remaining array-bounds and objsize fails by
relaxing the array-refs we can create from maybe_fold_offset_to_array_ref.
On the trunk we are doing the same foldings but via fold_binary
or via forwprop.  Thus this aligns the third copy of array-ref
folding (ugh) to what the others do.  Merging them is for
further excercising.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to
the branch.

No major show-stoppers remain.  IMHO the branch is ready to merge.

Richard.

2010-06-19  Richard Guenther  <rguenther@suse.de>

	* gimple-fold.c (maybe_fold_offset_to_array_ref): Allow
	possibly out-of bounds accesses if the array has just
	one dimension.  Remove always true parameter.
	(maybe_fold_offset_to_reference): Update caller.
	(maybe_fold_offset_to_address): Likewise.
	(maybe_fold_stmt_addition): Likewise.
	* tree-object-size.c (plus_stmt_object_size): Handle MEM_REF.
	(collect_object_sizes_for): Dispatch to plus_stmt_object_size
	for &MEM_REF.

Index: mem-ref2/gcc/gimple-fold.c
===================================================================
*** mem-ref2.orig/gcc/gimple-fold.c	2010-06-19 18:28:50.000000000 +0200
--- mem-ref2/gcc/gimple-fold.c	2010-06-19 18:28:55.000000000 +0200
*************** may_propagate_address_into_dereference (
*** 113,120 ****
     LOC is the location of the original expression.  */
  
  static tree
! maybe_fold_offset_to_array_ref (location_t loc, tree base, tree offset,
! 				bool allow_negative_idx)
  {
    tree min_idx, idx, idx_type, elt_offset = integer_zero_node;
    tree array_type, elt_type, elt_size;
--- 113,119 ----
     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;
*************** maybe_fold_offset_to_array_ref (location
*** 215,248 ****
         char *(c[4]);
         c[3][2];
       should not be simplified into (*c)[14] or tree-vrp will
!      give false warnings.  The same is true for
!        struct A { long x; char d[0]; } *a;
!        (char *)a - 4;
!      which should be not folded to &a->d[-8].  */
!   if (domain_type
!       && TYPE_MAX_VALUE (domain_type)
!       && TREE_CODE (TYPE_MAX_VALUE (domain_type)) == INTEGER_CST)
!     {
!       tree up_bound = TYPE_MAX_VALUE (domain_type);
! 
!       if (tree_int_cst_lt (up_bound, idx)
! 	  /* Accesses after the end of arrays of size 0 (gcc
! 	     extension) and 1 are likely intentional ("struct
! 	     hack").  */
! 	  && compare_tree_int (up_bound, 1) > 0)
  	return NULL_TREE;
!     }
!   if (domain_type
!       && TYPE_MIN_VALUE (domain_type))
!     {
!       if (!allow_negative_idx
! 	  && TREE_CODE (TYPE_MIN_VALUE (domain_type)) == INTEGER_CST
! 	  && tree_int_cst_lt (idx, TYPE_MIN_VALUE (domain_type)))
  	return NULL_TREE;
      }
-   else if (!allow_negative_idx
- 	   && compare_tree_int (idx, 0) < 0)
-     return NULL_TREE;
  
    {
      tree t = build4 (ARRAY_REF, elt_type, base, idx, NULL_TREE, NULL_TREE);
--- 214,235 ----
         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);
*************** maybe_fold_offset_to_reference (location
*** 272,278 ****
        && integer_zerop (offset))
      return base;
  
!   ret = maybe_fold_offset_to_array_ref (loc, base, offset, true);
    if (ret && useless_type_conversion_p (orig_type, TREE_TYPE (ret)))
      return ret;
    return NULL_TREE;
--- 259,265 ----
        && integer_zerop (offset))
      return base;
  
!   ret = maybe_fold_offset_to_array_ref (loc, base, offset);
    if (ret && useless_type_conversion_p (orig_type, TREE_TYPE (ret)))
      return ret;
    return NULL_TREE;
*************** maybe_fold_offset_to_address (location_t
*** 291,297 ****
    if (TREE_CODE (addr) != ADDR_EXPR)
      return NULL_TREE;
    base = TREE_OPERAND (addr, 0);
!   ret = maybe_fold_offset_to_array_ref (loc, base, offset, true);
    if (ret)
      {
        ret = build_fold_addr_expr (ret);
--- 278,284 ----
    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);
*************** maybe_fold_stmt_addition (location_t loc
*** 529,535 ****
      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, true);
    if (t)
      {
        t = build_fold_addr_expr (t);
--- 516,522 ----
      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);
Index: mem-ref2/gcc/tree-object-size.c
===================================================================
*** mem-ref2.orig/gcc/tree-object-size.c	2010-06-19 18:31:10.000000000 +0200
--- mem-ref2/gcc/tree-object-size.c	2010-06-19 18:31:12.000000000 +0200
*************** plus_stmt_object_size (struct object_siz
*** 762,771 ****
    unsigned HOST_WIDE_INT bytes;
    tree op0, op1;
  
!   gcc_assert (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR);
! 
!   op0 = gimple_assign_rhs1 (stmt);
!   op1 = gimple_assign_rhs2 (stmt);
  
    if (object_sizes[object_size_type][varno] == unknown[object_size_type])
      return false;
--- 762,781 ----
    unsigned HOST_WIDE_INT bytes;
    tree op0, op1;
  
!   if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
!     {
!       op0 = gimple_assign_rhs1 (stmt);
!       op1 = gimple_assign_rhs2 (stmt);
!     }
!   else if (gimple_assign_rhs_code (stmt) == ADDR_EXPR)
!     {
!       tree rhs = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
!       gcc_assert (TREE_CODE (rhs) == MEM_REF);
!       op0 = TREE_OPERAND (rhs, 0);
!       op1 = TREE_OPERAND (rhs, 1);
!     }
!   else
!     gcc_unreachable ();
  
    if (object_sizes[object_size_type][varno] == unknown[object_size_type])
      return false;
*************** collect_object_sizes_for (struct object_
*** 913,925 ****
      {
      case GIMPLE_ASSIGN:
        {
!         if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
            reexamine = plus_stmt_object_size (osi, var, stmt);
          else if (gimple_assign_single_p (stmt)
                   || gimple_assign_unary_nop_p (stmt))
            {
-             tree rhs = gimple_assign_rhs1 (stmt);
- 
              if (TREE_CODE (rhs) == SSA_NAME
                  && POINTER_TYPE_P (TREE_TYPE (rhs)))
                reexamine = merge_object_sizes (osi, var, rhs, 0);
--- 923,936 ----
      {
      case GIMPLE_ASSIGN:
        {
! 	tree rhs = gimple_assign_rhs1 (stmt);
!         if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
! 	    || (gimple_assign_rhs_code (stmt) == ADDR_EXPR
! 		&& TREE_CODE (TREE_OPERAND (rhs, 0)) == MEM_REF))
            reexamine = plus_stmt_object_size (osi, var, stmt);
          else if (gimple_assign_single_p (stmt)
                   || gimple_assign_unary_nop_p (stmt))
            {
              if (TREE_CODE (rhs) == SSA_NAME
                  && POINTER_TYPE_P (TREE_TYPE (rhs)))
                reexamine = merge_object_sizes (osi, var, rhs, 0);



More information about the Gcc-patches mailing list