Problems defining (sub)registers


We have a problem in our target that occurs during the “detect dead lanes” pass. I think it stems from how we’ve defined our register classes and/or registers and/or subregisters. SubRegLiveness is enabled on our target.

Taking a simple example where A registers have two low/high “half” subregisters, and B registers have four “quarter” subregisters. They can both be used interchangeably by certain instructions, so we stick them into one register class.

foreach i = 0-31 in {

def A#i : Reg<[ALo, AHi], [ALoSRIdx, AHiSRIdx]>;
def B#i : Reg<[BQ0, BQ1, BQ2, BQ3], [BQ0SRIdx, BQ1SRIdx, BQ2SRIdx, BQ3SRIdx]>;


def ARegs : RegisterClass<…(sequence “A%u”, 0, 31)>;

def BRegs : RegisterClass<…(sequence “B%u”, 0, 31)>;

def SuperRegs : RegisterClass<…(add ARegs, BRegs)>;

The following input MIR copies from an A to a B through the intermediary superclass:

%0:aregs = COPY $a0

%1:superregs = COPY %0

%2:bregs = COPY %1

After dead lanes, we get:

dead %0:aregs = COPY $a0

%1:superregs = COPY undef %0

%2:bregs = COPY undef %1

I think that it’s because the subregister lanes of aregs and bregs don’t overlap, so it decides that %0 defines no used lanes? If the middle COPY is removed, so we have a copy directly from aregs to bregs, then dead-lanes detects a copy between incompatible classes and does not produce the incorrect code.

I haven’t found any documentation about how registers and register classes should (or, should not) be defined and the implicit restrictions placed upon them. Does anyone more familiar with the register and sub-register code know more about that we’re doing wrong? I believe that whatever is happening, it should be documented.

This happens in 4.01 and 7.1.0. I’m afraid I haven’t tried anything more recent than that.

Thanks in advance,