[X86] Is it possible to implicitly promote a virtual subregister to a super?

Hi All,

Suppose I have in X86 MIR SSA:

Register WideReg = MRI->createVirtualRegister(&X86::GR32RegClass);

Register NarrowReg = MRI->createVirtualRegister(&X86::GR16RegClass);

// Generate other instructions that def WideReg and NarrowReg

BuildMI(MBB, InsertPt, Loc, TII->get(CMP32rr), WideReg).addReg(NarrowReg);

The above will not pass with --verify-machineinstrs and the CMP32rr will print to something like:

// other instructions that def %ax and %ebx

cmpl %ax, %ebx

Is it possible to implicitly “promote” (for lack of a better word) the 16-bit GPR into its 32-bit super? The output should look like:

// other instructions that def %ax and %ebx

cmpl %eax, %ebx

Thanks in advance,

Scott Constable

Not implicitly, you need another vreg with class GR32 and some
operation to widen the narrow one. And actually you probably need that
to be a real sign/zero extension or something because I don't think
x86 clears the high bits of eax when writing to ax, does it?

If it was 32 -> 64 bit, I think the rules are different and rax would
be zero-extended automatically. In that case you could use a
SUBREG_TO_REG which would eventually go away.



Hi Tim,

One of the first things I tried was to insert a zero extend 16-to-32-bit instruction, but that also caused an additional 32-bit physical register to be generated, which is not what I want.

The actual implementation I'm doing is a bit more complex than the example I provided for illustrative purposes. In my case, I don't need to care about the upper bits at all.



OK, in that case I think SUBREG_TO_REG is what you want. Something like

BuildMI(MBB, InsertPt, Loc, TII->get(X86::SUBREG_TO_REG), ExtendedReg)
    .addImm(0) // Never been entirely sure what this was here for.
It's always 0.

then use ExtendedReg (a GR32 vreg) in the compare.



If there’s no guarantee of a value for the upper bits don’t you want INSERT_SUBREG? SUBREG_TO_REG says the upper bits are 0(or whatever the immediate says). Not that I’ve ever found a place that checks it.

Ah yes, I think you're right there. That's annoying, it's uglier to use:

BuildMI(MBB, InsertPt, Loc, TII->get(X86::IMPLICIT_DEF), UndefReg);
BuildMI(MBB, InsertPt, Loc, TII->get(X86::INSERT_SUBREG), ExtendedReg)


Thanks Tim and Craig. I tried both of your suggestions, and both generate the correct machine code for the test examples I have written. Looking at the documentation for SUBREG_TO_REG:

/// SUBREG_TO_REG - This instruction is similar to INSERT_SUBREG except that

/// the first operand is an immediate integer constant. This constant is

/// often zero, because it is commonly used to assert that the instruction

/// defining the register implicitly clears the high bits.

So I think I agree with Craig that the more natural solution is to stick with INSERT_SUBREG.