- Update register allocation hint after coalescing. This is done by the target since the hint is target dependent. This is important for ARM register pair hints.

- Register allocator should resolve the second part of the hint (register number) before passing it to the target since it knows virtual register to physical register mapping.
- More fixes to get ARM load / store double word working.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73671 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-06-18 02:04:01 +00:00
parent 063989455d
commit f9f1da17f8
6 changed files with 172 additions and 87 deletions

View File

@ -523,7 +523,7 @@ public:
/// register class in the form of a pair of TargetRegisterClass iterators.
virtual std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
getAllocationOrder(const TargetRegisterClass *RC,
std::pair<unsigned,unsigned> Hint,
unsigned HintType, unsigned HintReg,
const MachineFunction &MF) const {
return std::make_pair(RC->allocation_order_begin(MF),
RC->allocation_order_end(MF));
@ -531,13 +531,24 @@ public:
/// ResolveRegAllocHint - Resolves the specified register allocation hint
/// to a physical register. Returns the physical register if it is successful.
unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg,
const MachineFunction &MF) const {
virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg,
const MachineFunction &MF) const {
if (Type == 0 && Reg && isPhysicalRegister(Reg))
return Reg;
return 0;
}
/// UpdateRegAllocHint - A callback to allow target a chance to update
/// register allocation hints when a register is "changed" (e.g. coalesced)
/// to another register. e.g. On ARM, some virtual registers should target
/// register pairs, if one of pair is coalesced to another register, the
/// allocation hint of the other half of the pair should be changed to point
/// to the new register.
virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
MachineFunction &MF) const {
// Do nothing.
}
/// targetHandlesStackFrameRounding - Returns true if the target is
/// responsible for rounding up the stack frame (probably at emitPrologue
/// time).

View File

