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] Fix PR58404


Jakub noticed that we don't forward &a[i] into a dereference of said
pointer when the resulting struct is partially accessed.  I suppose
I just didn't implement that initially because I was lazy.  It turns
out to be comparatively easy to do though.

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

Richard.

2013-09-12  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/58404
	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Also
	propagate non-invariant addresses into dereferences wrapped
	in component references.

	* g++.dg/tree-ssa/pr58404.C: New testcase.

Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c	(revision 202515)
--- gcc/tree-ssa-forwprop.c	(working copy)
*************** forward_propagate_addr_expr_1 (tree name
*** 786,794 ****
  
    /* Now strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS.
       ADDR_EXPR will not appear on the LHS.  */
!   lhs = gimple_assign_lhs (use_stmt);
!   while (handled_component_p (lhs))
!     lhs = TREE_OPERAND (lhs, 0);
  
    /* Now see if the LHS node is a MEM_REF using NAME.  If so,
       propagate the ADDR_EXPR into the use of NAME and fold the result.  */
--- 786,795 ----
  
    /* Now strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS.
       ADDR_EXPR will not appear on the LHS.  */
!   tree *lhsp = gimple_assign_lhs_ptr (use_stmt);
!   while (handled_component_p (*lhsp))
!     lhsp = &TREE_OPERAND (*lhsp, 0);
!   lhs = *lhsp;
  
    /* Now see if the LHS node is a MEM_REF using NAME.  If so,
       propagate the ADDR_EXPR into the use of NAME and fold the result.  */
*************** forward_propagate_addr_expr_1 (tree name
*** 822,832 ****
        /* If the LHS is a plain dereference and the value type is the same as
           that of the pointed-to type of the address we can put the
  	 dereferenced address on the LHS preserving the original alias-type.  */
!       else if (gimple_assign_lhs (use_stmt) == lhs
! 	       && integer_zerop (TREE_OPERAND (lhs, 1))
! 	       && useless_type_conversion_p
! 	            (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
! 		     TREE_TYPE (gimple_assign_rhs1 (use_stmt)))
  	       /* Don't forward anything into clobber stmts if it would result
  		  in the lhs no longer being a MEM_REF.  */
  	       && (!gimple_clobber_p (use_stmt)
--- 823,835 ----
        /* If the LHS is a plain dereference and the value type is the same as
           that of the pointed-to type of the address we can put the
  	 dereferenced address on the LHS preserving the original alias-type.  */
!       else if (integer_zerop (TREE_OPERAND (lhs, 1))
! 	       && ((gimple_assign_lhs (use_stmt) == lhs
! 		    && useless_type_conversion_p
! 		         (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
! 		          TREE_TYPE (gimple_assign_rhs1 (use_stmt))))
! 		   || types_compatible_p (TREE_TYPE (lhs),
! 					  TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
  	       /* Don't forward anything into clobber stmts if it would result
  		  in the lhs no longer being a MEM_REF.  */
  	       && (!gimple_clobber_p (use_stmt)
*************** forward_propagate_addr_expr_1 (tree name
*** 854,860 ****
  	  TREE_SIDE_EFFECTS (*def_rhs_basep) = TREE_SIDE_EFFECTS (lhs);
  	  TREE_THIS_NOTRAP (*def_rhs_basep) = TREE_THIS_NOTRAP (lhs);
  	  new_lhs = unshare_expr (TREE_OPERAND (def_rhs, 0));
! 	  gimple_assign_set_lhs (use_stmt, new_lhs);
  	  TREE_THIS_VOLATILE (new_lhs) = TREE_THIS_VOLATILE (lhs);
  	  TREE_SIDE_EFFECTS (new_lhs) = TREE_SIDE_EFFECTS (lhs);
  	  *def_rhs_basep = saved;
--- 857,863 ----
  	  TREE_SIDE_EFFECTS (*def_rhs_basep) = TREE_SIDE_EFFECTS (lhs);
  	  TREE_THIS_NOTRAP (*def_rhs_basep) = TREE_THIS_NOTRAP (lhs);
  	  new_lhs = unshare_expr (TREE_OPERAND (def_rhs, 0));
! 	  *lhsp = new_lhs;
  	  TREE_THIS_VOLATILE (new_lhs) = TREE_THIS_VOLATILE (lhs);
  	  TREE_SIDE_EFFECTS (new_lhs) = TREE_SIDE_EFFECTS (lhs);
  	  *def_rhs_basep = saved;
*************** forward_propagate_addr_expr_1 (tree name
*** 873,883 ****
  
    /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
       nodes from the RHS.  */
!   rhs = gimple_assign_rhs1 (use_stmt);
!   if (TREE_CODE (rhs) == ADDR_EXPR)
!     rhs = TREE_OPERAND (rhs, 0);
!   while (handled_component_p (rhs))
!     rhs = TREE_OPERAND (rhs, 0);
  
    /* Now see if the RHS node is a MEM_REF using NAME.  If so,
       propagate the ADDR_EXPR into the use of NAME and fold the result.  */
--- 876,887 ----
  
    /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
       nodes from the RHS.  */
!   tree *rhsp = gimple_assign_rhs1_ptr (use_stmt);
!   if (TREE_CODE (*rhsp) == ADDR_EXPR)
!     rhsp = &TREE_OPERAND (*rhsp, 0);
!   while (handled_component_p (*rhsp))
!     rhsp = &TREE_OPERAND (*rhsp, 0);
!   rhs = *rhsp;
  
    /* Now see if the RHS node is a MEM_REF using NAME.  If so,
       propagate the ADDR_EXPR into the use of NAME and fold the result.  */
*************** forward_propagate_addr_expr_1 (tree name
*** 909,919 ****
        /* If the RHS is a plain dereference and the value type is the same as
           that of the pointed-to type of the address we can put the
  	 dereferenced address on the RHS preserving the original alias-type.  */
!       else if (gimple_assign_rhs1 (use_stmt) == rhs
! 	       && integer_zerop (TREE_OPERAND (rhs, 1))
! 	       && useless_type_conversion_p
! 		    (TREE_TYPE (gimple_assign_lhs (use_stmt)),
! 		     TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
  	{
  	  tree *def_rhs_basep = &TREE_OPERAND (def_rhs, 0);
  	  tree new_offset, new_base, saved, new_rhs;
--- 913,925 ----
        /* If the RHS is a plain dereference and the value type is the same as
           that of the pointed-to type of the address we can put the
  	 dereferenced address on the RHS preserving the original alias-type.  */
!       else if (integer_zerop (TREE_OPERAND (rhs, 1))
! 	       && ((gimple_assign_rhs1 (use_stmt) == rhs
! 		    && useless_type_conversion_p
! 		         (TREE_TYPE (gimple_assign_lhs (use_stmt)),
! 		          TREE_TYPE (TREE_OPERAND (def_rhs, 0))))
! 		   || types_compatible_p (TREE_TYPE (rhs),
! 					  TREE_TYPE (TREE_OPERAND (def_rhs, 0)))))
  	{
  	  tree *def_rhs_basep = &TREE_OPERAND (def_rhs, 0);
  	  tree new_offset, new_base, saved, new_rhs;
*************** forward_propagate_addr_expr_1 (tree name
*** 937,943 ****
  	  TREE_SIDE_EFFECTS (*def_rhs_basep) = TREE_SIDE_EFFECTS (rhs);
  	  TREE_THIS_NOTRAP (*def_rhs_basep) = TREE_THIS_NOTRAP (rhs);
  	  new_rhs = unshare_expr (TREE_OPERAND (def_rhs, 0));
! 	  gimple_assign_set_rhs1 (use_stmt, new_rhs);
  	  TREE_THIS_VOLATILE (new_rhs) = TREE_THIS_VOLATILE (rhs);
  	  TREE_SIDE_EFFECTS (new_rhs) = TREE_SIDE_EFFECTS (rhs);
  	  *def_rhs_basep = saved;
--- 943,949 ----
  	  TREE_SIDE_EFFECTS (*def_rhs_basep) = TREE_SIDE_EFFECTS (rhs);
  	  TREE_THIS_NOTRAP (*def_rhs_basep) = TREE_THIS_NOTRAP (rhs);
  	  new_rhs = unshare_expr (TREE_OPERAND (def_rhs, 0));
! 	  *rhsp = new_rhs;
  	  TREE_THIS_VOLATILE (new_rhs) = TREE_THIS_VOLATILE (rhs);
  	  TREE_SIDE_EFFECTS (new_rhs) = TREE_SIDE_EFFECTS (rhs);
  	  *def_rhs_basep = saved;
Index: gcc/testsuite/g++.dg/tree-ssa/pr58404.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/pr58404.C	(revision 0)
--- gcc/testsuite/g++.dg/tree-ssa/pr58404.C	(working copy)
***************
*** 0 ****
--- 1,20 ----
+ // { dg-do compile }
+ // { dg-options "-O -fdump-tree-cddce1" }
+ 
+ struct S { int s; };
+ S a[1024];
+ 
+ void
+ foo ()
+ {
+   for (int i = 0; i < 1024; i++)
+     {
+       S &r = a[i];
+       r.s++;
+     }
+ }
+ 
+ // We should propagate the reference into both memory accesses
+ // during the first forwprop pass
+ // { dg-final { scan-tree-dump-times "= &a" 0 "cddce1" } }
+ // { dg-final { cleanup-tree-dump "cddce1" } }


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