Preserve implicit defs in ARMLoadStoreOptimizer.

When a number of sub-register VLRDS instructions are combined into a
VLDM, preserve any super-register implicit defs. This is required to
keep the register scavenger and machine code verifier happy.

Enable machine code verification after ARMLoadStoreOptimizer.
ARM/2012-01-26-CopyPropKills.ll was failing because of this.

llvm-svn: 153610
This commit is contained in:
Jakob Stoklund Olesen 2012-03-28 22:50:56 +00:00
parent 4970c304e1
commit cdee326ab6
2 changed files with 23 additions and 4 deletions

View File

@ -93,7 +93,9 @@ namespace {
bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
int Offset, unsigned Base, bool BaseKill, int Opcode, int Offset, unsigned Base, bool BaseKill, int Opcode,
ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch, ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch,
DebugLoc dl, SmallVector<std::pair<unsigned, bool>, 8> &Regs); DebugLoc dl,
ArrayRef<std::pair<unsigned, bool> > Regs,
ArrayRef<unsigned> ImpDefs);
void MergeOpsUpdate(MachineBasicBlock &MBB, void MergeOpsUpdate(MachineBasicBlock &MBB,
MemOpQueue &MemOps, MemOpQueue &MemOps,
unsigned memOpsBegin, unsigned memOpsBegin,
@ -282,7 +284,8 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
int Offset, unsigned Base, bool BaseKill, int Offset, unsigned Base, bool BaseKill,
int Opcode, ARMCC::CondCodes Pred, int Opcode, ARMCC::CondCodes Pred,
unsigned PredReg, unsigned Scratch, DebugLoc dl, unsigned PredReg, unsigned Scratch, DebugLoc dl,
SmallVector<std::pair<unsigned, bool>, 8> &Regs) { ArrayRef<std::pair<unsigned, bool> > Regs,
ArrayRef<unsigned> ImpDefs) {
// Only a single register to load / store. Don't bother. // Only a single register to load / store. Don't bother.
unsigned NumRegs = Regs.size(); unsigned NumRegs = Regs.size();
if (NumRegs <= 1) if (NumRegs <= 1)
@ -350,6 +353,10 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef) MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef)
| getKillRegState(Regs[i].second)); | getKillRegState(Regs[i].second));
// Add implicit defs for super-registers.
for (unsigned i = 0, e = ImpDefs.size(); i != e; ++i)
MIB.addReg(ImpDefs[i], RegState::ImplicitDefine);
return true; return true;
} }
@ -384,19 +391,29 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
} }
SmallVector<std::pair<unsigned, bool>, 8> Regs; SmallVector<std::pair<unsigned, bool>, 8> Regs;
SmallVector<unsigned, 8> ImpDefs;
for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) { for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
unsigned Reg = memOps[i].Reg; unsigned Reg = memOps[i].Reg;
// If we are inserting the merged operation after an operation that // If we are inserting the merged operation after an operation that
// uses the same register, make sure to transfer any kill flag. // uses the same register, make sure to transfer any kill flag.
bool isKill = memOps[i].isKill || KilledRegs.count(Reg); bool isKill = memOps[i].isKill || KilledRegs.count(Reg);
Regs.push_back(std::make_pair(Reg, isKill)); Regs.push_back(std::make_pair(Reg, isKill));
// Collect any implicit defs of super-registers. They must be preserved.
for (MIOperands MO(memOps[i].MBBI); MO.isValid(); ++MO) {
if (!MO->isReg() || !MO->isDef() || !MO->isImplicit() || MO->isDead())
continue;
unsigned DefReg = MO->getReg();
if (std::find(ImpDefs.begin(), ImpDefs.end(), DefReg) == ImpDefs.end())
ImpDefs.push_back(DefReg);
}
} }
// Try to do the merge. // Try to do the merge.
MachineBasicBlock::iterator Loc = memOps[insertAfter].MBBI; MachineBasicBlock::iterator Loc = memOps[insertAfter].MBBI;
++Loc; ++Loc;
if (!MergeOps(MBB, Loc, Offset, Base, BaseKill, Opcode, if (!MergeOps(MBB, Loc, Offset, Base, BaseKill, Opcode,
Pred, PredReg, Scratch, dl, Regs)) Pred, PredReg, Scratch, dl, Regs, ImpDefs))
return; return;
// Merge succeeded, update records. // Merge succeeded, update records.

View File

@ -158,8 +158,10 @@ bool ARMPassConfig::addPreRegAlloc() {
bool ARMPassConfig::addPreSched2() { bool ARMPassConfig::addPreSched2() {
// FIXME: temporarily disabling load / store optimization pass for Thumb1. // FIXME: temporarily disabling load / store optimization pass for Thumb1.
if (getOptLevel() != CodeGenOpt::None) { if (getOptLevel() != CodeGenOpt::None) {
if (!getARMSubtarget().isThumb1Only()) if (!getARMSubtarget().isThumb1Only()) {
PM.add(createARMLoadStoreOptimizationPass()); PM.add(createARMLoadStoreOptimizationPass());
printAndVerify("After ARM load / store optimizer");
}
if (getARMSubtarget().hasNEON()) if (getARMSubtarget().hasNEON())
PM.add(createExecutionDependencyFixPass(&ARM::DPRRegClass)); PM.add(createExecutionDependencyFixPass(&ARM::DPRRegClass));
} }