get_memreg_parts can return a memory base other than a REG, when the memory address in question is a PLUS with other than a REG as its first operand. This leads to an ICE with rtl checking enabled on the following, since the callers of get_memreg_parts expect a REG.
(gdb) p debug_rtx(addr_rtx) (plus:DI (plus:DI (reg/f:DI 9 9 [162]) (const_int 65536 [0x10000])) (const_int -31752 [0xffffffffffff83f8])) Bootstrapped and regression tested powerpc64-linux. OK for stage4? PR target/65182 * config/rs6000/rs6000.c (get_memref_parts): Only return true when *base is a reg. Handle nested plus addresses. Simplify pre_modify test. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 220902) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -27172,25 +27172,21 @@ get_memref_parts (rtx mem, rtx *base, HOST_WIDE_IN else return false; - if (GET_CODE (XEXP (mem, 0)) == PRE_MODIFY) - addr_rtx = XEXP (XEXP (mem, 0), 1); - else - addr_rtx = (XEXP (mem, 0)); + addr_rtx = (XEXP (mem, 0)); + if (GET_CODE (addr_rtx) == PRE_MODIFY) + addr_rtx = XEXP (addr_rtx, 1); - if (GET_CODE (addr_rtx) == REG) + *offset = 0; + while (GET_CODE (addr_rtx) == PLUS + && CONST_INT_P (XEXP (addr_rtx, 1))) { - *base = addr_rtx; - *offset = 0; + *offset += INTVAL (XEXP (addr_rtx, 1)); + addr_rtx = XEXP (addr_rtx, 0); } - else if (GET_CODE (addr_rtx) == PLUS - && CONST_INT_P (XEXP (addr_rtx, 1))) - { - *base = XEXP (addr_rtx, 0); - *offset = INTVAL (XEXP (addr_rtx, 1)); - } - else + if (!REG_P (addr_rtx)) return false; + *base = addr_rtx; return true; } -- Alan Modra Australia Development Lab, IBM