Teach ARMLoadStoreOptimizer to remove kill flags from merged instructions as well.

This is necessary to avoid a crash in certain tangled situations where a kill
flag is first correctly moved to a merged instruction, and then needs to be
moved again:

  STR %R0, a...
  STR %R0<kill>, b...

First becomes:

  STR %R0, b...
  STM a, %R0<kill>, ...

and then:

  STM a, %R0, ...
  STM b, %R0<kill>, ...

We can now remove the kill flag from the merged STM when needed. 8960050.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125591 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2011-02-15 19:51:58 +00:00
parent d3526eab46
commit 79bb6dd363

View File

@ -379,22 +379,14 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
// First calculate which of the registers should be killed by the merged // First calculate which of the registers should be killed by the merged
// instruction. // instruction.
const unsigned insertPos = memOps[insertAfter].Position; const unsigned insertPos = memOps[insertAfter].Position;
SmallSet<unsigned, 4> UnavailRegs;
SmallSet<unsigned, 4> KilledRegs; SmallSet<unsigned, 4> KilledRegs;
DenseMap<unsigned, unsigned> Killer; DenseMap<unsigned, unsigned> Killer;
for (unsigned i = 0; i < memOpsBegin; ++i) { for (unsigned i = 0, e = memOps.size(); i != e; ++i) {
if (memOps[i].Position < insertPos && memOps[i].isKill) { if (i == memOpsBegin) {
unsigned Reg = memOps[i].Reg; i = memOpsEnd;
if (memOps[i].Merged) if (i == e)
UnavailRegs.insert(Reg); break;
else {
KilledRegs.insert(Reg);
Killer[Reg] = i;
}
} }
}
for (unsigned i = memOpsEnd, e = memOps.size(); i != e; ++i) {
if (memOps[i].Position < insertPos && memOps[i].isKill) { if (memOps[i].Position < insertPos && memOps[i].isKill) {
unsigned Reg = memOps[i].Reg; unsigned Reg = memOps[i].Reg;
KilledRegs.insert(Reg); KilledRegs.insert(Reg);
@ -405,12 +397,7 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
SmallVector<std::pair<unsigned, bool>, 8> Regs; SmallVector<std::pair<unsigned, bool>, 8> Regs;
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 (UnavailRegs.count(Reg)) // If we are inserting the merged operation after an operation that
// Register is killed before and it's not easy / possible to update the
// kill marker on already merged instructions. Abort.
return;
// If we are inserting the merged operation after an unmerged 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));
@ -426,17 +413,24 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
// Merge succeeded, update records. // Merge succeeded, update records.
Merges.push_back(prior(Loc)); Merges.push_back(prior(Loc));
for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) { for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
// Remove kill flags from any unmerged memops that come before insertPos. // Remove kill flags from any memops that come before insertPos.
if (Regs[i-memOpsBegin].second) { if (Regs[i-memOpsBegin].second) {
unsigned Reg = Regs[i-memOpsBegin].first; unsigned Reg = Regs[i-memOpsBegin].first;
if (KilledRegs.count(Reg)) { if (KilledRegs.count(Reg)) {
unsigned j = Killer[Reg]; unsigned j = Killer[Reg];
memOps[j].MBBI->getOperand(0).setIsKill(false); int Idx = memOps[j].MBBI->findRegisterUseOperandIdx(Reg, true);
assert(Idx >= 0 && "Cannot find killing operand");
memOps[j].MBBI->getOperand(Idx).setIsKill(false);
memOps[j].isKill = false; memOps[j].isKill = false;
} }
memOps[i].isKill = true;
} }
MBB.erase(memOps[i].MBBI); MBB.erase(memOps[i].MBBI);
// Update this memop to refer to the merged instruction.
// We may need to move kill flags again.
memOps[i].Merged = true; memOps[i].Merged = true;
memOps[i].MBBI = Merges.back();
memOps[i].Position = insertPos;
} }
} }