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 PR31146, unable to optimize loop with placement new


This fixes PR31146 where we could not optimize a loop like

template <class T>
struct Vec
{
  Vec()
  {
    for (int i=0; i<3; ++i) 
      new (&a[i]) T(0); 
  }
  T a[3]; 
};

because after inlining the new operator we end up with a null-pointer
check against the "wrong" variable:

double * D.2720_4 = &v.a[i_5];  
void *  __p_6 = D.2720_4;              
double *  iftmp.3_7 = (double *) __p_6;  
  if (iftmp.3_7 != 0B)

where you can see that (unfortunately) a conversion from double* to void*
is tree_ssa_useless, but a conversion the other way around is not which
is why only FRE can clean this up (and only because a double* type pointer
is available).

Fixed by making forwprop propagate along the single use chain in this 
case.  This reduces function sizes for inlining.

Boostrapped and tested on x86_64-unknown-linux-gnu, applied to mainline.

Richard.

2007-05-02  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/31146
	* tree-ssa-forwprop.c (forward_propagate_addr_expr_1): New
	argument, single_use_p.  If we have a single use that is
	a conversion to the definition rhs type, propagate that rhs.
	(forward_propagate_addr_expr): Pass single_use_p argument
	to forward_propagate_addr_expr_1.

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

Index: tree-ssa-forwprop.c
===================================================================
*** tree-ssa-forwprop.c	(revision 124328)
--- tree-ssa-forwprop.c	(working copy)
*************** forward_propagate_addr_into_variable_arr
*** 559,565 ****
     be not totally successful, yet things may have been changed).  */
  
  static bool
! forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt)
  {
    tree lhs, rhs, array_ref;
  
--- 559,566 ----
     be not totally successful, yet things may have been changed).  */
  
  static bool
! forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt,
! 			       bool single_use_p)
  {
    tree lhs, rhs, array_ref;
  
*************** forward_propagate_addr_expr_1 (tree name
*** 584,593 ****
        /* Continue propagating into the RHS.  */
      }
  
!   /* Trivial case.  The use statement could be a trivial copy or a
       useless conversion.  Recurse to the uses of the lhs as copyprop does
       not copy through differen variant pointers and FRE does not catch
!      all useless conversions.  */
    else if ((TREE_CODE (lhs) == SSA_NAME
        	    && rhs == name)
  	   || ((TREE_CODE (rhs) == NOP_EXPR
--- 585,604 ----
        /* Continue propagating into the RHS.  */
      }
  
!   /* Trivial cases.  The use statement could be a trivial copy or a
       useless conversion.  Recurse to the uses of the lhs as copyprop does
       not copy through differen variant pointers and FRE does not catch
!      all useless conversions.  Treat the case of a single-use name and
!      a conversion to def_rhs type separate, though.  */
!   else if (TREE_CODE (lhs) == SSA_NAME
! 	   && (TREE_CODE (rhs) == NOP_EXPR
! 	       || TREE_CODE (rhs) == CONVERT_EXPR)
! 	   && TREE_TYPE (rhs) == TREE_TYPE (def_rhs)
! 	   && single_use_p)
!     {
!       GIMPLE_STMT_OPERAND (use_stmt, 1) = unshare_expr (def_rhs);
!       return true;
!     }
    else if ((TREE_CODE (lhs) == SSA_NAME
        	    && rhs == name)
  	   || ((TREE_CODE (rhs) == NOP_EXPR
*************** forward_propagate_addr_expr (tree name, 
*** 702,707 ****
--- 713,719 ----
    imm_use_iterator iter;
    tree use_stmt;
    bool all = true;
+   bool single_use_p = has_single_use (name);
  
    FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
      {
*************** forward_propagate_addr_expr (tree name, 
*** 726,732 ****
        
        push_stmt_changes (&use_stmt);
  
!       result = forward_propagate_addr_expr_1 (name, rhs, use_stmt);
        all &= result;
  
        pop_stmt_changes (&use_stmt);
--- 738,745 ----
        
        push_stmt_changes (&use_stmt);
  
!       result = forward_propagate_addr_expr_1 (name, rhs, use_stmt,
! 					      single_use_p);
        all &= result;
  
        pop_stmt_changes (&use_stmt);
Index: testsuite/g++.dg/tree-ssa/pr31146-2.C
===================================================================
*** testsuite/g++.dg/tree-ssa/pr31146-2.C	(revision 0)
--- testsuite/g++.dg/tree-ssa/pr31146-2.C	(revision 0)
***************
*** 0 ****
--- 1,24 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-forwprop1" } */
+ 
+ #include <new>
+ 
+ template <class T>
+ struct Vec
+ {
+   Vec()
+   {
+     for (int i=0; i<3; ++i)
+       new (&a[i]) T(0);
+   }
+   T a[3];
+ };
+ 
+ double foo (void)
+ {
+   Vec<double> v;
+   return v.a[2];
+ }
+ 
+ /* { dg-final { scan-tree-dump "Replaced .*iftmp.* != 0B. with .1" "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]