aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-07-21 13:19:18 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-07-21 13:19:18 +0000
commit3ceaf2f571c5b02610383abb80579861cff5d22e (patch)
tree521bd5035d3ea31fdd464007a7f1904d598fe907 /gcc
parenta423549540656e001cd6d0f820ff60cdbe045f7d (diff)
downloadgcc-3ceaf2f571c5b02610383abb80579861cff5d22e.zip
gcc-3ceaf2f571c5b02610383abb80579861cff5d22e.tar.gz
gcc-3ceaf2f571c5b02610383abb80579861cff5d22e.tar.bz2
re PR tree-optimization/49770 (wrong code with -fno-tree-forwprop)
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. From-SVN: r176567
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr49770.C86
-rw-r--r--gcc/tree-ssa-sccvn.c61
4 files changed, 150 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c0c820d..a6904e5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+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.
+
2011-07-21 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (ix86_decompose_address): Reject all but
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 05ad509..334730c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-07-21 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/49770
+ * g++.dg/torture/pr49770.C: New testcase.
+
2011-07-21 Kai Tietz <ktietz@redhat.com>
* 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 0000000..7eac9e0
--- /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 125d044..5f72f04 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,