Skip to content

Commit

Permalink
RegisterScavenging: Move scavenging logic from PEI to RegisterScaveng…
Browse files Browse the repository at this point in the history
…ing; NFC

These parts do not depend on any PrologEpilogInserter logic and
therefore better fits RegisterScaveging.cpp.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304596 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
MatzeB committed Jun 2, 2017
1 parent efbf6a8 commit 465de97
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 96 deletions.
4 changes: 4 additions & 0 deletions include/llvm/CodeGen/RegisterScavenging.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ class RegScavenger {
void setLiveInsUsed(const MachineBasicBlock &MBB);
};

/// Replaces all frame index virtual registers with physical registers. Uses the
/// register scavenger to find an appropriate register to use.
void scavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger &RS);

} // end namespace llvm

#endif // LLVM_CODEGEN_REGISTERSCAVENGING_H
100 changes: 4 additions & 96 deletions lib/CodeGen/PrologEpilogInserter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ static void doSpillCalleeSavedRegs(MachineFunction &MF, RegScavenger *RS,
const MBBVector &SaveBlocks,
const MBBVector &RestoreBlocks);

static void doScavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger *RS);

namespace {
class PEI : public MachineFunctionPass {
public:
Expand Down Expand Up @@ -84,7 +82,7 @@ class PEI : public MachineFunctionPass {
const MBBVector &SaveBlocks,
const MBBVector &RestoreBlocks)>
SpillCalleeSavedRegisters;
std::function<void(MachineFunction &MF, RegScavenger *RS)>
std::function<void(MachineFunction &MF, RegScavenger &RS)>
ScavengeFrameVirtualRegs;

bool UsesCalleeSaves = false;
Expand Down Expand Up @@ -142,7 +140,6 @@ MachineFunctionPass *llvm::createPrologEpilogInserterPass() {
return new PEI();
}

STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged");
STATISTIC(NumBytesStackSpace,
"Number of bytes used for stack in all functions");

Expand All @@ -168,10 +165,10 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
SpillCalleeSavedRegisters = [](MachineFunction &, RegScavenger *,
unsigned &, unsigned &, const MBBVector &,
const MBBVector &) {};
ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger *) {};
ScavengeFrameVirtualRegs = [](MachineFunction &, RegScavenger &) {};
} else {
SpillCalleeSavedRegisters = doSpillCalleeSavedRegs;
ScavengeFrameVirtualRegs = doScavengeFrameVirtualRegs;
ScavengeFrameVirtualRegs = scavengeFrameVirtualRegs;
UsesCalleeSaves = true;
}
}
Expand Down Expand Up @@ -222,7 +219,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) {
// post-pass, scavenge the virtual registers that frame index elimination
// inserted.
if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) {
ScavengeFrameVirtualRegs(Fn, RS);
ScavengeFrameVirtualRegs(Fn, *RS);

// Clear any vregs created by virtual scavenging.
Fn.getRegInfo().clearVirtRegs();
Expand Down Expand Up @@ -1153,92 +1150,3 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn,
RS->forward(MI);
}
}

