This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR49770
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 21 Jul 2011 15:14:31 +0200 (CEST)
- Subject: [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 ();
+ }
+