aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr69117.c23
-rw-r--r--gcc/tree-ssa-sccvn.c81
-rw-r--r--gcc/tree-ssa-sccvn.h3
5 files changed, 117 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6f9c6a5..410c893 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2016-01-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/69117
+ * tree-ssa-sccvn.h (struct vn_ssa_aux): Add info member.
+ * tree-ssa-sccvn.c (set_ssa_val_to): Save and adjust SSA name info
+ of the leader conservatively.
+ (free_scc_vn): Restore original SSA name infos.
+
2016-01-14 Jeff Law <law@redhat.com>
PR tree-optimization/69270
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 250f55f..52f5b1e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-15 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/69117
+ * gcc.dg/torture/pr69117.c: New testcase.
+
2015-01-14 Ryan Burn <contact@rnburn.com>
PR c++/69048
diff --git a/gcc/testsuite/gcc.dg/torture/pr69117.c b/gcc/testsuite/gcc.dg/torture/pr69117.c
new file mode 100644
index 0000000..fbf82c1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr69117.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-aliasing" } */
+
+int a, c, *d = &c, **e = &d, *g = &a;
+static int ***b, **f = &d;
+
+int
+main ()
+{
+ **f = 0;
+ int ****h = 0;
+ if (c)
+ {
+ *h = &e;
+ ***b = 0;
+ }
+ *e = g;
+
+ if (d != &a)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 669d0b1..a6ee501 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -3037,6 +3037,73 @@ set_ssa_val_to (tree from, tree to)
== get_addr_base_and_unit_offset (TREE_OPERAND (to, 0), &toff))
&& coff == toff))
{
+ /* If we equate two SSA names we have to make the side-band info
+ of the leader conservative (and remember whatever original value
+ was present). */
+ if (TREE_CODE (to) == SSA_NAME)
+ {
+ if (INTEGRAL_TYPE_P (TREE_TYPE (to))
+ && SSA_NAME_RANGE_INFO (to))
+ {
+ if (SSA_NAME_IS_DEFAULT_DEF (to)
+ || dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (from)),
+ gimple_bb (SSA_NAME_DEF_STMT (to))))
+ /* Keep the info from the dominator. */
+ ;
+ else if (SSA_NAME_IS_DEFAULT_DEF (from)
+ || dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (to)),
+ gimple_bb (SSA_NAME_DEF_STMT (from))))
+ {
+ /* Save old info. */
+ if (! VN_INFO (to)->info.range_info)
+ VN_INFO (to)->info.range_info = SSA_NAME_RANGE_INFO (to);
+ /* Use that from the dominator. */
+ SSA_NAME_RANGE_INFO (to) = SSA_NAME_RANGE_INFO (from);
+ }
+ else
+ {
+ /* Save old info. */
+ if (! VN_INFO (to)->info.range_info)
+ VN_INFO (to)->info.range_info = SSA_NAME_RANGE_INFO (to);
+ /* Rather than allocating memory and unioning the info
+ just clear it. */
+ SSA_NAME_RANGE_INFO (to) = NULL;
+ }
+ }
+ else if (POINTER_TYPE_P (TREE_TYPE (to))
+ && SSA_NAME_PTR_INFO (to))
+ {
+ if (SSA_NAME_IS_DEFAULT_DEF (to)
+ || dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (from)),
+ gimple_bb (SSA_NAME_DEF_STMT (to))))
+ /* Keep the info from the dominator. */
+ ;
+ else if (SSA_NAME_IS_DEFAULT_DEF (from)
+ || dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (to)),
+ gimple_bb (SSA_NAME_DEF_STMT (from))))
+ {
+ /* Save old info. */
+ if (! VN_INFO (to)->info.ptr_info)
+ VN_INFO (to)->info.ptr_info = SSA_NAME_PTR_INFO (to);
+ /* Use that from the dominator. */
+ SSA_NAME_PTR_INFO (to) = SSA_NAME_PTR_INFO (from);
+ }
+ else
+ {
+ /* Save old info. */
+ if (! VN_INFO (to)->info.ptr_info)
+ VN_INFO (to)->info.ptr_info = SSA_NAME_PTR_INFO (to);
+ /* Rather than allocating memory and unioning the info
+ just clear it. */
+ SSA_NAME_PTR_INFO (to) = NULL;
+ }
+ }
+ }
+
VN_INFO (from)->valnum = to;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " (changed)\n");
@@ -4152,9 +4219,17 @@ free_scc_vn (void)
{
tree name = ssa_name (i);
if (name
- && has_VN_INFO (name)
- && VN_INFO (name)->needs_insertion)
- release_ssa_name (name);
+ && has_VN_INFO (name))
+ {
+ if (VN_INFO (name)->needs_insertion)
+ release_ssa_name (name);
+ else if (POINTER_TYPE_P (TREE_TYPE (name))
+ && VN_INFO (name)->info.ptr_info)
+ SSA_NAME_PTR_INFO (name) = VN_INFO (name)->info.ptr_info;
+ else if (INTEGRAL_TYPE_P (TREE_TYPE (name))
+ && VN_INFO (name)->info.range_info)
+ SSA_NAME_RANGE_INFO (name) = VN_INFO (name)->info.range_info;
+ }
}
obstack_free (&vn_ssa_aux_obstack, NULL);
vn_ssa_aux_table.release ();
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 04339ac..d94bc1c 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -169,6 +169,9 @@ typedef struct vn_ssa_aux
/* Statements to insert if needs_insertion is true. */
gimple_seq expr;
+ /* Saved SSA name info. */
+ tree_ssa_name::ssa_name_info_type info;
+
/* Unique identifier that all expressions with the same value have. */
unsigned int value_id;