@ -1356,9 +1356,15 @@ unsigned RALinScan::getFreePhysReg(LiveInterval* cur,
unsigned FreeReg = 0;
unsigned FreeRegInactiveCount = 0;
std::pair<unsigned, unsigned> Hint = mri_->getRegAllocationHint(cur->reg);
// Resolve second part of the hint (if possible) given the current allocation.
unsigned physReg = Hint.second;
if (physReg &&
TargetRegisterInfo::isVirtualRegister(physReg) && vrm_->hasPhys(physReg))
physReg = vrm_->getPhys(physReg);
TargetRegisterClass::iterator I, E;
tie(I, E) = tri_->getAllocationOrder(RC,
mri_->getRegAllocationHint(cur->reg), *mf_);
tie(I, E) = tri_->getAllocationOrder(RC, Hint.first, physReg, *mf_);
assert(I != E && "No allocatable register in this register class!");
// Scan for the first available register.

View File

@ -1766,6 +1766,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
// being merged.
li_->removeInterval(SrcReg);
// Update regalloc hint.
tri_->UpdateRegAllocHint(SrcReg, DstReg, *mf_);
// Manually deleted the live interval copy.
if (SavedLI) {
SavedLI->clear();

View File

@ -41,6 +41,12 @@ STATISTIC(NumSTMGened , "Number of stm instructions generated");
STATISTIC(NumFLDMGened, "Number of fldm instructions generated");
STATISTIC(NumFSTMGened, "Number of fstm instructions generated");
STATISTIC(NumLdStMoved, "Number of load / store instructions moved");
STATISTIC(NumLDRDFormed,"Number of ldrd created before allocation");
STATISTIC(NumSTRDFormed,"Number of strd created before allocation");
STATISTIC(NumLDRD2LDM, "Number of ldrd instructions turned back into ldm");
STATISTIC(NumSTRD2STM, "Number of strd instructions turned back into stm");
STATISTIC(NumLDRD2LDR, "Number of ldrd instructions turned back into ldr's");
STATISTIC(NumSTRD2STR, "Number of strd instructions turned back into str's");
/// ARMAllocLoadStoreOpt - Post- register allocation pass the combine
/// load / store instructions to form ldm / stm instructions.
@ -651,9 +657,9 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
if ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum)
return false;
bool isDef = Opcode == ARM::LDRD;
bool EvenKill = isDef ? false : MI->getOperand(0).isKill();
bool OddKill = isDef ? false : MI->getOperand(1).isKill();
bool isLd = Opcode == ARM::LDRD;
bool EvenKill = isLd ? false : MI->getOperand(0).isKill();
bool OddKill = isLd ? false : MI->getOperand(1).isKill();
const MachineOperand &BaseOp = MI->getOperand(2);
unsigned BaseReg = BaseOp.getReg();
bool BaseKill = BaseOp.isKill();
@ -668,34 +674,49 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
// Ascending register numbers and no offset. It's safe to change it to a
// ldm or stm.
unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDM : ARM::STM;
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
.addReg(BaseReg, getKillRegState(BaseKill))
.addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
.addImm(Pred).addReg(PredReg)
.addReg(EvenReg, getDefRegState(isDef))
.addReg(OddReg, getDefRegState(isDef));
if (isLd) {
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
.addReg(BaseReg, getKillRegState(BaseKill))
.addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
.addImm(Pred).addReg(PredReg)
.addReg(EvenReg, getDefRegState(isLd))
.addReg(OddReg, getDefRegState(isLd));
++NumLDRD2LDM;
} else {
BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
.addReg(BaseReg, getKillRegState(BaseKill))
.addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
.addImm(Pred).addReg(PredReg)
.addReg(EvenReg, getKillRegState(EvenKill))
.addReg(OddReg, getKillRegState(OddKill));
++NumSTRD2STM;
}
} else {
// Split into two instructions.
unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDR : ARM::STR;
DebugLoc dl = MBBI->getDebugLoc();
// If this is a load and base register is killed, it may have been
// re-defed by the load, make sure the first load does not clobber it.
if (isDef &&
if (isLd &&
(BaseKill || OffKill) &&
(TRI->regsOverlap(EvenReg, BaseReg) ||
(OffReg && TRI->regsOverlap(EvenReg, OffReg)))) {
assert(!TRI->regsOverlap(OddReg, BaseReg) &&
(!OffReg || !TRI->regsOverlap(OddReg, OffReg)));
InsertLDR_STR(MBB, MBBI, OffImm+4, isDef, dl, NewOpc, OddReg, OddKill,
InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, OddReg, OddKill,
BaseReg, false, OffReg, false, Pred, PredReg, TII);
InsertLDR_STR(MBB, MBBI, OffImm, isDef, dl, NewOpc, EvenReg, EvenKill,
InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, EvenReg, EvenKill,
BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII);
} else {
InsertLDR_STR(MBB, MBBI, OffImm, isDef, dl, NewOpc, EvenReg, EvenKill,
InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, EvenReg, EvenKill,
BaseReg, false, OffReg, false, Pred, PredReg, TII);
InsertLDR_STR(MBB, MBBI, OffImm+4, isDef, dl, NewOpc, OddReg, OddKill,
InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, OddReg, OddKill,
BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII);
}
if (isLd)
++NumLDRD2LDR;
else
++NumSTRD2STR;
}
MBBI = prior(MBBI);
@ -1069,6 +1090,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
MachineInstr *FirstOp = 0;
MachineInstr *LastOp = 0;
int LastOffset = 0;
unsigned LastOpcode = 0;
unsigned LastBytes = 0;
unsigned NumMove = 0;
for (int i = Ops.size() - 1; i >= 0; --i) {
@ -1083,6 +1105,10 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
LastOp = Op;
}
unsigned Opcode = Op->getOpcode();
if (LastOpcode && Opcode != LastOpcode)
break;
int Offset = getMemoryOpOffset(Op);
unsigned Bytes = getLSMultipleTransferSize(Op);
if (LastBytes) {
@ -1091,6 +1117,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
}
LastOffset = Offset;
LastBytes = Bytes;
LastOpcode = Opcode;
if (++NumMove == 4)
break;
}
@ -1131,22 +1158,25 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
Offset, PredReg, Pred)) {
Ops.pop_back();
Ops.pop_back();
MBB->erase(Op0);
MBB->erase(Op1);
// Form the pair instruction.
if (isLd)
if (isLd) {
BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc))
.addReg(EvenReg, RegState::Define)
.addReg(OddReg, RegState::Define)
.addReg(BaseReg).addReg(0).addImm(Offset)
.addImm(Pred).addReg(PredReg);
else
++NumLDRDFormed;
} else {
BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc))
.addReg(EvenReg)
.addReg(OddReg)
.addReg(BaseReg).addReg(0).addImm(Offset)
.addImm(Pred).addReg(PredReg);
++NumSTRDFormed;
}
MBB->erase(Op0);
MBB->erase(Op1);
// Add register allocation hints to form register pairs.
MRI->setRegAllocationHint(EvenReg, ARMRI::RegPairEven, OddReg);

