aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2011-02-15 19:51:58 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2011-02-15 19:51:58 +0000
commit79bb6dd363fd0a23040910b32d69a282063521bd (patch)
tree3cfdf3de1bb60807889b15a92021a015b1afc199
parentd3526eab46b96509d3195cf3367811af67b6d2c7 (diff)
downloadexternal_llvm-79bb6dd363fd0a23040910b32d69a282063521bd.zip
external_llvm-79bb6dd363fd0a23040910b32d69a282063521bd.tar.gz
external_llvm-79bb6dd363fd0a23040910b32d69a282063521bd.tar.bz2
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
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp36
1 files changed, 15 insertions, 21 deletions
diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index f6d4076..d9dc5cd 100644
--- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -379,22 +379,14 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
// First calculate which of the registers should be killed by the merged
// instruction.
const unsigned insertPos = memOps[insertAfter].Position;
-
- SmallSet<unsigned, 4> UnavailRegs;
SmallSet<unsigned, 4> KilledRegs;
DenseMap<unsigned, unsigned> Killer;
- for (unsigned i = 0; i < memOpsBegin; ++i) {
- if (memOps[i].Position < insertPos && memOps[i].isKill) {
- unsigned Reg = memOps[i].Reg;
- if (memOps[i].Merged)
- UnavailRegs.insert(Reg);
- else {
- KilledRegs.insert(Reg);
- Killer[Reg] = i;
- }
+ for (unsigned i = 0, e = memOps.size(); i != e; ++i) {
+ if (i == memOpsBegin) {
+ i = memOpsEnd;
+ if (i == e)
+ break;
}
- }
- for (unsigned i = memOpsEnd, e = memOps.size(); i != e; ++i) {
if (memOps[i].Position < insertPos && memOps[i].isKill) {
unsigned Reg = memOps[i].Reg;
KilledRegs.insert(Reg);
@@ -405,12 +397,7 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
SmallVector<std::pair<unsigned, bool>, 8> Regs;
for (unsigned i = memOpsBegin; i < memOpsEnd; ++i) {
unsigned Reg = memOps[i].Reg;
- if (UnavailRegs.count(Reg))
- // 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
+ // If we are inserting the merged operation after an operation that
// uses the same register, make sure to transfer any kill flag.
bool isKill = memOps[i].isKill || KilledRegs.count(Reg);
Regs.push_back(std::make_pair(Reg, isKill));
@@ -426,17 +413,24 @@ void ARMLoadStoreOpt::MergeOpsUpdate(MachineBasicBlock &MBB,
// Merge succeeded, update records.
Merges.push_back(prior(Loc));
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) {
unsigned Reg = Regs[i-memOpsBegin].first;
if (KilledRegs.count(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[i].isKill = true;
}
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].MBBI = Merges.back();
+ memOps[i].Position = insertPos;
}
}