a question about copyPhysReg

Hi,

I have a question related to copyPhysReg. Suppose in the target backend, there is a register class can be i16 and i32, like this

def GRRegs : RegisterClass<“FOO”, [i16, i32], 32,
(add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15)>;

Then I define two ‘move’ instructions to lower the ‘COPY’: one for i32, the other for i16. However, because i16 and i32 share same register class, when defining the two ‘move’ instructions, I have something like following, which cannot work correctly:

def MOVEI32 : InstFOO<(outs GRRegs:$dst), (ins GRRegs:$src), “move $dst, $src”,[]>;

def MOVEI16 : InstFOO<(outs GRRegs:$dst), (ins GRRegs:$src), “move-i16 $dst, $src”,[]>;

Then the copyPhysReg looks like this:

if(FOO::GRRegsRegClass.contains(DestReg, SrcReg)){
BuildMI(MBB, I, I->getDebugLoc(), get(FOO::MOVEI32), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
}else if(FOO::GRRegClass.contains(DestReg, SrcReg)){
BuildMI(MBB, I, I->getDebugLoc(), get(FOO::MOVEI16), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
}

My implementation is wrong actually. Because it cannot differentiate the ‘move’ and ‘move-i16’. However, I have no idea to make it work. One thought is to define two register classes (one for i16, the other for i32. And they share same registers) like the follwing. Then for ‘move’ instructions and copyPhyReg use the different register classes. But this doesn’t work either because after ‘virtual register rewriter’ pass, the register class information is gone (e.g. we don’t know the virtual register R0 belongs to GRRegs0 or GRRegs1). In addition, I’m not sure if this (e.g. let one register belongs to two register classes) is safe? Any suggestion/hint are appreciated. Thanks.

def GRRegs0 : RegisterClass<“FOO”, [i16], 32,
(add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15)>;

def GRRegs1 : RegisterClass<“FOO”, [i32], 32,
(add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15)>;

Regards,

Xiangyang

Hi Xiangyang,

My implementation is wrong actually. Because it cannot differentiate the
'move' and 'move-i16'. However, I have no idea to make it work. One thought
is to define two register classes (one for i16, the other for i32. And they
share same registers) like the follwing. Then for 'move' instructions and
copyPhyReg use the different register classes. But this doesn't work either
because after 'virtual register rewriter' pass, the register class
information is gone (e.g. we don't know the virtual register R0 belongs to
GRRegs0 or GRRegs1). In addition, I'm not sure if this (e.g. let one
register belongs to two register classes) is safe? Any suggestion/hint are
appreciated. Thanks.

Having registers in two different classes is fine, but as you've seen
you don't always have a register class available. I think LLVM would
model this with sub-registers (so both R0_32 and R0_16 exist, for
example -- I'm sure you could come up with better names). It's easier
if the 16-bit versions are written differently (x86's eax/ax,
AArch64's x0/w0, ...) but that's probably reasonably easy to hack
around in the assembler.

Either that, or you could simply always copy the full 32-bits in
copyPhysReg. I can't see any particular harm in that unless the 16-bit
copy is more efficient or something.

Cheers.

Tim.