aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorJim Grosbach <grosbach@apple.com>2009-10-07 17:12:56 +0000
committerJim Grosbach <grosbach@apple.com>2009-10-07 17:12:56 +0000
commitb58f498f7502e7e1833decbbbb4df771367c7341 (patch)
tree87f2fd132b2e82049b7648ad35e7c2c30b4ceeef /lib/CodeGen
parent7f93f4d66c54e2628fbd159fa19bcfbe601458ae (diff)
downloadexternal_llvm-b58f498f7502e7e1833decbbbb4df771367c7341.tar.gz
external_llvm-b58f498f7502e7e1833decbbbb4df771367c7341.tar.bz2
external_llvm-b58f498f7502e7e1833decbbbb4df771367c7341.zip
Add register-reuse to frame-index register scavenging. When a target uses
a virtual register to eliminate a frame index, it can return that register and the constant stored there to PEI to track. When scavenging to allocate for those registers, PEI then tracks the last-used register and value, and if it is still available and matches the value for the next index, reuses the existing value rather and removes the re-materialization instructions. Fancier tracking and adjustment of scavenger allocations to keep more values live for longer is possible, but not yet implemented and would likely be better done via a different, less special-purpose, approach to the problem. eliminateFrameIndex() is modified so the target implementations can return the registers they wish to be tracked for reuse. ARM Thumb1 implements and utilizes the new mechanism. All other targets are simply modified to adjust for the changed eliminateFrameIndex() prototype. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83467 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp141
-rw-r--r--lib/CodeGen/PrologEpilogInserter.h8
-rw-r--r--lib/CodeGen/RegisterScavenging.cpp2
3 files changed, 129 insertions, 22 deletions
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index 51c78a18d7..a2a8af397a 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/lib/CodeGen/PrologEpilogInserter.cpp
@@ -655,6 +655,11 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) {
int FrameSetupOpcode = TRI.getCallFrameSetupOpcode();
int FrameDestroyOpcode = TRI.getCallFrameDestroyOpcode();
+ // Pre-allocate space for frame index mappings. If more space is needed,
+ // the map will be grown later.
+ if (FrameIndexVirtualScavenging)
+ FrameConstantRegMap.grow(Fn.getRegInfo().getLastVirtReg() + 128);
+
for (MachineFunction::iterator BB = Fn.begin(),
E = Fn.end(); BB != E; ++BB) {
int SPAdj = 0; // SP offset due to call frame setup / destroy.
@@ -703,9 +708,17 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) {
// If this instruction has a FrameIndex operand, we need to
// use that target machine register info object to eliminate
// it.
-
- TRI.eliminateFrameIndex(MI, SPAdj, FrameIndexVirtualScavenging ?
- NULL : RS);
+ int Value;
+ unsigned VReg =
+ TRI.eliminateFrameIndex(MI, SPAdj, &Value,
+ FrameIndexVirtualScavenging ? NULL : RS);
+ if (VReg) {
+ assert (FrameIndexVirtualScavenging &&
+ "Not scavenging, but virtual returned from "
+ "eliminateFrameIndex()!");
+ FrameConstantRegMap.grow(VReg);
+ FrameConstantRegMap[VReg] = FrameConstantEntry(Value, SPAdj);
+ }
// Reset the iterator if we were at the beginning of the BB.
if (AtBeginning) {
@@ -727,6 +740,35 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) {
}
}
+/// findLastUseReg - find the killing use of the specified register within
+/// the instruciton range. Return the operand number of the kill in Operand.
+static MachineBasicBlock::iterator
+findLastUseReg(MachineBasicBlock::iterator I, MachineBasicBlock::iterator ME,
+ unsigned Reg, unsigned *Operand) {
+ // Scan forward to find the last use of this virtual register
+ for (++I; I != ME; ++I) {
+ MachineInstr *MI = I;
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
+ if (MI->getOperand(i).isReg()) {
+ unsigned OpReg = MI->getOperand(i).getReg();
+ if (OpReg == 0 || !TargetRegisterInfo::isVirtualRegister(OpReg))
+ continue;
+ assert (OpReg == Reg
+ && "overlapping use of scavenged index register!");
+ // If this is the killing use, we're done
+ if (MI->getOperand(i).isKill()) {
+ if (Operand)
+ *Operand = i;
+ return I;
+ }
+ }
+ }
+ // If we hit the end of the basic block, there was no kill of
+ // the virtual register, which is wrong.
+ assert (0 && "scavenged index register never killed!");
+ return ME;
+}
+
/// scavengeFrameVirtualRegs - Replace all frame index virtual registers
/// with physical registers. Use the register scavenger to find an
/// appropriate register to use.
@@ -738,12 +780,21 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
unsigned CurrentVirtReg = 0;
unsigned CurrentScratchReg = 0;
+ unsigned PrevScratchReg = 0;
+ int PrevValue;
+ MachineInstr *PrevLastUseMI;
+ unsigned PrevLastUseOp;
+ // The instruction stream may change in the loop, so check BB->end()
+ // directly.
for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
MachineInstr *MI = I;
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
+ // Likewise, call getNumOperands() each iteration, as the MI may change
+ // inside the loop (with 'i' updated accordingly).
+ for (unsigned i = 0; i != MI->getNumOperands(); ++i)
if (MI->getOperand(i).isReg()) {
- unsigned Reg = MI->getOperand(i).getReg();
+ MachineOperand &MO = MI->getOperand(i);
+ unsigned Reg = MO.getReg();
if (Reg == 0)
continue;
if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
@@ -751,33 +802,81 @@ void PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) {
// seeing any references to it.
assert (Reg != CurrentScratchReg
&& "overlapping use of scavenged frame index register!");
+
+ // If we have a previous scratch reg, check and see if anything
+ // here kills whatever value is in there.
+ if (Reg == PrevScratchReg) {
+ if (MO.isUse()) {
+ // Two-address operands implicitly kill
+ if (MO.isKill() || MI->isRegTiedToDefOperand(i))
+ PrevScratchReg = 0;
+ } else {
+ assert (MO.isDef());
+ PrevScratchReg = 0;
+ }
+ }
continue;
}
// If we already have a scratch for this virtual register, use it
if (Reg != CurrentVirtReg) {
- // When we first encounter a new virtual register, it
- // must be a definition.
- assert(MI->getOperand(i).isDef() &&
- "frame index virtual missing def!");
- // We can't have nested virtual register live ranges because
- // there's only a guarantee of one scavenged register at a time.
- assert (CurrentVirtReg == 0 &&
- "overlapping frame index virtual registers!");
- CurrentVirtReg = Reg;
- const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg);
- CurrentScratchReg = RS->FindUnusedReg(RC);
- if (CurrentScratchReg == 0)
- // No register is "free". Scavenge a register.
- // FIXME: Track SPAdj. Zero won't always be right
- CurrentScratchReg = RS->scavengeRegister(RC, I, 0);
+ int Value = FrameConstantRegMap[Reg].first;
+ int SPAdj = FrameConstantRegMap[Reg].second;
+
+ // If the scratch register from the last allocation is still
+ // available, see if the value matches. If it does, just re-use it.
+ if (PrevScratchReg && Value == PrevValue) {
+ // FIXME: This assumes that the instructions in the live range
+ // for the virtual register are exclusively for the purpose
+ // of populating the value in the register. That reasonable
+ // for these frame index registers, but it's still a very, very
+ // strong assumption. Perhaps this implies that the frame index
+ // elimination should be before register allocation, with
+ // conservative heuristics since we'll know less then, and
+ // the reuse calculations done directly when doing the code-gen?
+
+ // Find the last use of the new virtual register. Remove all
+ // instruction between here and there, and update the current
+ // instruction to reference the last use insn instead.
+ MachineBasicBlock::iterator LastUseMI =
+ findLastUseReg(I, BB->end(), Reg, &i);
+ // Remove all instructions up 'til the last use, since they're
+ // just calculating the value we already have.
+ BB->erase(I, LastUseMI);
+ MI = I = LastUseMI;
+
+ CurrentScratchReg = PrevScratchReg;
+ // Extend the live range of the register
+ PrevLastUseMI->getOperand(PrevLastUseOp).setIsKill(false);
+ RS->setUsed(CurrentScratchReg);
+ } else {
+ // When we first encounter a new virtual register, it
+ // must be a definition.
+ assert(MI->getOperand(i).isDef() &&
+ "frame index virtual missing def!");
+ // We can't have nested virtual register live ranges because
+ // there's only a guarantee of one scavenged register at a time.
+ assert (CurrentVirtReg == 0 &&
+ "overlapping frame index virtual registers!");
+ CurrentVirtReg = Reg;
+ const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg);
+ CurrentScratchReg = RS->FindUnusedReg(RC);
+ if (CurrentScratchReg == 0)
+ // No register is "free". Scavenge a register.
+ CurrentScratchReg = RS->scavengeRegister(RC, I, SPAdj);
+
+ PrevValue = Value;
+ }
}
assert (CurrentScratchReg && "Missing scratch register!");
MI->getOperand(i).setReg(CurrentScratchReg);
// If this is the last use of the register, stop tracking it.
- if (MI->getOperand(i).isKill())
+ if (MI->getOperand(i).isKill()) {
+ PrevScratchReg = CurrentScratchReg;
+ PrevLastUseMI = MI;
CurrentScratchReg = CurrentVirtReg = 0;
+ }
}
RS->forward(MI);
}
diff --git a/lib/CodeGen/PrologEpilogInserter.h b/lib/CodeGen/PrologEpilogInserter.h
index d0a68e19a2..ee759e8622 100644
--- a/lib/CodeGen/PrologEpilogInserter.h
+++ b/lib/CodeGen/PrologEpilogInserter.h
@@ -27,6 +27,8 @@
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/Target/TargetRegisterInfo.h"
namespace llvm {
class RegScavenger;
@@ -93,6 +95,12 @@ namespace llvm {
// functions.
bool ShrinkWrapThisFunction;
+ // When using the scavenger post-pass to resolve frame reference
+ // materialization registers, maintain a map of the registers to
+ // the constant value and SP adjustment associated with it.
+ typedef std::pair<int, int> FrameConstantEntry;
+ IndexedMap<FrameConstantEntry, VirtReg2IndexFunctor> FrameConstantRegMap;
+
#ifndef NDEBUG
// Machine function handle.
MachineFunction* MF;
diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp
index 8c792325e1..5f1c4e2594 100644
--- a/lib/CodeGen/RegisterScavenging.cpp
+++ b/lib/CodeGen/RegisterScavenging.cpp
@@ -306,7 +306,7 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
"Cannot scavenge register without an emergency spill slot!");
TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC);
MachineBasicBlock::iterator II = prior(I);
- TRI->eliminateFrameIndex(II, SPAdj, this);
+ TRI->eliminateFrameIndex(II, SPAdj, NULL, this);
// Restore the scavenged register before its use (or first terminator).
TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC);