The following fixes PR71055. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard. 2016-05-11 Richard Biener <rguent...@suse.de> PR tree-optimization/71055 * tree-ssa-sccvn.c (vn_reference_lookup_3): When native-interpreting sth with precision not equal to access size verify we don't chop off bits. * gcc.dg/torture/pr71055.c: New testcase. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 236069) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1907,1920 **** buffer, sizeof (buffer)); if (len > 0) { ! tree val = native_interpret_expr (vr->type, buffer + ((offset - offset2) / BITS_PER_UNIT), ref->size / BITS_PER_UNIT); if (val) return vn_reference_lookup_or_insert_for_pieces ! (vuse, vr->set, vr->type, vr->operands, val); } } } --- 1950,1983 ---- buffer, sizeof (buffer)); if (len > 0) { ! tree type = vr->type; ! /* Make sure to interpret in a type that has a range ! covering the whole access size. */ ! if (INTEGRAL_TYPE_P (vr->type) ! && ref->size != TYPE_PRECISION (vr->type)) ! type = build_nonstandard_integer_type (ref->size, ! TYPE_UNSIGNED (type)); ! tree val = native_interpret_expr (type, buffer + ((offset - offset2) / BITS_PER_UNIT), ref->size / BITS_PER_UNIT); + /* If we chop off bits because the types precision doesn't + match the memory access size this is ok when optimizing + reads but not when called from the DSE code during + elimination. */ + if (val + && type != vr->type) + { + if (! int_fits_type_p (val, vr->type)) + val = NULL_TREE; + else + val = fold_convert (vr->type, val); + } + if (val) return vn_reference_lookup_or_insert_for_pieces ! (vuse, vr->set, vr->type, vr->operands, val); } } } Index: gcc/testsuite/gcc.dg/torture/pr71055.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr71055.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr71055.c (working copy) *************** *** 0 **** --- 1,18 ---- + /* { dg-do run } */ + + extern void abort (void); + union U { int i; _Bool b; char c; }; + void __attribute__((noinline,noclone)) + foo (union U *u) + { + if (u->c != 0) + abort (); + } + int main() + { + union U u; + u.i = 10; + u.b = 0; + foo (&u); + return 0; + }