https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66142
--- Comment #21 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, so if we fix SCCVN further we hit its (designed) limitation with stmt walking not following backedges (but the use is in a loop and the def outside). We avoid doing the work to determine if sth is loop invariant here. This was trying to improve things with SRA disabled - I'm going to still push those changes if testing works out fine. Now with SRA enabled we have a better situation in this regard but face _9 = &D.4309[_12].org; MEM[(struct vec_ *)_9] = 1.0e+0; MEM[(struct vec_ *)_9 + 4B] = _8; D.4309[_12].dir.x = x_13; D.4309[_12].dir.y = y_14; D.4308[_12].t = 1.0e+10; D.4308[_12].h = 0; _20 = &D.4308[_12]; _26 = MEM[(const struct Ray *)&D.4309][_12].org.x; which as said isn't friendly enough for the simplistic address forward propagation we have. The issue here is that we can't disambiguate against MEM[(struct vec_ *)_9 + 4B] = _8; when looking up MEM[(const struct Ray *)&D.4309][_12].org.x; because vn_reference_maybe_forwprop_address doesn't forward into MEM[(struct vec_ *)_9 + 4B] as its offset is not zero: /* If that didn't work because the address isn't invariant propagate the reference tree from the address operation in case the current dereference isn't offsetted. */ if (!addr_base && *i_p == ops->length () - 1 && off == 0 /* This makes us disable this transform for PRE where the reference ops might be also used for code insertion which is invalid. */ && default_vn_walk_kind == VN_WALKREWRITE) { auto_vec<vn_reference_op_s, 32> tem; copy_reference_ops_from_ref (TREE_OPERAND (addr, 0), &tem); ops->pop (); ops->pop (); ops->safe_splice (tem); --*i_p; return true; it also likely wouldn't help vn_reference_lookup_3 to do the disambiguation as that performs just lhs_ops = valueize_refs_1 (lhs_ops, &valueized_anything); if (valueized_anything) { lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref, get_alias_set (lhs), TREE_TYPE (lhs), lhs_ops); if (lhs_ref_ok && !refs_may_alias_p_1 (ref, &lhs_ref, true)) return NULL; but there is still the variable offset to cope with. We'd need to perform some disambiguation on lhs_ref vs. vr. But it's not clear how to represent &D.4309[_12].org forwarded into MEM[(struct vec_ *)_9 + 4B]. It's kind-of a COMPONENT_REF with just a offset added. Let's collect the improvements I have sofar in my local tree and see if they otherwise work.