https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96879

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
This is an aarch64 backend bug (I needed -fno-section-anchors to trigger
though).
aarch64_expand_mov_immediate has:
        case SYMBOL_FORCE_TO_MEM:
          if (const_offset != 0
              && targetm.cannot_force_const_mem (int_mode, imm))
            {
              gcc_assert (can_create_pseudo_p ());
              base = aarch64_force_temporary (int_mode, dest, base);
              aarch64_add_offset (int_mode, dest, base, const_offset,
                                  NULL_RTX, NULL_RTX, false);
              return;
            }

          mem = force_const_mem (ptr_mode, imm);
          gcc_assert (mem);
and is called with int_mode DImode and imm is a DImode SYMBOL_REF.  As ptr_mode
is SImode, the call to force_const_mem is invalid:
/* Given a constant rtx X, make (or find) a memory constant for its value
   and return a MEM rtx to refer to it in memory.  IN_MODE is the mode
   of X.  */
In particular, IN_MODE is not the mode of X in this case (the reason for the
mode is only for the case of VOIDmode constants).
So, either force_const_mem should be called with lowpart_subreg of imm if
ptr_mode != int_mode, or it should be called with int_mode instead of ptr_mode
and then the later ZERO_EXTEND should not be done.
As it seems before my constant pool optimizations such bogus constant pool
entry assembled into .word the_immediate, doing a lowpart subreg is probably
the right way to go.
So perhaps:
--- gcc/config/aarch64/aarch64.c.jj     2020-08-24 10:00:01.299258763 +0200
+++ gcc/config/aarch64/aarch64.c        2020-09-01 10:34:50.096468522 +0200
@@ -5131,6 +5131,7 @@ aarch64_expand_mov_immediate (rtx dest,
              return;
            }

+         imm = lowpart_subreg (ptr_mode, imm, int_mode);
          mem = force_const_mem (ptr_mode, imm);
          gcc_assert (mem);

except I don't know if it will handle the (const:DI (symbol_ref:DI whatever)
(const_int 32)) case properly.
Also, few lines above this the targetm.cannot_force_const_mem call using
int_mode rather than ptr_mode when it later uses ptr_mode is kind of weird.

Reply via email to