Hi,

Is there a way to force the compiler to consider an operand dead?

Specifically, I've got the RL78 backend to generate SET1 and CLR1 instructions to set and clear individual bits. These instructions can either work on the contents of a specific memory address, or indirectly by putting the memory address into the HL register.

If more than one bit in a given byte should be set or cleared, the compiler uses the indirect alternative but in most cases this actually leads to larger code especially if not all bit operations on any given memory address are performed sequentially (e.g. 'clear bit 3 of address X, set bit 6 of address Y, set bit 1 of address X').

--------------------------------------------------------
typedef struct {
   unsigned char no0 :1;
   unsigned char no1 :1;
   unsigned char no2 :1;
   unsigned char no3 :1;
   unsigned char no4 :1;
   unsigned char no5 :1;
   unsigned char no6 :1;
   unsigned char no7 :1;
} __BITS8;

#define MEMREG (*(volatile __BITS8*)0xFFF0C)

void test()
{
   MEMREG.no1 = 1;
   MEMREG.no2 = 0;
}
--------------------------------------------------------

Produces:

  28                                    _test:
  29 0000 36 0C FF                              movw    hl, #-244
  30 0003 71 92                                 set1    [hl].1
  31 0005 71 A3                                 clr1    [hl].2
  32 0007 D7                                    ret

Where this would be more efficient (and in real-world situations much more so):

  28                                    _test:
  29 0000 71 1A 0C                              set1    0xfff0c.1
  30 0003 71 2B 0C                              clr1    0xfff0c.2
  31 0006 D7                                    ret



The problem seems to be during the combine phase. With the second MEMREG line commented out:

--------------------------------------------------------
Trying 9 -> 10:
Successfully matched this instruction:
(set (mem/v/j:QI (reg/f:HI 44) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16]) (ior:QI (mem/v/j:QI (reg/f:HI 44) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16])
        (const_int 2 [0x2])))
deferring deletion of insn with uid = 9.
modifying insn i3    10: [r44:HI]=[r44:HI]|0x2
      REG_DEAD r44:HI
deferring rescan insn with uid = 10.

Trying 6 -> 10:
Successfully matched this instruction:
(set (mem/v/j:QI (const_int -244 [0xffffffffffffff0c]) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16]) (ior:QI (mem/v/j:QI (const_int -244 [0xffffffffffffff0c]) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16])
        (const_int 2 [0x2])))
deferring deletion of insn with uid = 6.
modifying insn i3    10: [0xffffffffffffff0c]=[0xffffffffffffff0c]|0x2
deferring rescan insn with uid = 10.
starting the processing of deferred insns
rescanning insn with uid = 10.
ending the processing of deferred insns
--------------------------------------------------------

With both lines active:

--------------------------------------------------------
Trying 9 -> 10:
Successfully matched this instruction:
(set (mem/v/j:QI (reg/f:HI 44) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16]) (ior:QI (mem/v/j:QI (reg/f:HI 44) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16])
        (const_int 2 [0x2])))
deferring deletion of insn with uid = 9.
modifying insn i3    10: [r44:HI]=[r44:HI]|0x2
deferring rescan insn with uid = 10.

Trying 6 -> 10:
Failed to match this instruction:
(parallel [
(set (mem/v/j:QI (const_int -244 [0xffffffffffffff0c]) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16]) (ior:QI (mem/v/j:QI (const_int -244 [0xffffffffffffff0c]) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16])
                (const_int 2 [0x2])))
        (set (reg/f:HI 44)
            (const_int -244 [0xffffffffffffff0c]))
    ])
Failed to match this instruction:
(parallel [
(set (mem/v/j:QI (const_int -244 [0xffffffffffffff0c]) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16]) (ior:QI (mem/v/j:QI (const_int -244 [0xffffffffffffff0c]) [3 MEM[(volatile struct __BITS8 *)65292B].no1+0 S1 A16])
                (const_int 2 [0x2])))
        (set (reg/f:HI 44)
            (const_int -244 [0xffffffffffffff0c]))
    ])
--------------------------------------------------------

The second example leaves the destination operand 'alive', and fails to find a match for the direct-addressing alternative.

Is there any way of preventing the compiler going with the indirect alternative? Can a 'parallel' match be defined in the machine description that indicates the '(set (reg/f:HI...' should be discarded?

Thanks in advance,

Richard.

Reply via email to