View File

@ -308,7 +308,7 @@ const TargetRegisterClass *ARMRegisterInfo::getPointerRegClass() const {
/// register class in the form of a pair of TargetRegisterClass iterators.
std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
std::pair<unsigned, unsigned> Hint,
unsigned HintType, unsigned HintReg,
const MachineFunction &MF) const {
// Alternative register allocation orders when favoring even / odd registers
// of register pairs.
@ -384,7 +384,13 @@ ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
};
if (Hint.first == ARMRI::RegPairEven) {
if (HintType == ARMRI::RegPairEven) {
if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0)
// It's no longer possible to fulfill this hint. Return the default
// allocation order.
return std::make_pair(RC->allocation_order_begin(MF),
RC->allocation_order_end(MF));
if (!STI.isTargetDarwin() && !hasFP(MF)) {
if (!STI.isR9Reserved())
return std::make_pair(GPREven1,
@ -407,7 +413,13 @@ ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
return std::make_pair(GPREven6,
GPREven6 + (sizeof(GPREven6)/sizeof(unsigned)));
}
} else if (Hint.first == ARMRI::RegPairOdd) {
} else if (HintType == ARMRI::RegPairOdd) {
if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0)
// It's no longer possible to fulfill this hint. Return the default
// allocation order.
return std::make_pair(RC->allocation_order_begin(MF),
RC->allocation_order_end(MF));
if (!STI.isTargetDarwin() && !hasFP(MF)) {
if (!STI.isR9Reserved())
return std::make_pair(GPROdd1,
@ -453,6 +465,26 @@ ARMRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg,
return 0;
}
void
ARMRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
MachineFunction &MF) const {
MachineRegisterInfo *MRI = &MF.getRegInfo();
std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
if ((Hint.first == (unsigned)ARMRI::RegPairOdd ||
Hint.first == (unsigned)ARMRI::RegPairEven) &&
Hint.second && TargetRegisterInfo::isVirtualRegister(Hint.second)) {
// If 'Reg' is one of the even / odd register pair and it's now changed
// (e.g. coalesced) into a different register. The other register of the
// pair allocation hint must be updated to reflect the relationship
// change.
unsigned OtherReg = Hint.second;
Hint = MRI->getRegAllocationHint(OtherReg);
if (Hint.second == Reg)
// Make sure the pair has not already divorced.
MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg);
}
}
bool
ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@ -1680,68 +1712,68 @@ unsigned ARMRegisterInfo::getRegisterPairEven(unsigned Reg,
default: break;
// Return 0 if either register of the pair is a special register.
// So no R12, etc.
case ARM::R0: case ARM::R1:
case ARM::R1:
return ARM::R0;
case ARM::R2: case ARM::R3:
case ARM::R3:
// FIXME!
return STI.isThumb() ? 0 : ARM::R2;
case ARM::R4: case ARM::R5:
case ARM::R5:
return ARM::R4;
case ARM::R6: case ARM::R7:
case ARM::R7:
return isReservedReg(MF, ARM::R7) ? 0 : ARM::R6;
case ARM::R8: case ARM::R9:
case ARM::R9:
return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8;
case ARM::R10: case ARM::R11:
case ARM::R11:
return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10;
case ARM::S0: case ARM::S1:
case ARM::S1:
return ARM::S0;
case ARM::S2: case ARM::S3:
case ARM::S3:
return ARM::S2;
case ARM::S4: case ARM::S5:
case ARM::S5:
return ARM::S4;
case ARM::S6: case ARM::S7:
case ARM::S7:
return ARM::S6;
case ARM::S8: case ARM::S9:
case ARM::S9:
return ARM::S8;
case ARM::S10: case ARM::S11:
case ARM::S11:
return ARM::S10;
case ARM::S12: case ARM::S13:
case ARM::S13:
return ARM::S12;
case ARM::S14: case ARM::S15:
case ARM::S15:
return ARM::S14;
case ARM::S16: case ARM::S17:
case ARM::S17:
return ARM::S16;
case ARM::S18: case ARM::S19:
case ARM::S19:
return ARM::S18;
case ARM::S20: case ARM::S21:
case ARM::S21:
return ARM::S20;
case ARM::S22: case ARM::S23:
case ARM::S23:
return ARM::S22;
case ARM::S24: case ARM::S25:
case ARM::S25:
return ARM::S24;
case ARM::S26: case ARM::S27:
case ARM::S27:
return ARM::S26;
case ARM::S28: case ARM::S29:
case ARM::S29:
return ARM::S28;
case ARM::S30: case ARM::S31:
case ARM::S31:
return ARM::S30;
case ARM::D0: case ARM::D1:
case ARM::D1:
return ARM::D0;
case ARM::D2: case ARM::D3:
case ARM::D3:
return ARM::D2;
case ARM::D4: case ARM::D5:
case ARM::D5:
return ARM::D4;
case ARM::D6: case ARM::D7:
case ARM::D7:
return ARM::D6;
case ARM::D8: case ARM::D9:
case ARM::D9:
return ARM::D8;
case ARM::D10: case ARM::D11:
case ARM::D11:
return ARM::D10;
case ARM::D12: case ARM::D13:
case ARM::D13:
return ARM::D12;
case ARM::D14: case ARM::D15:
case ARM::D15:
return ARM::D14;
}
@ -1754,68 +1786,68 @@ unsigned ARMRegisterInfo::getRegisterPairOdd(unsigned Reg,
default: break;
// Return 0 if either register of the pair is a special register.
// So no R12, etc.
case ARM::R0: case ARM::R1:
case ARM::R0:
return ARM::R1;
case ARM::R2: case ARM::R3:
case ARM::R2:
// FIXME!
return STI.isThumb() ? 0 : ARM::R3;
case ARM::R4: case ARM::R5:
case ARM::R4:
return ARM::R5;
case ARM::R6: case ARM::R7:
case ARM::R6:
return isReservedReg(MF, ARM::R7) ? 0 : ARM::R7;
case ARM::R8: case ARM::R9:
case ARM::R8:
return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9;
case ARM::R10: case ARM::R11:
case ARM::R10:
return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11;
case ARM::S0: case ARM::S1:
case ARM::S0:
return ARM::S1;
case ARM::S2: case ARM::S3:
case ARM::S2:
return ARM::S3;
case ARM::S4: case ARM::S5:
case ARM::S4:
return ARM::S5;
case ARM::S6: case ARM::S7:
case ARM::S6:
return ARM::S7;
case ARM::S8: case ARM::S9:
case ARM::S8:
return ARM::S9;
case ARM::S10: case ARM::S11:
case ARM::S10:
return ARM::S11;
case ARM::S12: case ARM::S13:
case ARM::S12:
return ARM::S13;
case ARM::S14: case ARM::S15:
case ARM::S14:
return ARM::S15;
case ARM::S16: case ARM::S17:
case ARM::S16:
return ARM::S17;
case ARM::S18: case ARM::S19:
case ARM::S18:
return ARM::S19;
case ARM::S20: case ARM::S21:
case ARM::S20:
return ARM::S21;
case ARM::S22: case ARM::S23:
case ARM::S22:
return ARM::S23;
case ARM::S24: case ARM::S25:
case ARM::S24:
return ARM::S25;
case ARM::S26: case ARM::S27:
case ARM::S26:
return ARM::S27;
case ARM::S28: case ARM::S29:
case ARM::S28:
return ARM::S29;
case ARM::S30: case ARM::S31:
case ARM::S30:
return ARM::S31;
case ARM::D0: case ARM::D1:
case ARM::D0:
return ARM::D1;
case ARM::D2: case ARM::D3:
case ARM::D2:
return ARM::D3;
case ARM::D4: case ARM::D5:
case ARM::D4:
return ARM::D5;
case ARM::D6: case ARM::D7:
case ARM::D6:
return ARM::D7;
case ARM::D8: case ARM::D9:
case ARM::D8:
return ARM::D9;
case ARM::D10: case ARM::D11:
case ARM::D10:
return ARM::D11;
case ARM::D12: case ARM::D13:
case ARM::D12:
return ARM::D13;
case ARM::D14: case ARM::D15:
case ARM::D14:
return ARM::D15;
}

View File

@ -70,12 +70,15 @@ public:
std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
getAllocationOrder(const TargetRegisterClass *RC,
std::pair<unsigned,unsigned> Hint,
unsigned HintType, unsigned HintReg,
const MachineFunction &MF) const;
unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg,
const MachineFunction &MF) const;
void UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
MachineFunction &MF) const;
bool requiresRegisterScavenging(const MachineFunction &MF) const;
bool hasFP(const MachineFunction &MF) const;