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]

[PATCH] Teach forwprop about constant offsets when propagating offset into array-ref


This teaches forwprop to still re-construct an array-ref if we
start to canonicalize a * 4 + 4 differently (not as (a + 1) * 4 as now).
This is also a missed optimization if the address arithmetic is
in decomposed form initially.

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

Richard.

2009-03-31  Richard Guenther  <rguenther@suse.de>

	* tree.h (div_if_zero_remainder): Declare.
	* fold-const.c (div_if_zero_remainder): Export.
	* tree-ssa-forwprop.c
	(forward_propagate_addr_into_variable_array_index): Handle
	constant array index addition outside of the variable index.

	* gcc.dg/tree-ssa/forwprop-12.c: New testcase.

Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig	2009-03-31 10:37:02.000000000 +0200
--- gcc/tree.h	2009-03-31 10:38:09.000000000 +0200
*************** extern tree build_fold_indirect_ref (tre
*** 4838,4843 ****
--- 4838,4844 ----
  extern tree fold_indirect_ref (tree);
  extern tree constant_boolean_node (int, tree);
  extern tree build_low_bits_mask (tree, unsigned);
+ extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
  
  extern bool tree_swap_operands_p (const_tree, const_tree, bool);
  extern enum tree_code swap_tree_comparison (enum tree_code);
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig	2009-03-30 15:51:07.000000000 +0200
--- gcc/fold-const.c	2009-03-31 10:39:13.000000000 +0200
*************** div_and_round_double (enum tree_code cod
*** 874,880 ****
     of type CODE and returns the quotient.
     Otherwise returns NULL_TREE.  */
  
! static tree
  div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
  {
    unsigned HOST_WIDE_INT int1l, int2l;
--- 874,880 ----
     of type CODE and returns the quotient.
     Otherwise returns NULL_TREE.  */
  
! tree
  div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
  {
    unsigned HOST_WIDE_INT int1l, int2l;
Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c.orig	2009-03-30 15:51:07.000000000 +0200
--- gcc/tree-ssa-forwprop.c	2009-03-31 10:38:09.000000000 +0200
*************** forward_propagate_addr_into_variable_arr
*** 618,625 ****
  						  tree def_rhs,
  						  gimple_stmt_iterator *use_stmt_gsi)
  {
!   tree index;
    gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi);
  
    /* Get the offset's defining statement.  */
    offset_def = SSA_NAME_DEF_STMT (offset);
--- 618,630 ----
  						  tree def_rhs,
  						  gimple_stmt_iterator *use_stmt_gsi)
  {
!   tree index, tunit;
    gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi);
+   tree tmp;
+ 
+   tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)));
+   if (!host_integerp (tunit, 1))
+     return false;
  
    /* Get the offset's defining statement.  */
    offset_def = SSA_NAME_DEF_STMT (offset);
*************** forward_propagate_addr_into_variable_arr
*** 629,635 ****
       along in case the element size is one. In that case, however, we do not
       allow multiplications because they can be computing index to a higher
       level dimension (PR 37861). */
!   if (integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)))))
      {
        if (is_gimple_assign (offset_def)
  	  && gimple_assign_rhs_code (offset_def) == MULT_EXPR)
--- 634,640 ----
       along in case the element size is one. In that case, however, we do not
       allow multiplications because they can be computing index to a higher
       level dimension (PR 37861). */
!   if (integer_onep (tunit))
      {
        if (is_gimple_assign (offset_def)
  	  && gimple_assign_rhs_code (offset_def) == MULT_EXPR)
*************** forward_propagate_addr_into_variable_arr
*** 648,665 ****
  	 multiplication of an object by the size of the array elements. 
  	 This implicitly verifies that the size of the array elements
  	 is constant.  */
!      offset = gimple_assign_rhs1 (offset_def);
!      if (gimple_assign_rhs_code (offset_def) != MULT_EXPR
! 	 || TREE_CODE (gimple_assign_rhs2 (offset_def)) != INTEGER_CST
! 	 || !simple_cst_equal (gimple_assign_rhs2 (offset_def),
! 			       TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)))))
  	return false;
- 
-       /* The first operand to the MULT_EXPR is the desired index.  */
-       index = offset;
      }
  
    /* Replace the pointer addition with array indexing.  */
    gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs));
    use_stmt = gsi_stmt (*use_stmt_gsi);
    TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1)
--- 653,693 ----
  	 multiplication of an object by the size of the array elements. 
  	 This implicitly verifies that the size of the array elements
  	 is constant.  */
!      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), tunit))
!        {
! 	 /* The first operand to the MULT_EXPR is the desired index.  */
! 	 index = gimple_assign_rhs1 (offset_def);
!        }
!      /* If we have idx * tunit + CST * tunit re-associate that.  */
!      else if ((gimple_assign_rhs_code (offset_def) == PLUS_EXPR
! 	       || gimple_assign_rhs_code (offset_def) == MINUS_EXPR)
! 	      && TREE_CODE (gimple_assign_rhs1 (offset_def)) == SSA_NAME
! 	      && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
! 	      && (tmp = div_if_zero_remainder (EXACT_DIV_EXPR,
! 					       gimple_assign_rhs2 (offset_def),
! 					       tunit)) != NULL_TREE)
!        {
! 	 gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def));
! 	 if (gimple_assign_rhs_code (offset_def2) == MULT_EXPR
! 	     && TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST
! 	     && tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit))
! 	   {
! 	     index = fold_build2 (gimple_assign_rhs_code (offset_def),
! 				  TREE_TYPE (offset),
! 				  gimple_assign_rhs1 (offset_def2), tmp);
! 	   }
! 	 else
! 	   return false;
!        }
!      else
  	return false;
      }
  
    /* Replace the pointer addition with array indexing.  */
+   index = force_gimple_operand_gsi (use_stmt_gsi, index, true, NULL_TREE,
+ 				    true, GSI_SAME_STMT);
    gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs));
    use_stmt = gsi_stmt (*use_stmt_gsi);
    TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1)
Index: gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c	2009-03-31 10:38:09.000000000 +0200
***************
*** 0 ****
--- 1,22 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-forwprop1" } */
+ 
+ struct X { int a[256]; };
+ 
+ int foo(struct X *p, __SIZE_TYPE__ i)
+ {
+   int *q = &p->a[0];
+   int *q2 = (int *)((void *)q + i*4 + 32);
+   return *q2;
+ }
+ 
+ int bar(struct X *p, int i)
+ {
+   return *((int *)p + i + 8);
+ }
+ 
+ /* We should have propagated the base array address through the
+    address arithmetic into the memory access as an array access.  */
+ 
+ /* { dg-final { scan-tree-dump-times "->a\\\[D\\\." 2 "forwprop1" } } */
+ /* { dg-final { cleanup-tree-dump "forwprop1" } } */


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