In this BZ we generate a modeless REG and as a result eventually ICE gen_addr_rtx takes a symbol, base, index, step and offset from a MEM_REF and constructs suitable RTL for the address. The caller in question (addr_for_mem_ref) will use expand_expr on the above objects to turn them from trees into suitable RTL.
If the base is an SSA_NAME with a constant value (consider we may be compiling with -O1 and fail to propagate away the SSA_NAME), then expand_expr will return the constant rather than a REG, which we pass as base to gen_addr_rtx which will ultimately generate something like (plus (const_int) (const_int)) ^^^ ^^^ base offset Later we want the first argument of the PLUS to be a REG, so we extract the mode from the constant int and use that to generate the REG expression and we've lost because constants are modeless. We could simplify those within gen_addr_rtx. In fact that's precisely what my first patch did. But gen_addr_rtx itself assumes that the form will be (plus (base) (offset)) and will reference the XEXP (addr, 1) which in the case we care about doesn't exist after simplification. That can be worked around with some surgery, but it's actually easier to fix in the caller. So in the caller (addr_for_mem_ref) if we detect that the base, after expansion, is a CONST_INT, we fold it into the offset and set the base to NULL_RTX (gen_addr_rtx is prepared to handle this scenario). This is active in gcc-9 and the trunk, but latent on the older release branches. I'm going to commit to the trunk and backport after suitable soak time. Bootstrapped and regression tested on x86_64, ppc64, ppc64le & sparc (aarch64 failed its comparison test due to an unrelated issue). It's also been regression tested on various *-elf platforms. Jeff
commit a0efaa5c1185e6db605c4b16866c9bbbdea8f149 Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Tue Jul 16 14:44:44 2019 +0000 PR rtl-optimization/91173 * tree-ssa-address.c (addr_for_mem_ref): If the base is an SSA_NAME with a constant value, fold its value into the offset and clear the base before calling gen_addr_rtx. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@273529 138bc75d-0d04-0410-961f-82ee72b054a4 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1eb2797d85f..2bce569e320 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2019-07-16 Jeff Law <l...@redhat.com> + + PR rtl-optimization/91173 + * tree-ssa-address.c (addr_for_mem_ref): If the base is an + SSA_NAME with a constant value, fold its value into the offset + and clear the base before calling gen_addr_rtx. + 2019-07-16 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/91164 diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index e83e1b9296f..8004951d2e8 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -259,6 +259,20 @@ addr_for_mem_ref (struct mem_address *addr, addr_space_t as, ? expand_expr (addr->index, NULL_RTX, pointer_mode, EXPAND_NORMAL) : NULL_RTX); + /* addr->base could be an SSA_NAME that was set to a constant value. The + call to expand_expr may expose that constant. If so, fold the value + into OFF and clear BSE. Otherwise we may later try to pull a mode from + BSE to generate a REG, which won't work with constants because they + are modeless. */ + if (bse && GET_CODE (bse) == CONST_INT) + { + if (off) + off = simplify_gen_binary (PLUS, pointer_mode, bse, off); + else + off = bse; + gcc_assert (GET_CODE (off) == CONST_INT); + bse = NULL_RTX; + } gen_addr_rtx (pointer_mode, sym, bse, idx, st, off, &address, NULL, NULL); if (pointer_mode != address_mode) address = convert_memory_address (address_mode, address);