This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Indirect memory addresses vs. lra



On 2019-08-04 3:18 p.m., John Darrington wrote:
I'm trying to write a back-end for an architecture (s12z - the ISA you can
download from [1]).  This arch accepts indirect memory addresses.   That is to
say, those of the form (mem (mem (...)))  and although my TARGET_LEGITIMATE_ADDRESS
function returns true for such addresses, LRA insists on reloading them out of
existence.

For example, when compiling a code fragment:

   volatile unsigned char *led = 0x2F2;
   *led = 1;

the ira dump file shows:

(insn 7 6 8 2 (set (mem/f/c:PSI (reg/f:PSI 9 y) [3 led+0 S4 A8])
         (const_int 754 [0x2f2])) "/home/jmd/MemMem/memmem.c":15:27 96 {movpsi}
      (nil))
(insn 8 7 14 2 (set (mem/v:QI (mem/f/c:PSI (reg/f:PSI 9 y) [3 led+0 S4 A8]) [0 *led_7+0 S1 A8])
         (const_int 1 [0x1])) "/home/jmd/MemMem/memmem.c":16:8 98 {movqi}
      (nil))

which is a perfectly valid insn, and the most efficient assembler for it is:
mov.p #0x2f2, y
mov.b #1, [0,y]

However the reload dump shows this has been changed to:

(insn 7 6 22 2 (set (mem/f/c:PSI (reg/f:PSI 9 y) [3 led+0 S4 A8])
         (const_int 754 [0x2f2])) "/home/jmd/MemMem/memmem.c":15:27 96 {movpsi}
      (nil))
(insn 22 7 8 2 (set (reg:PSI 8 x [22])
         (mem/f/c:PSI (reg/f:PSI 9 y) [3 led+0 S4 A8])) "/home/jmd/MemMem/memmem.c":16:8 96 {movpsi}
      (nil))
(insn 8 22 14 2 (set (mem/v:QI (reg:PSI 8 x [22]) [0 *led_7+0 S1 A8])
         (const_int 1 [0x1])) "/home/jmd/MemMem/memmem.c":16:8 98 {movqi}
      (nil))

and ends up as:

mov.p #0x2f2, y
mov.p (0,y) x
mov.b #1, (0,x)

So this wastes a register (which leads to other issues which I don't want to go
into in this email).

After a lot of debugging I tracked down the part of lra which is doing this
reload to the function process_addr_reg at lra-constraints.c:1378

  if (! REG_P (reg))
     {
       if (check_only_p)
         return true;
       /* Always reload memory in an address even if the target supports such addresses.  */
       new_reg = lra_create_new_reg_with_unique_value (mode, reg, cl, "address");
       before_p = true;
     }

Changing this to

  if (! REG_P (reg))
     {
       if (check_only_p)
         return true;
       return false;
     }

solves my immediate problem.  However I imagine there was a reason for doing
this reload, and presumably a better way of avoiding it.

Can someone explain the reason for this reload, and how I can best ensure that
indirect memory operands are left in the compiled code?

The old reload (reload[1].c) supports such addressing.  As modern mainstream architectures have no this kind of addressing, it was not implemented in LRA.

I don't think the above simple change will work fully.  For example, you need to constrain memory nesting.  The constraints should be described, may be some hooks should be implemented (may be not and TARGET_LEGITIMATE_ADDRESS will be enough), may be additional address anslysis and transformations should be implemented in LRA, etc.  But may be implementing this is not hard either.

It is also difficult for me to say is it worth to do.  Removing such addressing helps to remove redundant memory reads.  On the other hand, its usage can decrease #insns and save registers for better RA and utilize hardware on design of which a lot of efforts were spent.

In any case, if somebody implements this, it can be included in LRA.


[1] https://www.nxp.com/docs/en/reference-manual/S12ZCPU_RM_V1.pdf



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]