forked from OSchip/llvm-project
[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:
parent
7b1c8168c7
commit
45b3ddc5a4
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue