Clean up sub-register implementation by moving subReg information back to

MachineOperand auxInfo. Previous clunky implementation uses an external map
to track sub-register uses. That works because register allocator uses
a new virtual register for each spilled use. With interval splitting (coming
soon), we may have multiple uses of the same register some of which are
of using different sub-registers from others. It's too fragile to constantly
update the information.

llvm-svn: 44104
This commit is contained in:
Evan Cheng 2007-11-14 07:59:08 +00:00
parent 9c30fc234c
commit 7f02cfa599
9 changed files with 53 additions and 63 deletions

View File

@ -76,6 +76,10 @@ private:
/// offset - Offset to address of global or external, only valid for
/// MO_GlobalAddress, MO_ExternalSym and MO_ConstantPoolIndex
int offset;
/// subReg - SubRegister number, only valid for MO_Register. A value of 0
/// indicates the MO_Register has no subReg.
unsigned subReg;
} auxInfo;
MachineOperand() {}
@ -182,6 +186,10 @@ public:
"Wrong MachineOperand accessor");
return auxInfo.offset;
}
unsigned getSubReg() const {
assert(isRegister() && "Wrong MachineOperand accessor");
return auxInfo.subReg;
}
const char *getSymbolName() const {
assert(isExternalSymbol() && "Wrong MachineOperand accessor");
return contents.SymbolName;
@ -267,6 +275,10 @@ public:
"Wrong MachineOperand accessor");
auxInfo.offset = Offset;
}
void setSubReg(unsigned subReg) {
assert(isRegister() && "Wrong MachineOperand accessor");
auxInfo.subReg = subReg;
}
void setConstantPoolIndex(unsigned Idx) {
assert(isConstantPoolIndex() && "Wrong MachineOperand accessor");
contents.immedVal = Idx;
@ -451,7 +463,8 @@ public:
/// addRegOperand - Add a register operand.
///
void addRegOperand(unsigned Reg, bool IsDef, bool IsImp = false,
bool IsKill = false, bool IsDead = false) {
bool IsKill = false, bool IsDead = false,
unsigned SubReg = 0) {
MachineOperand &Op = AddNewOperand(IsImp);
Op.opType = MachineOperand::MO_Register;
Op.IsDef = IsDef;
@ -459,6 +472,7 @@ public:
Op.IsKill = IsKill;
Op.IsDead = IsDead;
Op.contents.RegNo = Reg;
Op.auxInfo.subReg = SubReg;
}
/// addImmOperand - Add a zero extended constant argument to the

View File

@ -39,8 +39,8 @@ public:
const
MachineInstrBuilder &addReg(unsigned RegNo, bool isDef = false,
bool isImp = false, bool isKill = false,
bool isDead = false) const {
MI->addRegOperand(RegNo, isDef, isImp, isKill, isDead);
bool isDead = false, unsigned SubReg = 0) const {
MI->addRegOperand(RegNo, isDef, isImp, isKill, isDead, SubReg);
return *this;
}

View File

@ -26,7 +26,6 @@ class TargetRegisterClass;
class SSARegMap {
IndexedMap<const TargetRegisterClass*, VirtReg2IndexFunctor> RegClassMap;
IndexedMap<std::pair<unsigned, unsigned>, VirtReg2IndexFunctor> RegSubIdxMap;
unsigned NextRegNum;
public:
@ -43,30 +42,12 @@ class SSARegMap {
assert(RegClass && "Cannot create register without RegClass!");
RegClassMap.grow(NextRegNum);
RegClassMap[NextRegNum] = RegClass;
RegSubIdxMap.grow(NextRegNum);
RegSubIdxMap[NextRegNum] = std::make_pair(0,0);
return NextRegNum++;
}
unsigned getLastVirtReg() const {
return NextRegNum - 1;
}
void setIsSubRegister(unsigned Reg, unsigned SuperReg, unsigned SubIdx) {
RegSubIdxMap[Reg] = std::make_pair(SuperReg, SubIdx);
}
bool isSubRegister(unsigned Reg) const {
return RegSubIdxMap[Reg].first != 0;
}
unsigned getSuperRegister(unsigned Reg) const {
return RegSubIdxMap[Reg].first;
}
unsigned getSubRegisterIndex(unsigned Reg) const {
return RegSubIdxMap[Reg].second;
}
};
} // End llvm namespace

View File

@ -670,12 +670,8 @@ rewriteInstructionForSpills(const LiveInterval &li,
unsigned RegI = Reg;
if (Reg == 0 || MRegisterInfo::isPhysicalRegister(Reg))
continue;
bool isSubReg = RegMap->isSubRegister(Reg);
unsigned SubIdx = 0;
if (isSubReg) {
SubIdx = RegMap->getSubRegisterIndex(Reg);
Reg = RegMap->getSuperRegister(Reg);
}
unsigned SubIdx = mop.getSubReg();
bool isSubReg = SubIdx != 0;
if (Reg != li.reg)
continue;
@ -710,8 +706,6 @@ rewriteInstructionForSpills(const LiveInterval &li,
// Create a new virtual register for the spill interval.
unsigned NewVReg = RegMap->createVirtualRegister(rc);
vrm.grow();
if (isSubReg)
RegMap->setIsSubRegister(NewVReg, NewVReg, SubIdx);
// Scan all of the operands of this instruction rewriting operands
// to use NewVReg instead of li.reg as appropriate. We do this for

View File

@ -39,6 +39,7 @@ void MachineInstr::addImplicitDefUseOperands() {
Op.IsKill = false;
Op.IsDead = false;
Op.contents.RegNo = *ImpDefs;
Op.auxInfo.subReg = 0;
Operands.push_back(Op);
}
if (TID->ImplicitUses)
@ -50,6 +51,7 @@ void MachineInstr::addImplicitDefUseOperands() {
Op.IsKill = false;
Op.IsDead = false;
Op.contents.RegNo = *ImpUses;
Op.auxInfo.subReg = 0;
Operands.push_back(Op);
}
}

View File

@ -1387,6 +1387,7 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
r2rRevMap_.grow(RegMap->getLastVirtReg());
// Join (coalesce) intervals if requested.
IndexedMap<unsigned, VirtReg2IndexFunctor> RegSubIdxMap;
if (EnableJoining) {
joinIntervals();
DOUT << "********** INTERVALS POST JOINING **********\n";
@ -1404,10 +1405,11 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
// Transfer sub-registers info to SSARegMap now that coalescing information
// is complete.
RegSubIdxMap.grow(mf_->getSSARegMap()->getLastVirtReg()+1);
while (!SubRegIdxes.empty()) {
std::pair<unsigned, unsigned> RI = SubRegIdxes.back();
SubRegIdxes.pop_back();
mf_->getSSARegMap()->setIsSubRegister(RI.first, rep(RI.first), RI.second);
RegSubIdxMap[RI.first] = RI.second;
}
}
@ -1448,12 +1450,13 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
// replace register with representative register
unsigned OrigReg = mop.getReg();
unsigned reg = rep(OrigReg);
// Don't rewrite if it is a sub-register of a virtual register.
if (!RegMap->isSubRegister(OrigReg))
unsigned SubIdx = RegSubIdxMap[OrigReg];
if (SubIdx && MRegisterInfo::isPhysicalRegister(reg))
mii->getOperand(i).setReg(mri_->getSubReg(reg, SubIdx));
else {
mii->getOperand(i).setReg(reg);
else if (MRegisterInfo::isPhysicalRegister(reg))
mii->getOperand(i).setReg(mri_->getSubReg(reg,
RegMap->getSubRegisterIndex(OrigReg)));
mii->getOperand(i).setSubReg(SubIdx);
}
// Multiple uses of reg by the same instruction. It should not
// contribute to spill weight again.

View File

@ -788,8 +788,7 @@ bool LocalSpiller::PrepForUnfoldOpti(MachineBasicBlock &MBB,
if (!MO.isRegister() || MO.getReg() == 0 || !MO.isUse())
continue;
unsigned VirtReg = MO.getReg();
if (MRegisterInfo::isPhysicalRegister(VirtReg) ||
RegMap->isSubRegister(VirtReg))
if (MRegisterInfo::isPhysicalRegister(VirtReg) || MO.getSubReg())
continue;
if (VRM.isAssignedReg(VirtReg)) {
unsigned PhysReg = VRM.getPhys(VirtReg);
@ -911,20 +910,14 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
assert(MRegisterInfo::isVirtualRegister(VirtReg) &&
"Not a virtual or a physical register?");
unsigned SubIdx = 0;
bool isSubReg = RegMap->isSubRegister(VirtReg);
if (isSubReg) {
SubIdx = RegMap->getSubRegisterIndex(VirtReg);
VirtReg = RegMap->getSuperRegister(VirtReg);
}
unsigned SubIdx = MO.getSubReg();
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);
unsigned RReg = isSubReg ? MRI->getSubReg(Phys, SubIdx) : Phys;
unsigned RReg = SubIdx ? MRI->getSubReg(Phys, SubIdx) : Phys;
MI.getOperand(i).setReg(RReg);
continue;
}
@ -960,7 +953,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
// 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)) {
(SubIdx || MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)) {
const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg);
if (!RC->contains(PhysReg))
PhysReg = 0;
@ -994,7 +987,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
<< MRI->getName(PhysReg) << " for vreg"
<< VirtReg <<" instead of reloading into physreg "
<< MRI->getName(VRM.getPhys(VirtReg)) << "\n";
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
unsigned RReg = SubIdx ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
// The only technical detail we have is that we don't know that
@ -1067,7 +1060,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
DOUT << " from physreg " << MRI->getName(PhysReg) << " for vreg"
<< VirtReg
<< " instead of reloading into same physreg.\n";
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
unsigned RReg = SubIdx ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
ReusedOperands.markClobbered(RReg);
++NumReused;
@ -1087,7 +1080,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
Spills.addAvailable(ReuseSlot, &MI, DesignatedReg);
unsigned RReg =
isSubReg ? MRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg;
SubIdx ? MRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg;
MI.getOperand(i).setReg(RReg);
DOUT << '\t' << *prior(MII);
++NumReused;
@ -1127,7 +1120,7 @@ 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();
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
unsigned RReg = SubIdx ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
MI.getOperand(i).setReg(RReg);
UpdateKills(*prior(MII), RegKills, KillOps);
DOUT << '\t' << *prior(MII);
@ -1308,13 +1301,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
continue;
}
unsigned SubIdx = 0;
bool isSubReg = RegMap->isSubRegister(VirtReg);
if (isSubReg) {
SubIdx = RegMap->getSubRegisterIndex(VirtReg);
VirtReg = RegMap->getSuperRegister(VirtReg);
}
unsigned SubIdx = MO.getSubReg();
bool DoReMat = VRM.isReMaterialized(VirtReg);
if (DoReMat)
ReMatDefs.insert(&MI);
@ -1329,7 +1316,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
int TiedOp = MI.getInstrDescriptor()->findTiedToSrcOperand(i);
if (TiedOp != -1) {
PhysReg = MI.getOperand(TiedOp).getReg();
if (isSubReg) {
if (SubIdx) {
unsigned SuperReg = findSuperReg(RC, PhysReg, SubIdx, MRI);
assert(SuperReg && MRI->getSubReg(SuperReg, SubIdx) == PhysReg &&
"Can't find corresponding super-register!");
@ -1346,7 +1333,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) {
}
MF.setPhysRegUsed(PhysReg);
unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
unsigned RReg = SubIdx ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg;
ReusedOperands.markClobbered(RReg);
MI.getOperand(i).setReg(RReg);

View File

@ -616,6 +616,15 @@ void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
case X86::PsMOVZX64rr32:
O << TAI->getCommentString() << " ZERO-EXTEND " << "\n\t";
break;
case X86::MOV8mr: {
const MachineOperand &MO = MI->getOperand(4);
switch (MO.getReg()) {
default: abort();
case X86::AH: case X86::DH: case X86::CH: case X86::BH:
case X86::AL: case X86::DL: case X86::CL: case X86::BL:
break;
}
}
}
// Call the autogenerated instruction printer routines.

View File

@ -773,7 +773,8 @@ bool X86RegisterInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
static const MachineInstrBuilder &X86InstrAddOperand(MachineInstrBuilder &MIB,
MachineOperand &MO) {
if (MO.isRegister())
MIB = MIB.addReg(MO.getReg(), MO.isDef(), MO.isImplicit());
MIB = MIB.addReg(MO.getReg(), MO.isDef(), MO.isImplicit(),
false, false, MO.getSubReg());
else if (MO.isImmediate())
MIB = MIB.addImm(MO.getImm());
else if (MO.isFrameIndex())
@ -1498,8 +1499,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
unsigned Opc = (Amount < 128) ?
(Is64Bit ? X86::ADD64ri8 : X86::ADD32ri8) :
(Is64Bit ? X86::ADD64ri32 : X86::ADD32ri);
New = BuildMI(TII.get(Opc), StackPtr)
.addReg(StackPtr).addImm(Amount);
New = BuildMI(TII.get(Opc), StackPtr).addReg(StackPtr).addImm(Amount);
}
}