LiveIntervals, replace register with representative register?

I don't understand the following code snippet in LiveIntervalAnalysis.cpp.

Why changing the type of the opreand from a virtual register to a
machine register? The register number (reg) is still a virtual
register index (>1024).

bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
  // perform a final pass over the instructions and compute spill
  // weights, coalesce virtual registers and remove identity moves

  ...
        for (unsigned i = 0; i < mii->getNumOperands(); ++i) {
          const MachineOperand& mop = mii->getOperand(i);
          if (mop.isRegister() && mop.getReg() &&
              MRegisterInfo::isVirtualRegister(mop.getReg())) {
            // replace register with representative register
            unsigned reg = rep(mop.getReg());
            mii->SetMachineOperandReg(i, reg);

            LiveInterval &RegInt = getInterval(reg);
            RegInt.weight +=
              (mop.isUse() + mop.isDef()) * pow(10.0F, (int)loopDepth);

After joining intervals some moves are unecessary. If for example this
instruction was in the code:

mov %reg1024, %reg1045

and intervals for reg1024 and reg1045 were joined, only one register
needs to be present in the pre register-allocation machine code. So all
references to reg1024 and reg1045 are replaced with a reference to their
representative register (found using a union find algorithm). Note that
the representative register could be a real register if we ever joined
an interval of a real register with one of a virtual register (and this
real register will be the representative register of the set of
intervals joined together).

I don't understand the following code snippet in LiveIntervalAnalysis.cpp.

Why changing the type of the opreand from a virtual register to a
machine register? The register number (reg) is still a virtual
register index (>1024).

This code isn't actually replacing the virtual register with a physreg. As you noticed, it replaces it with a different virtual register. As part of coallescing, the code uses union-find to find a single representative register for all merged live ranges. This code just makes sure that all of the merged live ranges are rewritten to use a single virtual register (the representative).

After this is done, the "spiller" (in CodeGen/VirtRegMap.*) rewrites to virtual registers to use physregs and/or spilled values.

-Chris

bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
// perform a final pass over the instructions and compute spill
// weights, coalesce virtual registers and remove identity moves

...
       for (unsigned i = 0; i < mii->getNumOperands(); ++i) {
         const MachineOperand& mop = mii->getOperand(i);
         if (mop.isRegister() && mop.getReg() &&
             MRegisterInfo::isVirtualRegister(mop.getReg())) {
           // replace register with representative register
           unsigned reg = rep(mop.getReg());
           mii->SetMachineOperandReg(i, reg);

           LiveInterval &RegInt = getInterval(reg);
           RegInt.weight +=
             (mop.isUse() + mop.isDef()) * pow(10.0F, (int)loopDepth);

-Chris

Then why changing its optype?

It makes the assertion fails:

MachineOperand& MO = inst.getOperand(n);
if (MRegisterInfo::isVirtualRegister(MO.getReg())) {
  assert(MachineOperand::MO_VirtualRegister == MO.getType());
  ...
}

Is that alright?

Some of my code using MachineOperand::getType() instead of
MRegisterInfo::is{Physical,Virtual}Register() to check the register
type.

I understand the representative register could be a physical (real)
register if one of the coallescing register is a physical register.
But the code _uncondtionally_ changes MachineOperand::optype to
MO_MachineRegister, why?

(Same question as my previous post)

This code isn't actually replacing the virtual register with a physreg.

Then why changing its optype?

It makes the assertion fails:

MachineOperand& MO = inst.getOperand(n);
if (MRegisterInfo::isVirtualRegister(MO.getReg())) {
assert(MachineOperand::MO_VirtualRegister == MO.getType());
...
}

Is that alright?

No, that's not right. There is no distinction between MO_VirtualRegister and MO_PhysicalRegister in the target independent backend. This is due to difference between how the SparcV9 backend (which uses this distinction) and the target-indep backend work. If you use: MO.isRegister(), it accepts both MO_MachineRegister and MO_VirtualRegister. In the target-indep backend, there is no distinction: the distinction is based on the value of the register itself.

Some of my code using MachineOperand::getType() instead of
MRegisterInfo::is{Physical,Virtual}Register() to check the register
type.

If you use MO.isRegister() things should work.

-Chris

See above. There is no distinction, and some of these changes are required by the SparcV9 backend. This kind of stuff will be cleaned up over time.

-Chris