https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86062
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2018-06-06 Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- Confirmed. The issue is that when trying to translate MEM[(struct I *)&res + 8B] through the aggregate copy res = MEM[(const struct I &)&D.25143][1]; we run into /* Now re-write REF to be based on the rhs of the assignment. */ copy_reference_ops_from_ref (gimple_assign_rhs1 (def_stmt), &rhs); /* Apply an extra offset to the inner MEM_REF of the RHS. */ if (maybe_ne (extra_off, 0)) { if (rhs.length () < 2 || rhs[0].opcode != MEM_REF || known_eq (rhs[0].off, -1)) return (void *)-1; where the rhs ref is an ARRAY_REF of a MEM_REF. This is a TBAA issue IIRC (at least when the translated ref would end up in PRE insertion somehow - PRE doesn't run into this code though). The following untested fixes it but as said I'm not 100% sure it's safe. diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 4e946ba7baf..4aec41e96c1 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2270,14 +2270,16 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_, /* Apply an extra offset to the inner MEM_REF of the RHS. */ if (maybe_ne (extra_off, 0)) { - if (rhs.length () < 2 - || rhs[0].opcode != MEM_REF - || known_eq (rhs[0].off, -1)) + if (rhs.length () < 2) return (void *)-1; - rhs[0].off += extra_off; - rhs[0].op0 = int_const_binop (PLUS_EXPR, rhs[0].op0, - build_int_cst (TREE_TYPE (rhs[0].op0), - extra_off)); + int ix = rhs.length () - 2; + if (rhs[ix].opcode != MEM_REF + || known_eq (rhs[ix].off, -1)) + return (void *)-1; + rhs[ix].off += extra_off; + rhs[ix].op0 = int_const_binop (PLUS_EXPR, rhs[ix].op0, + build_int_cst (TREE_TYPE (rhs[ix].op0), + extra_off)); } /* We need to pre-pend vr->operands[0..i] to rhs. */