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 PR49770


This patch fixes PR49770 by introducing an indicator whether it's
worth to lose some TBAA in favor of using existing valueization.
Simple for now - always make sure use the valueized variant if
that is in any way different from the unvalueized one.

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

Richard.

2011-07-21  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/49770
	* tree-ssa-sccvn.c (valueize_refs_1): Return whether we
	valueized any operand.  Renamed from ...
	(valueize_refs): ... this.  New wrapper around valueize_refs_1.
	(valueize_shared_reference_ops_from_ref): Return whether we
	valueized any operand.
	(vn_reference_lookup): Only when we valueized any operand
	use the valueized reference for alias analysis.  Do not preserve
	the original reference tree in this case.

	* g++.dg/torture/pr49770.C: New testcase.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c	(revision 176554)
--- gcc/tree-ssa-sccvn.c	(working copy)
*************** fully_constant_vn_reference_p (vn_refere
*** 1146,1174 ****
  
  /* Transform any SSA_NAME's in a vector of vn_reference_op_s
     structures into their value numbers.  This is done in-place, and
!    the vector passed in is returned.  */
  
  static VEC (vn_reference_op_s, heap) *
! valueize_refs (VEC (vn_reference_op_s, heap) *orig)
  {
    vn_reference_op_t vro;
    unsigned int i;
  
    FOR_EACH_VEC_ELT (vn_reference_op_s, orig, i, vro)
      {
        if (vro->opcode == SSA_NAME
  	  || (vro->op0 && TREE_CODE (vro->op0) == SSA_NAME))
  	{
! 	  vro->op0 = SSA_VAL (vro->op0);
  	  /* If it transforms from an SSA_NAME to a constant, update
  	     the opcode.  */
  	  if (TREE_CODE (vro->op0) != SSA_NAME && vro->opcode == SSA_NAME)
  	    vro->opcode = TREE_CODE (vro->op0);
  	}
        if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
! 	vro->op1 = SSA_VAL (vro->op1);
        if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
! 	vro->op2 = SSA_VAL (vro->op2);
        /* If it transforms from an SSA_NAME to an address, fold with
  	 a preceding indirect reference.  */
        if (i > 0
--- 1146,1196 ----
  
  /* Transform any SSA_NAME's in a vector of vn_reference_op_s
     structures into their value numbers.  This is done in-place, and
!    the vector passed in is returned.  *VALUEIZED_ANYTHING will specify
!    whether any operands were valueized.  */
  
  static VEC (vn_reference_op_s, heap) *
! valueize_refs_1 (VEC (vn_reference_op_s, heap) *orig, bool *valueized_anything)
  {
    vn_reference_op_t vro;
    unsigned int i;
  
+   *valueized_anything = false;
+ 
    FOR_EACH_VEC_ELT (vn_reference_op_s, orig, i, vro)
      {
        if (vro->opcode == SSA_NAME
  	  || (vro->op0 && TREE_CODE (vro->op0) == SSA_NAME))
  	{
! 	  tree tem = SSA_VAL (vro->op0);
! 	  if (tem != vro->op0)
! 	    {
! 	      *valueized_anything = true;
! 	      vro->op0 = tem;
! 	    }
  	  /* If it transforms from an SSA_NAME to a constant, update
  	     the opcode.  */
  	  if (TREE_CODE (vro->op0) != SSA_NAME && vro->opcode == SSA_NAME)
  	    vro->opcode = TREE_CODE (vro->op0);
  	}
        if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
! 	{
! 	  tree tem = SSA_VAL (vro->op1);
! 	  if (tem != vro->op1)
! 	    {
! 	      *valueized_anything = true;
! 	      vro->op1 = tem;
! 	    }
! 	}
        if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
! 	{
! 	  tree tem = SSA_VAL (vro->op2);
! 	  if (tem != vro->op2)
! 	    {
! 	      *valueized_anything = true;
! 	      vro->op2 = tem;
! 	    }
! 	}
        /* If it transforms from an SSA_NAME to an address, fold with
  	 a preceding indirect reference.  */
        if (i > 0
*************** valueize_refs (VEC (vn_reference_op_s, h
*** 1203,1222 ****
    return orig;
  }
  
  static VEC(vn_reference_op_s, heap) *shared_lookup_references;
  
  /* Create a vector of vn_reference_op_s structures from REF, a
     REFERENCE_CLASS_P tree.  The vector is shared among all callers of
!    this function.  */
  
  static VEC(vn_reference_op_s, heap) *
! valueize_shared_reference_ops_from_ref (tree ref)
  {
    if (!ref)
      return NULL;
    VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
    copy_reference_ops_from_ref (ref, &shared_lookup_references);
!   shared_lookup_references = valueize_refs (shared_lookup_references);
    return shared_lookup_references;
  }
  
--- 1225,1253 ----
    return orig;
  }
  
+ static VEC (vn_reference_op_s, heap) *
+ valueize_refs (VEC (vn_reference_op_s, heap) *orig)
+ {
+   bool tem;
+   return valueize_refs_1 (orig, &tem);
+ }
+ 
  static VEC(vn_reference_op_s, heap) *shared_lookup_references;
  
  /* Create a vector of vn_reference_op_s structures from REF, a
     REFERENCE_CLASS_P tree.  The vector is shared among all callers of
!    this function.  *VALUEIZED_ANYTHING will specify whether any
!    operands were valueized.  */
  
  static VEC(vn_reference_op_s, heap) *
! valueize_shared_reference_ops_from_ref (tree ref, bool *valueized_anything)
  {
    if (!ref)
      return NULL;
    VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
    copy_reference_ops_from_ref (ref, &shared_lookup_references);
!   shared_lookup_references = valueize_refs_1 (shared_lookup_references,
! 					      valueized_anything);
    return shared_lookup_references;
  }
  
*************** vn_reference_lookup (tree op, tree vuse,
*** 1694,1705 ****
    VEC (vn_reference_op_s, heap) *operands;
    struct vn_reference_s vr1;
    tree cst;
  
    if (vnresult)
      *vnresult = NULL;
  
    vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
!   vr1.operands = operands = valueize_shared_reference_ops_from_ref (op);
    vr1.type = TREE_TYPE (op);
    vr1.set = get_alias_set (op);
    vr1.hashcode = vn_reference_compute_hash (&vr1);
--- 1725,1738 ----
    VEC (vn_reference_op_s, heap) *operands;
    struct vn_reference_s vr1;
    tree cst;
+   bool valuezied_anything;
  
    if (vnresult)
      *vnresult = NULL;
  
    vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
!   vr1.operands = operands
!     = valueize_shared_reference_ops_from_ref (op, &valuezied_anything);
    vr1.type = TREE_TYPE (op);
    vr1.set = get_alias_set (op);
    vr1.hashcode = vn_reference_compute_hash (&vr1);
*************** vn_reference_lookup (tree op, tree vuse,
*** 1711,1722 ****
      {
        vn_reference_t wvnresult;
        ao_ref r;
!       /* Make sure to use a valueized reference ...  */
!       if (!ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type, vr1.operands))
  	ao_ref_init (&r, op);
-       else
- 	/* ... but also preserve a full reference tree for advanced TBAA.  */
- 	r.ref = op;
        vn_walk_kind = kind;
        wvnresult =
  	(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
--- 1744,1755 ----
      {
        vn_reference_t wvnresult;
        ao_ref r;
!       /* Make sure to use a valueized reference if we valueized anything.
!          Otherwise preserve the full reference for advanced TBAA.  */
!       if (!valuezied_anything
! 	  || !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type,
! 					     vr1.operands))
  	ao_ref_init (&r, op);
        vn_walk_kind = kind;
        wvnresult =
  	(vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
Index: gcc/testsuite/g++.dg/torture/pr49770.C
===================================================================
*** gcc/testsuite/g++.dg/torture/pr49770.C	(revision 0)
--- gcc/testsuite/g++.dg/torture/pr49770.C	(revision 0)
***************
*** 0 ****
--- 1,86 ----
+ /* { dg-do run } */
+ /* { dg-options "-std=c++0x -fno-tree-forwprop" } */
+ 
+ typedef __SIZE_TYPE__ size_t;
+ 
+ template < typename > struct remove_reference;
+ template < typename _Tp > struct remove_reference <_Tp & >
+ {
+   typedef _Tp type;
+ };
+ template < typename _Tp > typename remove_reference < _Tp >::type &&
+ move (_Tp && __t)
+ {
+   return static_cast < typename remove_reference < _Tp >::type && >(__t);
+ }
+ 
+ template < typename _Tp > void
+ stdswap (_Tp & __a, _Tp & __b)
+ {
+   _Tp __tmp (__a);
+   __a = (__b);
+   __b = (__tmp);
+ }
+ 
+ struct _Deque_iterator
+ {
+   int *_M_cur;
+   int *_M_first;
+   int *_M_last;
+   int **_M_node;
+ };
+ 
+ static inline int operatorMIN (_Deque_iterator & __x, _Deque_iterator & __y)
+ {
+   return sizeof (int) * (__x._M_node - __y._M_node - 1)
+     + (__x._M_cur - __x._M_first) + (__y._M_last - __y._M_cur);
+ }
+ 
+ struct deque
+ {
+   deque & operator = (deque && __x)
+   {
+     stdswap (_M_finish, __x._M_finish);
+     return *this;
+   }
+   size_t size ()
+   {
+     return operatorMIN (_M_finish, _M_start);
+   }
+ 
+ deque ():
+   _M_map (), _M_map_size (), _M_start (), _M_finish ()
+   {
+     _M_start._M_last = _M_start._M_first + sizeof (int);
+   }
+ 
+   int **_M_map;
+   size_t _M_map_size;
+   _Deque_iterator _M_start;
+   _Deque_iterator _M_finish;
+ };
+ 
+ struct queue
+ {
+   deque c;
+   size_t size ()
+   {
+     return c.size ();
+   }
+ };
+ 
+ void
+ test01 ()
+ {
+   queue a, b;
+   ++a.c._M_finish._M_cur;
+   b = move (a);
+   if (!b.size ())
+     __builtin_abort ();
+ }
+ 
+ main ()
+ {
+   test01 ();
+ }
+ 


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