https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95493
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> --- Now, the real issue is of course that we fail to properly expand the inner MEM_REF since get_inner_reference strips that away and so we expand the decl resulting in bogus mem_attrs being applied. That is, we like to fix the set_mem_attrs_minus_bitpos without clearing attrs.expr but that makes the testcase still fail. Now, in this particular case the MEM_ATTRs should be still fine (the access modification on the MEM_REF is a simple down-cast) so we _do_ have an underlying issue in path-based disambiguation I think. Or from the !MEM_OFFSET_KNOWN_P path in ao_ref_from_mem which makes the access appear as a full def of the structure (but that shouldn't be wrong here either). In aliasing_component_refs_p cmp_outer is zero (accesses have the same size), then aliasing_component_refs_walk figures cmp == 0 && same_p == 0 for record_type 0x7ffff6975e70 ._anon_0 and record_type 0x7ffff6975d20 SW. In the opposite direction it suddenly is cmp == 1 for vector_type 0x7ffff696bdc8 K (size 128) and record_type 0x7ffff6975e70 ._anon_0 (size 128)!? That's because compare_type_sizes special-handling of arrays and vectors. So we get non-conclusive result here as well but maybe_match remains false (don't we need to set maybe_match to true here?) So we fall down to return (base2_alias_set == ref1_alias_set || alias_set_subset_of (base2_alias_set, ref1_alias_set)); but oddly enough we have base2_alias_set 4 and ref1_alias_set 1 here which does not match up as ref1_type has alias-set 5. That might be because we have MEM_KEEP_ALIAS_SET_P set on the RTX. Documented as /* 1 if RTX is a mem and we should keep the alias set for this mem unchanged when we access a component. Set to 1, or example, when we are already in a non-addressable component of an aggregate. */ #define MEM_KEEP_ALIAS_SET_P(RTX) \ this "optimization" defeats the assumptions by path-based disambiguation which expects a match between alias sets and components here. The flag is set because of the VIEW_CONVERT_EXPR. Ah, and we've updated the alias-set from the VIEW_CONVERT_EXPR<int[4]>(MEM[(struct SW &)&xx].d)[i.1_2] expression but choose to keep the original one (which had a different alias-set). That's another source of confusion for the path-based disambiguation. If we fix that down the drain store_field will break it again via 7249 if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0) 7250 set_mem_alias_set (to_rtx, alias_set); we can fix _that_ by adjusting the caller to preserve a MEM_ALIAS_SET if present rather than looking at the GENERIC tree again.