https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121362
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 Last reconfirmed| |2025-08-02 Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot gnu.org Status|UNCONFIRMED |ASSIGNED --- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- FRE1 gets to see struct s3 * t; struct s1 tmp; struct s2 c; int _1; int _2; __BB(2): tmp.t = a_4(D); tmp.t1 = b_6(D); __MEM <struct s3> ((struct s3 *)&c).t = tmp; (*) tmp ={v} _Literal (struct s1) {CLOBBER(eos)}; _1 = c.t.t.t1; _2 = c.t.t.t; f (_2, _1); c ={v} _Literal (struct s2) {CLOBBER(eos)}; and when at (*) we try to match up {component_ref<t1>,component_ref<t>,component_ref<t>,mem_ref<0B>,addr_expr<&c>} with {component_ref<t>,mem_ref<0B>,addr_expr<&c>} and the only match we have is the addr_expr, so we didn't fully consume __MEM <struct s3> ((struct s3 *)&c).t, meaning that's not a base of the reference looked up. The /* ??? The innermost op should always be a MEM_REF and we already checked that the assignment to the lhs kills vr. Thus for aggregate copies using char[] types the vn_reference_op_eq may fail when comparing types for compatibility. But we really don't care here - further lookups with the rewritten operands will simply fail if we messed up types too badly. */ poly_int64 extra_off = 0; if (j == 0 && i >= 0 && lhs_ops[0].opcode == MEM_REF && maybe_ne (lhs_ops[0].off, -1)) { if (known_eq (lhs_ops[0].off, vr->operands[i].off)) i--, j--; else if (vr->operands[i].opcode == MEM_REF && maybe_ne (vr->operands[i].off, -1)) { extra_off = vr->operands[i].off - lhs_ops[0].off; i--, j--; } } code looks a bit confused. I'll have to check what I added this for... But in essence we can try to match up a sequence of zero-offset components in a more relaxed way, and appearantly with extra_off even more. I have to re-familiarize myself with this.