[MachineCopyPropagation] Refactor copy tracking into a class. NFC

This is a bit easier to follow than handling the copy and src maps
directly in the pass, and will make upcoming changes to how this is
done easier to follow.

llvm-svn: 342703
This commit is contained in:
Justin Bogner 2018-09-21 00:51:04 +00:00
parent 7b1c8168c7
commit 45b3ddc5a4
1 changed files with 133 additions and 99 deletions

View File

@ -74,9 +74,115 @@ DEBUG_COUNTER(FwdCounter, "machine-cp-fwd",
namespace {
using RegList = SmallVector<unsigned, 4>;
using SourceMap = DenseMap<unsigned, RegList>;
using Reg2MIMap = DenseMap<unsigned, MachineInstr *>;
class CopyTracker {
using RegList = SmallVector<unsigned, 4>;
using SourceMap = DenseMap<unsigned, RegList>;
using Reg2MIMap = DenseMap<unsigned, MachineInstr *>;
/// Def -> available copies map.
Reg2MIMap AvailCopyMap;
/// Def -> copies map.
Reg2MIMap CopyMap;
/// Src -> Def map
SourceMap SrcMap;
public:
/// Mark all of the given registers and their subregisters as unavailable for
/// copying.
void markRegsUnavailable(const RegList &Regs, const TargetRegisterInfo &TRI) {
for (unsigned Reg : Regs) {
// Source of copy is no longer available for propagation.
for (MCSubRegIterator SR(Reg, &TRI, true); SR.isValid(); ++SR)
AvailCopyMap.erase(*SR);
}
}
/// Remove any entry in the tracker's copy maps that is marked clobbered in \p
/// RegMask. The map will typically have a lot fewer entries than the regmask
/// clobbers, so this is more efficient than iterating the clobbered registers
/// and calling ClobberRegister() on them.
void removeClobberedRegs(const MachineOperand &RegMask,
const TargetRegisterInfo &TRI) {
auto RemoveFromMap = [&RegMask](Reg2MIMap &Map) {
for (Reg2MIMap::iterator I = Map.begin(), E = Map.end(), Next; I != E;
I = Next) {
Next = std::next(I);
if (RegMask.clobbersPhysReg(I->first))
Map.erase(I);
}
};
RemoveFromMap(AvailCopyMap);
RemoveFromMap(CopyMap);
for (SourceMap::iterator I = SrcMap.begin(), E = SrcMap.end(), Next; I != E;
I = Next) {
Next = std::next(I);
if (RegMask.clobbersPhysReg(I->first)) {
markRegsUnavailable(I->second, TRI);
SrcMap.erase(I);
}
}
}
/// Clobber a single register, removing it from the tracker's copy maps.
void clobberRegister(unsigned Reg, const TargetRegisterInfo &TRI) {
for (MCRegAliasIterator AI(Reg, &TRI, true); AI.isValid(); ++AI) {
CopyMap.erase(*AI);
AvailCopyMap.erase(*AI);
SourceMap::iterator SI = SrcMap.find(*AI);
if (SI != SrcMap.end()) {
markRegsUnavailable(SI->second, TRI);
SrcMap.erase(SI);
}
}
}
/// Add this copy's registers into the tracker's copy maps.
void trackCopy(MachineInstr *Copy, const TargetRegisterInfo &TRI) {
assert(Copy->isCopy() && "Tracking non-copy?");
unsigned Def = Copy->getOperand(0).getReg();
unsigned Src = Copy->getOperand(1).getReg();
// Remember Def is defined by the copy.
for (MCSubRegIterator SR(Def, &TRI, /*IncludeSelf=*/true); SR.isValid();
++SR) {
CopyMap[*SR] = Copy;
AvailCopyMap[*SR] = Copy;
}
// Remember source that's copied to Def. Once it's clobbered, then
// it's no longer available for copy propagation.
RegList &DestList = SrcMap[Src];
if (!is_contained(DestList, Def))
DestList.push_back(Def);
}
bool hasAvailableCopies() { return !AvailCopyMap.empty(); }
MachineInstr *findAvailCopy(unsigned Reg) {
auto CI = AvailCopyMap.find(Reg);
if (CI != AvailCopyMap.end())
return CI->second;
return nullptr;
}
MachineInstr *findCopy(unsigned Reg) {
auto CI = CopyMap.find(Reg);
if (CI != CopyMap.end())
return CI->second;
return nullptr;
}
void clear() {
AvailCopyMap.clear();
CopyMap.clear();
SrcMap.clear();
}
};
class MachineCopyPropagation : public MachineFunctionPass {
const TargetRegisterInfo *TRI;
@ -115,14 +221,7 @@ private:
/// Candidates for deletion.
SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;
/// Def -> available copies map.
Reg2MIMap AvailCopyMap;
/// Def -> copies map.
Reg2MIMap CopyMap;
/// Src -> Def map
SourceMap SrcMap;
CopyTracker Tracker;
bool Changed;
};
@ -136,54 +235,13 @@ char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE,
"Machine Copy Propagation Pass", false, false)
/// Remove any entry in \p Map where the register is a subregister or equal to
/// a register contained in \p Regs.
static void removeRegsFromMap(Reg2MIMap &Map, const RegList &Regs,
const TargetRegisterInfo &TRI) {
for (unsigned Reg : Regs) {
// Source of copy is no longer available for propagation.
for (MCSubRegIterator SR(Reg, &TRI, true); SR.isValid(); ++SR)
Map.erase(*SR);
}
}
/// Remove any entry in \p Map that is marked clobbered in \p RegMask.
/// The map will typically have a lot fewer entries than the regmask clobbers,
/// so this is more efficient than iterating the clobbered registers and calling
/// ClobberRegister() on them.
static void removeClobberedRegsFromMap(Reg2MIMap &Map,
const MachineOperand &RegMask) {
for (Reg2MIMap::iterator I = Map.begin(), E = Map.end(), Next; I != E;
I = Next) {
Next = std::next(I);
unsigned Reg = I->first;
if (RegMask.clobbersPhysReg(Reg))
Map.erase(I);
}
}
void MachineCopyPropagation::ClobberRegister(unsigned Reg) {
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
CopyMap.erase(*AI);
AvailCopyMap.erase(*AI);
SourceMap::iterator SI = SrcMap.find(*AI);
if (SI != SrcMap.end()) {
removeRegsFromMap(AvailCopyMap, SI->second, *TRI);
SrcMap.erase(SI);
}
}
}
void MachineCopyPropagation::ReadRegister(unsigned Reg) {
// If 'Reg' is defined by a copy, the copy is no longer a candidate
// for elimination.
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
Reg2MIMap::iterator CI = CopyMap.find(*AI);
if (CI != CopyMap.end()) {
LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: ";
CI->second->dump());
MaybeDeadCopies.remove(CI->second);
if (MachineInstr *Copy = Tracker.findCopy(*AI)) {
LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());
MaybeDeadCopies.remove(Copy);
}
}
}
@ -219,15 +277,14 @@ bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy, unsigned Src,
return false;
// Search for an existing copy.
Reg2MIMap::iterator CI = AvailCopyMap.find(Def);
if (CI == AvailCopyMap.end())
MachineInstr *PrevCopy = Tracker.findAvailCopy(Def);
if (!PrevCopy)
return false;
// Check that the existing copy uses the correct sub registers.
MachineInstr &PrevCopy = *CI->second;
if (PrevCopy.getOperand(0).isDead())
if (PrevCopy->getOperand(0).isDead())
return false;
if (!isNopCopy(PrevCopy, Src, Def, TRI))
if (!isNopCopy(*PrevCopy, Src, Def, TRI))
return false;
LLVM_DEBUG(dbgs() << "MCP: copy is a NOP, removing: "; Copy.dump());
@ -238,7 +295,7 @@ bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy, unsigned Src,
unsigned CopyDef = Copy.getOperand(0).getReg();
assert(CopyDef == Src || CopyDef == Def);
for (MachineInstr &MI :
make_range(PrevCopy.getIterator(), Copy.getIterator()))
make_range(PrevCopy->getIterator(), Copy.getIterator()))
MI.clearRegisterKills(CopyDef, TRI);
Copy.eraseFromParent();
@ -314,7 +371,7 @@ bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,
/// Look for available copies whose destination register is used by \p MI and
/// replace the use in \p MI with the copy's source register.
void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
if (AvailCopyMap.empty())
if (!Tracker.hasAvailableCopies())
return;
// Look for non-tied explicit vreg uses that have an active COPY
@ -341,13 +398,12 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
if (!MOUse.isRenamable())
continue;
auto CI = AvailCopyMap.find(MOUse.getReg());
if (CI == AvailCopyMap.end())
MachineInstr *Copy = Tracker.findAvailCopy(MOUse.getReg());
if (!Copy)
continue;
MachineInstr &Copy = *CI->second;
unsigned CopyDstReg = Copy.getOperand(0).getReg();
const MachineOperand &CopySrc = Copy.getOperand(1);
unsigned CopyDstReg = Copy->getOperand(0).getReg();
const MachineOperand &CopySrc = Copy->getOperand(1);
unsigned CopySrcReg = CopySrc.getReg();
// FIXME: Don't handle partial uses of wider COPYs yet.
@ -362,7 +418,7 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
if (MRI->isReserved(CopySrcReg) && !MRI->isConstantPhysReg(CopySrcReg))
continue;
if (!isForwardableRegClassCopy(Copy, MI, OpIdx))
if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
continue;
if (hasImplicitOverlap(MI, MOUse))
@ -376,7 +432,7 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
LLVM_DEBUG(dbgs() << "MCP: Replacing " << printReg(MOUse.getReg(), TRI)
<< "\n with " << printReg(CopySrcReg, TRI)
<< "\n in " << MI << " from " << Copy);
<< "\n in " << MI << " from " << *Copy);
MOUse.setReg(CopySrcReg);
if (!CopySrc.isRenamable())
@ -386,7 +442,7 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
// Clear kill markers that may have been invalidated.
for (MachineInstr &KMI :
make_range(Copy.getIterator(), std::next(MI.getIterator())))
make_range(Copy->getIterator(), std::next(MI.getIterator())))
KMI.clearRegisterKills(CopySrcReg, TRI);
++NumCopyForwards;
@ -459,28 +515,17 @@ void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
// %xmm2 = copy %xmm0
// ...
// %xmm2 = copy %xmm9
ClobberRegister(Def);
Tracker.clobberRegister(Def, *TRI);
for (const MachineOperand &MO : MI->implicit_operands()) {
if (!MO.isReg() || !MO.isDef())
continue;
unsigned Reg = MO.getReg();
if (!Reg)
continue;
ClobberRegister(Reg);
Tracker.clobberRegister(Reg, *TRI);
}
// Remember Def is defined by the copy.
for (MCSubRegIterator SR(Def, TRI, /*IncludeSelf=*/true); SR.isValid();
++SR) {
CopyMap[*SR] = MI;
AvailCopyMap[*SR] = MI;
}
// Remember source that's copied to Def. Once it's clobbered, then
// it's no longer available for copy propagation.
RegList &DestList = SrcMap[Src];
if (!is_contained(DestList, Def))
DestList.push_back(Def);
Tracker.trackCopy(MI, *TRI);
continue;
}
@ -494,7 +539,7 @@ void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
// later.
if (MO.isTied())
ReadRegister(Reg);
ClobberRegister(Reg);
Tracker.clobberRegister(Reg, *TRI);
}
forwardUses(*MI);
@ -549,21 +594,12 @@ void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
++NumDeletes;
}
removeClobberedRegsFromMap(AvailCopyMap, *RegMask);
removeClobberedRegsFromMap(CopyMap, *RegMask);
for (SourceMap::iterator I = SrcMap.begin(), E = SrcMap.end(), Next;
I != E; I = Next) {
Next = std::next(I);
if (RegMask->clobbersPhysReg(I->first)) {
removeRegsFromMap(AvailCopyMap, I->second, *TRI);
SrcMap.erase(I);
}
}
Tracker.removeClobberedRegs(*RegMask, *TRI);
}
// Any previous copy definition or reading the Defs is no longer available.
for (unsigned Reg : Defs)
ClobberRegister(Reg);
Tracker.clobberRegister(Reg, *TRI);
}
// If MBB doesn't have successors, delete the copies whose defs are not used.
@ -581,9 +617,7 @@ void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
}
MaybeDeadCopies.clear();
AvailCopyMap.clear();
CopyMap.clear();
SrcMap.clear();
Tracker.clear();
}
bool MachineCopyPropagation::runOnMachineFunction(MachineFunction &MF) {