From 3ceaf2f571c5b02610383abb80579861cff5d22e Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Thu, 21 Jul 2011 13:19:18 +0000 Subject: [PATCH] re PR tree-optimization/49770 (wrong code with -fno-tree-forwprop) 2011-07-21 Richard Guenther 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. From-SVN: r176567 --- gcc/ChangeLog | 12 ++++ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/torture/pr49770.C | 86 ++++++++++++++++++++++++++ gcc/tree-ssa-sccvn.c | 61 +++++++++++++----- 4 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr49770.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c0c820ddcac..a6904e524ea 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2011-07-21 Richard Guenther + + 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. + 2011-07-21 Uros Bizjak * config/i386/i386.c (ix86_decompose_address): Reject all but diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 05ad509b33a..334730cc80a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-07-21 Richard Guenther + + PR tree-optimization/49770 + * g++.dg/torture/pr49770.C: New testcase. + 2011-07-21 Kai Tietz * gcc.dg/tree-ssa/pr30978.c: adjusted. diff --git a/gcc/testsuite/g++.dg/torture/pr49770.C b/gcc/testsuite/g++.dg/torture/pr49770.C new file mode 100644 index 00000000000..7eac9e0d9bb --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr49770.C @@ -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 (); +} + diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 125d0444f4a..5f72f041290 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -1146,29 +1146,51 @@ fully_constant_vn_reference_p (vn_reference_t ref) /* 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. */ + the vector passed in is returned. *VALUEIZED_ANYTHING will specify + whether any operands were valueized. */ static VEC (vn_reference_op_s, heap) * -valueize_refs (VEC (vn_reference_op_s, heap) *orig) +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)) { - vro->op0 = SSA_VAL (vro->op0); + 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) - vro->op1 = SSA_VAL (vro->op1); + { + 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) - vro->op2 = SSA_VAL (vro->op2); + { + 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 @@ -1203,20 +1225,29 @@ valueize_refs (VEC (vn_reference_op_s, heap) *orig) 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. */ + 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) +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 (shared_lookup_references); + shared_lookup_references = valueize_refs_1 (shared_lookup_references, + valueized_anything); return shared_lookup_references; } @@ -1694,12 +1725,14 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, 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); + 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); @@ -1711,12 +1744,12 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, { 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)) + /* 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); - 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, -- 2.30.2