/// doScavengeFrameVirtualRegs - Replace all frame index virtual registers
/// with physical registers. Use the register scavenger to find an
/// appropriate register to use.
///
/// FIXME: Iterating over the instruction stream is unnecessary. We can simply
/// iterate over the vreg use list, which at this point only contains machine
/// operands for which eliminateFrameIndex need a new scratch reg.
static void
doScavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger *RS) {
// Run through the instructions and find any virtual registers.
MachineRegisterInfo &MRI = MF.getRegInfo();
for (MachineBasicBlock &MBB : MF) {
RS->enterBasicBlock(MBB);

int SPAdj = 0;

// The instruction stream may change in the loop, so check MBB.end()
// directly.
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.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 MBB.
if (I == MachineBasicBlock::iterator(nullptr))
I = MBB.begin();

const MachineInstr &MI = *I;
MachineBasicBlock::iterator J = std::next(I);
MachineBasicBlock::iterator P =
I == MBB.begin() ? MachineBasicBlock::iterator(nullptr)
: std::prev(I);

// RS should process this instruction before we might scavenge at this
// location. This is because we might be replacing a virtual register
// defined by this instruction, and if so, registers killed by this
// instruction are available, and defined registers are not.
RS->forward(I);

for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg())
continue;
unsigned Reg = MO.getReg();
if (!TargetRegisterInfo::isVirtualRegister(Reg))
continue;

// When we first encounter a new virtual register, it
// must be a definition.
assert(MO.isDef() && "frame index virtual missing def!");
// Scavenge a new scratch register
const TargetRegisterClass *RC = MRI.getRegClass(Reg);
unsigned ScratchReg = RS->scavengeRegister(RC, J, SPAdj);

++NumScavengedRegs;

// Replace this reference to the virtual register with the
// scratch register.
assert(ScratchReg && "Missing scratch register!");
MRI.replaceRegWith(Reg, ScratchReg);

// Because this instruction was processed by the RS before this
// register was allocated, make sure that the RS now records the
// register as being used.
RS->setRegUsed(ScratchReg);
}

// If the scavenger needed to use one of its spill slots, the
// spill code will have been inserted in between I and J. This is a
// problem because we need the spill code before I: Move I to just
// prior to J.
if (I != std::prev(J)) {
MBB.splice(J, &MBB, 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;
}
}

MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
}
88 changes: 88 additions & 0 deletions lib/CodeGen/RegisterScavenging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
Expand All @@ -39,6 +40,8 @@ using namespace llvm;

#define DEBUG_TYPE "reg-scavenging"

STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged");

void RegScavenger::setRegUsed(unsigned Reg, LaneBitmask LaneMask) {
LiveUnits.addRegMasked(Reg, LaneMask);
}
Expand Down Expand Up @@ -469,3 +472,88 @@ unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,

return SReg;
}

void llvm::scavengeFrameVirtualRegs(MachineFunction &MF, RegScavenger &RS) {
// FIXME: Iterating over the instruction stream is unnecessary. We can simply
// iterate over the vreg use list, which at this point only contains machine
// operands for which eliminateFrameIndex need a new scratch reg.

// Run through the instructions and find any virtual registers.
MachineRegisterInfo &MRI = MF.getRegInfo();
for (MachineBasicBlock &MBB : MF) {
RS.enterBasicBlock(MBB);

int SPAdj = 0;

// The instruction stream may change in the loop, so check MBB.end()
// directly.
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.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 MBB.
if (I == MachineBasicBlock::iterator(nullptr))
I = MBB.begin();

const MachineInstr &MI = *I;
MachineBasicBlock::iterator J = std::next(I);
MachineBasicBlock::iterator P =
I == MBB.begin() ? MachineBasicBlock::iterator(nullptr)
: std::prev(I);

// RS should process this instruction before we might scavenge at this
// location. This is because we might be replacing a virtual register
// defined by this instruction, and if so, registers killed by this
// instruction are available, and defined registers are not.
RS.forward(I);

for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg())
continue;
unsigned Reg = MO.getReg();
if (!TargetRegisterInfo::isVirtualRegister(Reg))
continue;

// When we first encounter a new virtual register, it
// must be a definition.
assert(MO.isDef() && "frame index virtual missing def!");
// Scavenge a new scratch register
const TargetRegisterClass *RC = MRI.getRegClass(Reg);
unsigned ScratchReg = RS.scavengeRegister(RC, J, SPAdj);

++NumScavengedRegs;

// Replace this reference to the virtual register with the
// scratch register.
assert(ScratchReg && "Missing scratch register!");
MRI.replaceRegWith(Reg, ScratchReg);

// Because this instruction was processed by the RS before this
// register was allocated, make sure that the RS now records the
// register as being used.
RS.setRegUsed(ScratchReg);
}

// If the scavenger needed to use one of its spill slots, the
// spill code will have been inserted in between I and J. This is a
// problem because we need the spill code before I: Move I to just
// prior to J.
if (I != std::prev(J)) {
MBB.splice(J, &MBB, 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;
}
}

MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
}

0 comments on commit 465de97

Please sign in to comment.