https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116145
Richard Sandiford <rsandifo at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rsandifo at gcc dot gnu.org --- Comment #6 from Richard Sandiford <rsandifo at gcc dot gnu.org> --- The problem seems to be that may_trap_or_fault_p returns true for the memory, which stops loop2_invariant from hoisting the load. The code there is: if (/* MEM_NOTRAP_P only relates to the actual position of the memory reference; moving it out of context such as when moving code when optimizing, might cause its address to become invalid. */ code_changed || !MEM_NOTRAP_P (x)) { poly_int64 size = MEM_SIZE_KNOWN_P (x) ? MEM_SIZE (x) : -1; return rtx_addr_can_trap_p_1 (XEXP (x, 0), 0, size, GET_MODE (x), code_changed); } (where code_changed is true). Since the SVE load doesn't support the full LO_SUM range, there is no hint that the address refers to invariant memory. I'm not sure the comment in the code is correct for MEM_READONLY_P, which only refers to _statically allocated_ readonly memory. (At least, the comment doesn't apply to constant memory created by force_const_mem, which creates things that cannot trap regardless of context.) Adding: if (MEM_READONLY_P (x) && MEM_NOTRAP_P (x)) return false; makes the test work for me.