This fixes bogus non-overlap considerations based on TBAA. Since we also have to care for punning through unions the following uses only align-based checks which are always valid.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Variant for the branch below, also boostrapped/tested and applied to GCC 9 sofar, backport to GCC 8 pending. Richard. 2019-07-08 Richard Biener <rguent...@suse.de> PR tree-optimization/91108 * tree-ssa-sccvn.c: Include builtins.h. (vn_reference_lookup_3): Use only alignment constraints to verify same-valued store disambiguation. * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust back. * gcc.dg/tree-ssa/ssa-fre-78.c: New testcase. Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c (revision 273194) +++ gcc/tree-ssa-sccvn.c (working copy) @@ -70,6 +70,7 @@ along with GCC; see the file COPYING3. #include "tree-ssa-loop.h" #include "tree-scalar-evolution.h" #include "tree-ssa-loop-niter.h" +#include "builtins.h" #include "tree-ssa-sccvn.h" /* This algorithm is based on the SCC algorithm presented by Keith @@ -2248,24 +2249,10 @@ vn_reference_lookup_3 (ao_ref *ref, tree /* If we reach a clobbering statement try to skip it and see if we find a VN result with exactly the same value as the possible clobber. In this case we can ignore the clobber - and return the found value. - Note that we don't need to worry about partial overlapping - accesses as we then can use TBAA to disambiguate against the - clobbering statement when looking up a load (thus the - VN_WALKREWRITE guard). */ - if (data->vn_walk_kind == VN_WALKREWRITE - && is_gimple_reg_type (TREE_TYPE (lhs)) + and return the found value. */ + if (is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) - /* The overlap restriction breaks down when either access - alias-set is zero. Still for accesses of the size of - an addressable unit there can be no overlaps. Overlaps - between different union members are not an issue since - activation of a union member via a store makes the - values of untouched bytes unspecified. */ - && (known_eq (ref->size, BITS_PER_UNIT) - || (flag_strict_aliasing - && get_alias_set (lhs) != 0 - && ao_ref_alias_set (ref) != 0))) + && ref->ref) { tree *saved_last_vuse_ptr = data->last_vuse_ptr; /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ @@ -2284,7 +2271,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree if (TREE_CODE (rhs) == SSA_NAME) rhs = SSA_VAL (rhs); if (vnresult->result - && operand_equal_p (vnresult->result, rhs, 0)) + && operand_equal_p (vnresult->result, rhs, 0) + /* We have to honor our promise about union type punning + and also support arbitrary overlaps with + -fno-strict-aliasing. So simply resort to alignment to + rule out overlaps. Do this check last because it is + quite expensive compared to the hash-lookup above. */ + && multiple_p (get_object_alignment (ref->ref), ref->size) + && multiple_p (get_object_alignment (lhs), ref->size)) return res; } } Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c (revision 273194) +++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c (working copy) @@ -1,5 +1,5 @@ /* { dg-do link } */ -/* { dg-options "-O -fstrict-aliasing -fdump-tree-fre1-details" } */ +/* { dg-options "-O -fdump-tree-fre1-details" } */ void link_error (void); Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c (nonexistent) +++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c (working copy) @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fstrict-aliasing" } */ + +union U { + struct A { int : 2; int x : 8; } a; + struct B { int : 6; int x : 8; } b; +}; + +int __attribute__((noipa)) +foo (union U *p, union U *q) +{ + p->a.x = 1; + q->b.x = 1; + return p->a.x; +} + +int +main() +{ + union U x; + if (foo (&x, &x) != x.a.x) + __builtin_abort (); + return 0; +} + +/* We support arbitrary punning through unions when it happens through + the union type and thus p == q is valid here. */ 2019-07-08 Richard Biener <rguent...@suse.de> PR tree-optimization/91108 * tree-ssa-sccvn.c: Include builtins.h. (vn_reference_lookup_3): Use only alignment constraints to verify same-valued store disambiguation. * gcc.dg/tree-ssa/pr91091-1.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-78.c: Likewise. Index: gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c (working copy) @@ -0,0 +1,23 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-strict-aliasing" } */ + +struct s { int x; } __attribute__((packed)); +struct t { int x; }; + +void __attribute__((noinline,noipa)) +swap(struct s* p, struct t* q) +{ + p->x = q->x; + q->x = p->x; +} + +int main() +{ + struct t a[2]; + a[0].x = 0x12345678; + a[1].x = 0x98765432; + swap ((struct s *)((char *)a + 1), a); + if (a[0].x != 0x12345678) + __builtin_abort (); + return 0; +} Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c (nonexistent) +++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c (working copy) @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fstrict-aliasing" } */ + +union U { + struct A { int : 2; int x : 8; } a; + struct B { int : 6; int x : 8; } b; +}; + +int __attribute__((noipa)) +foo (union U *p, union U *q) +{ + p->a.x = 1; + q->b.x = 1; + return p->a.x; +} + +int +main() +{ + union U x; + if (foo (&x, &x) != x.a.x) + __builtin_abort (); + return 0; +} + +/* We support arbitrary punning through unions when it happens through + the union type and thus p == q is valid here. */ Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c (revision 273226) +++ gcc/tree-ssa-sccvn.c (working copy) @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. #include "tree-ssa-loop.h" #include "tree-scalar-evolution.h" #include "tree-ssa-loop-niter.h" +#include "builtins.h" #include "tree-ssa-sccvn.h" /* This algorithm is based on the SCC algorithm presented by Keith @@ -1993,23 +1994,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree /* If we reach a clobbering statement try to skip it and see if we find a VN result with exactly the same value as the possible clobber. In this case we can ignore the clobber - and return the found value. - Note that we don't need to worry about partial overlapping - accesses as we then can use TBAA to disambiguate against the - clobbering statement when looking up a load (thus the - VN_WALKREWRITE guard). */ + and return the found value. */ if (vn_walk_kind == VN_WALKREWRITE && is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) - /* The overlap restriction breaks down when either access - alias-set is zero. Still for accesses of the size of - an addressable unit there can be no overlaps. Overlaps - between different union members are not an issue since - activation of a union member via a store makes the - values of untouched bytes unspecified. */ - && (known_eq (ref->size, BITS_PER_UNIT) - || (get_alias_set (lhs) != 0 - && ao_ref_alias_set (ref) != 0))) + && ref->ref) { tree *saved_last_vuse_ptr = last_vuse_ptr; /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ @@ -2026,7 +2015,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree vn_reference_t vnresult = (vn_reference_t) res; if (vnresult->result && operand_equal_p (vnresult->result, - gimple_assign_rhs1 (def_stmt), 0)) + gimple_assign_rhs1 (def_stmt), 0) + /* We have to honor our promise about union type punning + and also support arbitrary overlaps with + -fno-strict-aliasing. So simply resort to alignment to + rule out overlaps. Do this check last because it is + quite expensive compared to the hash-lookup above. */ + && multiple_p (get_object_alignment (ref->ref), ref->size) + && multiple_p (get_object_alignment (lhs), ref->size)) return res; } }