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);

Reply via email to