FRE/PREs redundant store removal code doesn't honor the middle-end memory model which says that all stores change the dynamic type of the affected memory region. So it removed the second 'int' store in
MEM[(int *)p_3] = 1; MEM[(double *)p_3] = 0.0; MEM[(int *)p_3] = 1; which is not valid (if not done later DSE removes the first int store which _is_ valid). So I am bootstrapping and testing the following fix on x86_64-unknown-linux-gnu. Richard. 2016-02-12 Richard Biener <rguent...@suse.de> PR tree-optimization/69776 * tree-ssa-sccvn.h (vn_reference_lookup): Adjust prototype. * tree-ssa-sccvn.c (vn_reference_lookup): Add parameter to indicate whether we can use TBAA to disambiguate against stores. Use alias-set zero if not. (visit_reference_op_store): Do not use TBAA when looking up redundant stores. * tree-ssa-pre.c (compute_avail): Use TBAA here. (eliminate_dom_walker::before_dom_children): But not when looking up redundant stores. * gcc.dg/torture/pr69776.c: New testcase. Index: gcc/tree-ssa-sccvn.h =================================================================== *** gcc/tree-ssa-sccvn.h (revision 233369) --- gcc/tree-ssa-sccvn.h (working copy) *************** bool ao_ref_init_from_vn_reference (ao_r *** 216,222 **** tree vn_reference_lookup_pieces (tree, alias_set_type, tree, vec<vn_reference_op_s> , vn_reference_t *, vn_lookup_kind); ! tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *); void vn_reference_lookup_call (gcall *, vn_reference_t *, vn_reference_t); vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree, vec<vn_reference_op_s> , --- 216,222 ---- tree vn_reference_lookup_pieces (tree, alias_set_type, tree, vec<vn_reference_op_s> , vn_reference_t *, vn_lookup_kind); ! tree vn_reference_lookup (tree, tree, vn_lookup_kind, vn_reference_t *, bool); void vn_reference_lookup_call (gcall *, vn_reference_t *, vn_reference_t); vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree, vec<vn_reference_op_s> , Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 233369) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_reference_lookup_pieces (tree vuse, a *** 2230,2240 **** number if it exists in the hash table. Return NULL_TREE if it does not exist in the hash table or if the result field of the structure was NULL.. VNRESULT will be filled in with the vn_reference_t ! stored in the hashtable if one exists. */ tree vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, ! vn_reference_t *vnresult) { vec<vn_reference_op_s> operands; struct vn_reference_s vr1; --- 2230,2241 ---- number if it exists in the hash table. Return NULL_TREE if it does not exist in the hash table or if the result field of the structure was NULL.. VNRESULT will be filled in with the vn_reference_t ! stored in the hashtable if one exists. When TBAA_P is false assume ! we are looking up a store and treat it as having alias-set zero. */ tree vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind, ! vn_reference_t *vnresult, bool tbaa_p) { vec<vn_reference_op_s> operands; struct vn_reference_s vr1; *************** vn_reference_lookup (tree op, tree vuse, *** 2264,2269 **** --- 2265,2272 ---- || !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type, vr1.operands)) ao_ref_init (&r, op); + if (! tbaa_p) + r.ref_alias_set = r.base_alias_set = 0; vn_walk_kind = kind; wvnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, *************** visit_reference_op_load (tree lhs, tree *** 3350,3356 **** last_vuse = gimple_vuse (stmt); last_vuse_ptr = &last_vuse; result = vn_reference_lookup (op, gimple_vuse (stmt), ! default_vn_walk_kind, NULL); last_vuse_ptr = NULL; /* We handle type-punning through unions by value-numbering based --- 3353,3359 ---- last_vuse = gimple_vuse (stmt); last_vuse_ptr = &last_vuse; result = vn_reference_lookup (op, gimple_vuse (stmt), ! default_vn_walk_kind, NULL, true); last_vuse_ptr = NULL; /* We handle type-punning through unions by value-numbering based *************** visit_reference_op_store (tree lhs, tree *** 3472,3478 **** Otherwise, the vdefs for the store are used when inserting into the table, since the store generates a new memory state. */ ! result = vn_reference_lookup (lhs, vuse, VN_NOWALK, NULL); if (result) { --- 3475,3481 ---- Otherwise, the vdefs for the store are used when inserting into the table, since the store generates a new memory state. */ ! result = vn_reference_lookup (lhs, vuse, VN_NOWALK, NULL, false); if (result) { *************** visit_reference_op_store (tree lhs, tree *** 3487,3493 **** && default_vn_walk_kind == VN_WALK) { assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op); ! vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult); if (vnresult) { VN_INFO (vdef)->use_processed = true; --- 3490,3496 ---- && default_vn_walk_kind == VN_WALK) { assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op); ! vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false); if (vnresult) { VN_INFO (vdef)->use_processed = true; Index: gcc/tree-ssa-pre.c =================================================================== *** gcc/tree-ssa-pre.c (revision 233369) --- gcc/tree-ssa-pre.c (working copy) *************** compute_avail (void) *** 3745,3751 **** vn_reference_t ref; vn_reference_lookup (gimple_assign_rhs1 (stmt), gimple_vuse (stmt), ! VN_WALK, &ref); if (!ref) continue; --- 3745,3751 ---- vn_reference_t ref; vn_reference_lookup (gimple_assign_rhs1 (stmt), gimple_vuse (stmt), ! VN_WALK, &ref, true); if (!ref) continue; *************** eliminate_dom_walker::before_dom_childre *** 4208,4214 **** tree val; tree rhs = gimple_assign_rhs1 (stmt); val = vn_reference_lookup (gimple_assign_lhs (stmt), ! gimple_vuse (stmt), VN_WALK, NULL); if (TREE_CODE (rhs) == SSA_NAME) rhs = VN_INFO (rhs)->valnum; if (val --- 4208,4214 ---- tree val; tree rhs = gimple_assign_rhs1 (stmt); val = vn_reference_lookup (gimple_assign_lhs (stmt), ! gimple_vuse (stmt), VN_WALK, NULL, false); if (TREE_CODE (rhs) == SSA_NAME) rhs = VN_INFO (rhs)->valnum; if (val Index: gcc/testsuite/gcc.dg/torture/pr69776.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr69776.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr69776.c (working copy) *************** *** 0 **** --- 1,28 ---- + /* { dg-do run } */ + /* { dg-additional-options "-fstrict-aliasing" } */ + + extern void *malloc (__SIZE_TYPE__); + extern void abort (void); + + void __attribute__((noinline,noclone)) + foo (int *pi) + { + if (*pi != 1) + abort (); + } + + int + main() + { + void *p = malloc(sizeof (double)); + int *pi = p; + double *pd = p; + + *pi = 1; + int a = *pi; + *pd = 0; + *pi = a; + foo (pi); + + return 0; + }