This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Start fixing PR19807


The patch attached below starts fixing PR19807 by teaching try_move_mult_to_index to also fold &a[i] + c with c being
a constant multiple of the array element size. This "fixes"
the following two C++ tests:


void foo(int i)
{
        int a[4];
        if ((char*)&a[1] + 4*i + 4 != (char*)&a[i+2])
                link_error();
        if (&a[1] + i + 1 != &a[i+2])
                link_error();
}

but fails to handle the counterparts with unsigned int.

The difficult part of the patch, which I'm not sure how to do correctly
is the selection of the right type for the new ARRAY_REF offset. Otherwise this fixes that we previously could have PLUS_EXPR(..., int, unsinged int) which is invalid, but harmless.


Any ideas how to correctly promote one (or both) of the offsets for
their addition and insertion to the ARRAY_REF?

Thanks,
Richard.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.503
diff -c -3 -p -r1.503 fold-const.c
*** fold-const.c	9 Feb 2005 18:15:30 -0000	1.503
--- fold-const.c	9 Feb 2005 19:05:05 -0000
*************** fold_sign_changed_comparison (enum tree_
*** 6172,6205 ****
  }
  
  /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
!    step of the array.  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 (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))
      {
--- 6172,6217 ----
  }
  
  /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is
!    step of the array.  Also handles the case of &a[idx] CODE delta with
!    delta being a constant multiple of the step of the array.
!    ADDR is the address. MULT is the multiplicative expression or the integer
!    constant offset. If the function succeeds, the new address expression is
!    returned.  Otherwise NULL_TREE is returned.  */
  
  static tree
! try_fold_into_array_ref (enum tree_code code, tree addr, tree mult)
  {
!   tree s = NULL_TREE, delta, step;
    tree ref = TREE_OPERAND (addr, 0), pref;
    tree ret, pos;
!   tree itype, type;
  
!   if (TREE_CODE (mult) == MULT_EXPR)
      {
!       tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
! 
!       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;
      }
!   else if (TREE_CODE (mult) == INTEGER_CST)
      {
!       delta = mult;
      }
    else
!     gcc_unreachable ();
  
    for (;; ref = TREE_OPERAND (ref, 0))
      {
*************** try_move_mult_to_index (enum tree_code c
*** 6212,6233 ****
  
  	  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 (TREE_TYPE (s)))
! 	    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.  */
  
--- 6224,6256 ----
  
  	  itype = TREE_TYPE (step);
  
! 	  if (s)
! 	    {
! 	      /* Try if the steps match.  */
! 	      if (tree_int_cst_equal (step, s))
! 		break;
! 	    }
! 	  else
! 	    {
! 	      /* Try if delta is a multiple of step.  */
! 	      tree mod = int_const_binop (TRUNC_MOD_EXPR, delta, step, 0);
! 	      if (integer_zerop (mod))
! 		{
! 		  delta = int_const_binop (EXACT_DIV_EXPR, delta, step, 0);
! 		  break;
! 		}
! 	    }
  	}
  
        if (!handled_component_p (ref))
  	return NULL_TREE;
      }
  
+   /* Use the bigger type for the new offset.  */
+   type = TREE_TYPE (TREE_OPERAND (ref, 1));
+   if (TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (delta)))
+     type = TREE_TYPE (delta);
+ 
    /* We found the suitable array reference.  So copy everything up to it,
       and replace the index.  */
  
*************** try_move_mult_to_index (enum tree_code c
*** 6242,6250 ****
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1) = fold (build2 (code, itype,
! 					TREE_OPERAND (pos, 1),
! 					delta));
  
    return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
  }
--- 6265,6273 ----
        pos = TREE_OPERAND (pos, 0);
      }
  
!   TREE_OPERAND (pos, 1) = fold (build2 (code, type,
! 					fold_convert (type, TREE_OPERAND (pos, 1)),
! 					fold_convert (type, delta)));
  
    return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
  }
*************** fold (tree expr)
*** 6942,6957 ****
  	     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 (PLUS_EXPR, arg0, arg1);
  	      if (tem)
  		return fold_convert (type, fold (tem));
  	    }
  	  else if (TREE_CODE (arg1) == ADDR_EXPR
! 		   && TREE_CODE (arg0) == MULT_EXPR)
  	    {
! 	      tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
  	      if (tem)
  		return fold_convert (type, fold (tem));
  	    }
--- 6965,6982 ----
  	     of the array.  Loop optimizer sometimes produce this type of
  	     expressions.  */
  	  if (TREE_CODE (arg0) == ADDR_EXPR
! 	      && (TREE_CODE (arg1) == MULT_EXPR
! 		  || TREE_CODE (arg1) == INTEGER_CST))
  	    {
! 	      tem = try_fold_into_array_ref (PLUS_EXPR, arg0, arg1);
  	      if (tem)
  		return fold_convert (type, fold (tem));
  	    }
  	  else if (TREE_CODE (arg1) == ADDR_EXPR
! 		   && (TREE_CODE (arg0) == MULT_EXPR
! 		       || TREE_CODE (arg0) == INTEGER_CST))
  	    {
! 	      tem = try_fold_into_array_ref (PLUS_EXPR, arg1, arg0);
  	      if (tem)
  		return fold_convert (type, fold (tem));
  	    }
*************** fold (tree expr)
*** 7330,7338 ****
  	 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 (MINUS_EXPR, arg0, arg1);
  	  if (tem)
  	    return fold_convert (type, fold (tem));
  	}
--- 7355,7364 ----
  	 of the array.  Loop optimizer sometimes produce this type of
  	 expressions.  */
        if (TREE_CODE (arg0) == ADDR_EXPR
! 	  && (TREE_CODE (arg1) == MULT_EXPR
! 	      || TREE_CODE (arg1) == INTEGER_CST))
  	{
! 	  tem = try_fold_into_array_ref (MINUS_EXPR, arg0, arg1);
  	  if (tem)
  	    return fold_convert (type, fold (tem));
  	}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]