summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2013-04-05 22:31:56 +0000
committerHal Finkel <hfinkel@anl.gov>2013-04-05 22:31:56 +0000
commit2e80991a7712d51f7637513703fc896f93eea252 (patch)
tree93aeec83934b6b577cb4a396d98ab938f63a4706
parent13bbe1f52e8d57151e2730db49094e1c62a4c793 (diff)
downloadllvm-2e80991a7712d51f7637513703fc896f93eea252.tar.gz
llvm-2e80991a7712d51f7637513703fc896f93eea252.tar.bz2
llvm-2e80991a7712d51f7637513703fc896f93eea252.tar.xz
Reapply r178845 with fix - Fix bug in PEI's virtual-register scavenging
This fixes PEI as previously described, but correctly handles the case where the instruction defining the virtual register to be scavenged is the first in the block. Arnold provided me with a bugpoint-reduced test case, but even that seems too large to use as a regression test. If I'm successful in cleaning it up then I'll commit that as well. Original commit message: This change fixes a bug that I introduced in r178058. After a register is scavenged using one of the available spills slots the instruction defining the virtual register needs to be moved to after the spill code. The scavenger has already processed the defining instruction so that registers killed by that instruction are available for definition in that same instruction. Unfortunately, after this, the scavenger needs to iterate through the spill code and then visit, again, the instruction that defines the now-scavenged register. In order to avoid confusion, the register scavenger needs the ability to 'back up' through the spill code so that it can again process the instructions in the appropriate order. Prior to this fix, once the scavenger reached the just-moved instruction, it would assert if it killed any registers because, having already processed the instruction, it believed they were undefined. Unfortunately, I don't yet have a small test case. Thanks to Pranav Bhandarkar for diagnosing the problem and testing this fix. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178919 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h17
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp22
-rw-r--r--lib/CodeGen/RegisterScavenging.cpp72
3 files changed, 87 insertions, 24 deletions
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 49d16892f8..95bf29167c 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -93,6 +93,15 @@ public:
while (MBBI != I) forward();
}
+ /// Invert the behavior of forward() on the current instruction (undo the
+ /// changes to the available registers made by forward()).
+ void unprocess();
+
+ /// Unprocess instructions until you reach the provided iterator.
+ void unprocess(MachineBasicBlock::iterator I) {
+ while (MBBI != I) unprocess();
+ }
+
/// skipTo - Move the internal MBB iterator but do not update register states.
void skipTo(MachineBasicBlock::iterator I) {
if (I == MachineBasicBlock::iterator(NULL))
@@ -100,6 +109,10 @@ public:
MBBI = I;
}
+ MachineBasicBlock::iterator getCurrentPosition() const {
+ return MBBI;
+ }
+
/// getRegsUsed - return all registers currently in use in used.
void getRegsUsed(BitVector &used, bool includeReserved);
@@ -171,6 +184,10 @@ private:
RegsAvailable |= Regs;
}
+ /// Processes the current instruction and fill the KillRegs and DefRegs bit
+ /// vectors.
+ void determineKillsAndDefs();
+
/// Add Reg and all its sub-registers to BV.
void addRegWithSubRegs(BitVector &BV, unsigned Reg);
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index 5a168dd244..959dd7df58 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/lib/CodeGen/PrologEpilogInserter.cpp
@@ -824,8 +824,16 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
// The instruction stream may change in the loop, so check BB->end()
// directly.
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) {
+ // We might end up here again with a NULL iterator if we scavenged a
+ // register for which we inserted spill code for definition by what was
+ // originally the first instruction in BB.
+ if (I == MachineBasicBlock::iterator(NULL))
+ I = BB->begin();
+
MachineInstr *MI = I;
MachineBasicBlock::iterator J = llvm::next(I);
+ MachineBasicBlock::iterator P = I == BB->begin() ?
+ MachineBasicBlock::iterator(NULL) : llvm::prior(I);
// RS should process this instruction before we might scavenge at this
// location. This is because we might be replacing a virtual register
@@ -869,8 +877,18 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
// problem because we need the spill code before I: Move I to just
// prior to J.
if (I != llvm::prior(J)) {
- BB->splice(J, BB, I++);
- RS->skipTo(I == BB->begin() ? NULL : llvm::prior(I));
+ BB->splice(J, BB, I);
+
+ // Before we move I, we need to prepare the RS to visit I again.
+ // Specifically, RS will assert if it sees uses of registers that
+ // it believes are undefined. Because we have already processed
+ // register kills in I, when it visits I again, it will believe that
+ // those registers are undefined. To avoid this situation, unprocess
+ // the instruction I.
+ assert(RS->getCurrentPosition() == I &&
+ "The register scavenger has an unexpected position");
+ I = P;
+ RS->unprocess(P);
} else
++I;
}
diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp
index 55a66ba548..f82ccbe84d 100644
--- a/lib/CodeGen/RegisterScavenging.cpp
+++ b/lib/CodeGen/RegisterScavenging.cpp
@@ -110,30 +110,11 @@ void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) {
BV.set(*SubRegs);
}
-void RegScavenger::forward() {
- // Move ptr forward.
- if (!Tracking) {
- MBBI = MBB->begin();
- Tracking = true;
- } else {
- assert(MBBI != MBB->end() && "Already past the end of the basic block!");
- MBBI = llvm::next(MBBI);
- }
- assert(MBBI != MBB->end() && "Already at the end of the basic block!");
+void RegScavenger::determineKillsAndDefs() {
+ assert(Tracking && "Must be tracking to determine kills and defs");
MachineInstr *MI = MBBI;
-
- for (SmallVector<ScavengedInfo, 2>::iterator I = Scavenged.begin(),
- IE = Scavenged.end(); I != IE; ++I) {
- if (I->Restore != MI)
- continue;
-
- I->Reg = 0;
- I->Restore = NULL;
- }
-
- if (MI->isDebugValue())
- return;
+ assert(!MI->isDebugValue() && "Debug values have no kills or defs");
// Find out which registers are early clobbered, killed, defined, and marked
// def-dead in this instruction.
@@ -167,6 +148,53 @@ void RegScavenger::forward() {
addRegWithSubRegs(DefRegs, Reg);
}
}
+}
+
+void RegScavenger::unprocess() {
+ assert(Tracking && "Cannot unprocess because we're not tracking");
+
+ MachineInstr *MI = MBBI;
+ if (!MI->isDebugValue()) {
+ determineKillsAndDefs();
+
+ // Commit the changes.
+ setUsed(KillRegs);
+ setUnused(DefRegs);
+ }
+
+ if (MBBI == MBB->begin()) {
+ MBBI = MachineBasicBlock::iterator(NULL);
+ Tracking = false;
+ } else
+ --MBBI;
+}
+
+void RegScavenger::forward() {
+ // Move ptr forward.
+ if (!Tracking) {
+ MBBI = MBB->begin();
+ Tracking = true;
+ } else {
+ assert(MBBI != MBB->end() && "Already past the end of the basic block!");
+ MBBI = llvm::next(MBBI);
+ }
+ assert(MBBI != MBB->end() && "Already at the end of the basic block!");
+
+ MachineInstr *MI = MBBI;
+
+ for (SmallVector<ScavengedInfo, 2>::iterator I = Scavenged.begin(),
+ IE = Scavenged.end(); I != IE; ++I) {
+ if (I->Restore != MI)
+ continue;
+
+ I->Reg = 0;
+ I->Restore = NULL;
+ }
+
+ if (MI->isDebugValue())
+ return;
+
+ determineKillsAndDefs();
// Verify uses and defs.
#ifndef NDEBUG