EXTRACT_SUBREG coalescing support. The coalescer now treats EXTRACT_SUBREG like

(almost) a register copy. However, it always coalesced to the register of the
RHS (the super-register). All uses of the result of a EXTRACT_SUBREG are sub-
register uses which adds subtle complications to load folding, spiller rewrite,
etc.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42899 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng
2007-10-12 08:50:34 +00:00
parent 10136e7c7f
commit 32dfbeada7
12 changed files with 422 additions and 248 deletions
+70 -38
View File
@@ -242,10 +242,12 @@ namespace {
/// blocks that have low register pressure (the vreg may be spilled due to
/// register pressure in other blocks).
class VISIBILITY_HIDDEN LocalSpiller : public Spiller {
SSARegMap *RegMap;
const MRegisterInfo *MRI;
const TargetInstrInfo *TII;
public:
bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM) {
RegMap = MF.getSSARegMap();
MRI = MF.getTarget().getRegisterInfo();
TII = MF.getTarget().getInstrInfo();
DOUT << "\n**** Local spiller rewriting function '"
@@ -776,25 +778,33 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
if (!MO.isRegister() || MO.getReg() == 0)
continue; // Ignore non-register operands.
if (MRegisterInfo::isPhysicalRegister(MO.getReg())) {
unsigned VirtReg = MO.getReg();
if (MRegisterInfo::isPhysicalRegister(VirtReg)) {
// Ignore physregs for spilling, but remember that it is used by this
// function.
MF.setPhysRegUsed(MO.getReg());
ReusedOperands.markClobbered(MO.getReg());
MF.setPhysRegUsed(VirtReg);
ReusedOperands.markClobbered(VirtReg);
continue;
}
assert(MRegisterInfo::isVirtualRegister(MO.getReg()) &&
assert(MRegisterInfo::isVirtualRegister(VirtReg) &&
"Not a virtual or a physical register?");
unsigned VirtReg = MO.getReg();
unsigned SubIdx = 0;
bool isSubReg = RegMap->isSubRegister(VirtReg);
if (isSubReg) {
SubIdx = RegMap->getSubRegisterIndex(VirtReg);
VirtReg = RegMap->getSuperRegister(VirtReg);
}
if (VRM.isAssignedReg(VirtReg)) {
// This virtual register was assigned a physreg!
unsigned Phys = VRM.getPhys(VirtReg);
MF.setPhysRegUsed(Phys);
if (MO.isDef())
ReusedOperands.markClobbered(Phys);
MI.getOperand(i).setReg(Phys);
unsigned RReg = isSubReg ? MRI->getSubReg(Phys, SubIdx) : Phys;
MI.getOperand(i).setReg(RReg);
continue;
}
@@ -817,6 +827,24 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
if (ReuseSlot != VirtRegMap::NO_STACK_SLOT)
PhysReg = Spills.getSpillSlotOrReMatPhysReg(ReuseSlot);
}
// If this is a sub-register use, make sure the reuse register is in the
// right register class. For example, for x86 not all of the 32-bit
// registers have accessible sub-registers.
// Similarly so for EXTRACT_SUBREG. Consider this:
// EDI = op
// MOV32_mr fi#1, EDI
// ...
// = EXTRACT_SUBREG fi#1
// fi#1 is available in EDI, but it cannot be reused because it's not in
// the right register file.
if (PhysReg &&
(isSubReg || MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)) {
const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg);
if (!RC->contains(PhysReg))
PhysReg = 0;
}
if (PhysReg) {
// This spilled operand might be part of a two-address operand. If this
// is the case, then changing it will necessarily require changing the
@@ -824,6 +852,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
// aren't allowed to modify the reused register. If none of these cases
// apply, reuse it.
bool CanReuse = true;
int ti = TID->getOperandConstraint(i, TOI::TIED_TO);
if (ti != -1 &&
MI.getOperand(ti).isRegister() &&
@@ -845,7 +874,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
<< MRI->getName(PhysReg) << " for vreg"
<< VirtReg <<" instead of reloading into physreg "
<< MRI->getName(VRM.getPhys(VirtReg)) << "\n";
MI.getOperand(i).setReg(PhysReg);
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
// The only technical detail we have is that we don't know that
// PhysReg won't be clobbered by a reloaded stack slot that occurs
@@ -883,7 +913,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
}
}
continue;
}
} // CanReuse
// Otherwise we have a situation where we have a two-address instruction
// whose mod/ref operand needs to be reloaded. This reload is already
@@ -917,13 +947,14 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
DOUT << " from physreg " << MRI->getName(PhysReg) << " for vreg"
<< VirtReg
<< " instead of reloading into same physreg.\n";
MI.getOperand(i).setReg(PhysReg);
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
ReusedOperands.markClobbered(PhysReg);
++NumReused;
continue;
}
const TargetRegisterClass* RC = MF.getSSARegMap()->getRegClass(VirtReg);
const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg);
MF.setPhysRegUsed(DesignatedReg);
ReusedOperands.markClobbered(DesignatedReg);
MRI->copyRegToReg(MBB, &MI, DesignatedReg, PhysReg, RC, RC);
@@ -935,16 +966,17 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
Spills.ClobberPhysReg(DesignatedReg);
Spills.addAvailable(ReuseSlot, &MI, DesignatedReg);
MI.getOperand(i).setReg(DesignatedReg);
unsigned RReg =
isSubReg ? MRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg;
MI.getOperand(i).setReg(RReg);
DOUT << '\t' << *prior(MII);
++NumReused;
continue;
}
} // is (PhysReg)
// Otherwise, reload it and remember that we have it.
PhysReg = VRM.getPhys(VirtReg);
assert(PhysReg && "Must map virtreg to physreg!");
const TargetRegisterClass* RC = MF.getSSARegMap()->getRegClass(VirtReg);
// Note that, if we reused a register for a previous operand, the
// register we want to reload into might not actually be
@@ -960,6 +992,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
MRI->reMaterialize(MBB, &MI, PhysReg, VRM.getReMaterializedMI(VirtReg));
++NumReMats;
} else {
const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg);
MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, SSorRMId, RC);
++NumLoads;
}
@@ -974,7 +1007,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
// unless it's a two-address operand.
if (TID->getOperandConstraint(i, TOI::TIED_TO) == -1)
MI.getOperand(i).setIsKill();
MI.getOperand(i).setReg(PhysReg);
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
UpdateKills(*prior(MII), RegKills, KillOps);
DOUT << '\t' << *prior(MII);
}
@@ -1002,30 +1036,28 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
// straight load from the virt reg slot.
if ((MR & VirtRegMap::isRef) && !(MR & VirtRegMap::isMod)) {
int FrameIdx;
if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) {
if (FrameIdx == SS) {
// If this spill slot is available, turn it into a copy (or nothing)
// instead of leaving it as a load!
if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) {
DOUT << "Promoted Load To Copy: " << MI;
if (DestReg != InReg) {
const TargetRegisterClass *RC =
MF.getSSARegMap()->getRegClass(VirtReg);
MRI->copyRegToReg(MBB, &MI, DestReg, InReg, RC, RC);
// Revisit the copy so we make sure to notice the effects of the
// operation on the destreg (either needing to RA it if it's
// virtual or needing to clobber any values if it's physical).
NextMII = &MI;
--NextMII; // backtrack to the copy.
BackTracked = true;
} else
DOUT << "Removing now-noop copy: " << MI;
unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx);
if (DestReg && FrameIdx == SS) {
// If this spill slot is available, turn it into a copy (or nothing)
// instead of leaving it as a load!
if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) {
DOUT << "Promoted Load To Copy: " << MI;
if (DestReg != InReg) {
const TargetRegisterClass *RC = RegMap->getRegClass(VirtReg);
MRI->copyRegToReg(MBB, &MI, DestReg, InReg, RC, RC);
// Revisit the copy so we make sure to notice the effects of the
// operation on the destreg (either needing to RA it if it's
// virtual or needing to clobber any values if it's physical).
NextMII = &MI;
--NextMII; // backtrack to the copy.
BackTracked = true;
} else
DOUT << "Removing now-noop copy: " << MI;
VRM.RemoveFromFoldedVirtMap(&MI);
MBB.erase(&MI);
Erased = true;
goto ProcessNextInst;
}
VRM.RemoveFromFoldedVirtMap(&MI);
MBB.erase(&MI);
Erased = true;
goto ProcessNextInst;
}
}
}
@@ -1121,7 +1153,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
// The only vregs left are stack slot definitions.
int StackSlot = VRM.getStackSlot(VirtReg);
const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(VirtReg);
const TargetRegisterClass *RC = RegMap->getRegClass(VirtReg);
// If this def is part of a two-address operand, make sure to execute
// the store from the correct physical register.