https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67443
--- Comment #16 from Richard Biener <rguenth at gcc dot gnu.org> --- I see multiple issues with ao_ref_from_mem connected with MEM_OFFSET/MEM_SIZE. I don't remember exactly what was the issue with the promoted parameters but it may have been with ranges_overlap_p not dealing with signed offsets properly (that has been fixed meanwhile). So I'd start with simply removing /* If the base decl is a parameter we can have negative MEM_OFFSET in case of promoted subregs on bigendian targets. Trust the MEM_EXPR here. */ if (MEM_OFFSET (mem) < 0 && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size) return true; One issue that remains is that when MEM_OFFSET/MEM_SIZE gets us outside of the MEM_EXPR object (its offset/size) we have to strip handled-component-refs until MEM_OFFSET/MEM_SIZE are again within bounds (or conservatively reset ref->ref to NULL_TREE). Either the code adjusting the mem attributes MEM_OFFSET/MEM_SIZE is supposed to do that already (no idea) or we'll run into issues. Basically MEM_SIZE must be <= ref->size, MEM_OFFSET may never be negative unless ref->offset is zero and if MEM_OFFSET is positive then MEM_OFFSET + MEM_SIZE must be <= ref->size. It's of course a tricky area ;) I believe that /* If MEM_OFFSET and MEM_SIZE get us outside of the base object of the MEM_EXPR punt. This happens for STRICT_ALIGNMENT targets a lot. */ if (MEM_EXPR (mem) != get_spill_slot_decl (false) && (ref->offset < 0 || (DECL_P (ref->base) && (DECL_SIZE (ref->base) == NULL_TREE || TREE_CODE (DECL_SIZE (ref->base)) != INTEGER_CST || wi::ltu_p (wi::to_offset (DECL_SIZE (ref->base)), ref->offset + ref->size))))) return false; will ultimatively "save" us here as well (very conservatively though). So does Index: gcc/alias.c =================================================================== --- gcc/alias.c (revision 229022) +++ gcc/alias.c (working copy) @@ -339,15 +339,16 @@ ao_ref_from_mem (ao_ref *ref, const_rtx || !MEM_SIZE_KNOWN_P (mem)) return true; - /* If the base decl is a parameter we can have negative MEM_OFFSET in - case of promoted subregs on bigendian targets. Trust the MEM_EXPR - here. */ + /* If MEM_OFFSET/MEM_SIZE get us outside of ref->offset/ref->max_size + drop ref->ref. */ if (MEM_OFFSET (mem) < 0 - && (MEM_SIZE (mem) + MEM_OFFSET (mem)) * BITS_PER_UNIT == ref->size) - return true; + || (ref->max_size != -1 + && ((MEM_OFFSET (mem) + MEM_SIZE (mem)) * BITS_PER_UNIT + > ref->max_size))) + ref->ref = NULL_TREE; - /* Otherwise continue and refine size and offset we got from analyzing - MEM_EXPR by using MEM_SIZE and MEM_OFFSET. */ + /* Refine size and offset we got from analyzing MEM_EXPR by using + MEM_SIZE and MEM_OFFSET. */ ref->offset += MEM_OFFSET (mem) * BITS_PER_UNIT; ref->size = MEM_SIZE (mem) * BITS_PER_UNIT; fix the issue?