diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr69117.c | 23 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 81 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.h | 3 |
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; |