Allow target to specify regclass for which antideps will only be broken along the critical path.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@88682 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Goodwin 2009-11-13 19:52:48 +00:00
parent a8173b934f
commit 87d21b92fc
9 changed files with 123 additions and 44 deletions

View File

@ -38,7 +38,7 @@ public:
// AntiDepBreakMode - Type of anti-dependence breaking that should // AntiDepBreakMode - Type of anti-dependence breaking that should
// be performed before post-RA scheduling. // be performed before post-RA scheduling.
typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode;
typedef SmallVectorImpl<TargetRegisterClass*> ExcludedRCVector; typedef SmallVectorImpl<TargetRegisterClass*> RegClassVector;
virtual ~TargetSubtarget(); virtual ~TargetSubtarget();
@ -50,10 +50,12 @@ public:
// enablePostRAScheduler - If the target can benefit from post-regalloc // enablePostRAScheduler - If the target can benefit from post-regalloc
// scheduling and the specified optimization level meets the requirement // scheduling and the specified optimization level meets the requirement
// return true to enable post-register-allocation scheduling. // return true to enable post-register-allocation scheduling. In
// CriticalPathRCs return any register classes that should only be broken
// if on the critical path.
virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
AntiDepBreakMode& Mode, AntiDepBreakMode& Mode,
ExcludedRCVector& ExcludedRCs) const; RegClassVector& CriticalPathRCs) const;
// adjustSchedDependency - Perform target specific adjustments to // adjustSchedDependency - Perform target specific adjustments to
// the latency of a schedule dependency. // the latency of a schedule dependency.
virtual void adjustSchedDependency(SUnit *def, SUnit *use, virtual void adjustSchedDependency(SUnit *def, SUnit *use,

View File

@ -54,10 +54,13 @@ unsigned AggressiveAntiDepState::GetGroup(unsigned Reg)
return Node; return Node;
} }
void AggressiveAntiDepState::GetGroupRegs(unsigned Group, std::vector<unsigned> &Regs) void AggressiveAntiDepState::GetGroupRegs(
unsigned Group,
std::vector<unsigned> &Regs,
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference> *RegRefs)
{ {
for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) { for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) {
if (GetGroup(Reg) == Group) if ((GetGroup(Reg) == Group) && (RegRefs->count(Reg) > 0))
Regs.push_back(Reg); Regs.push_back(Reg);
} }
} }
@ -100,23 +103,27 @@ bool AggressiveAntiDepState::IsLive(unsigned Reg)
AggressiveAntiDepBreaker:: AggressiveAntiDepBreaker::
AggressiveAntiDepBreaker(MachineFunction& MFi, AggressiveAntiDepBreaker(MachineFunction& MFi,
TargetSubtarget::ExcludedRCVector& ExcludedRCs) : TargetSubtarget::RegClassVector& CriticalPathRCs) :
AntiDepBreaker(), MF(MFi), AntiDepBreaker(), MF(MFi),
MRI(MF.getRegInfo()), MRI(MF.getRegInfo()),
TRI(MF.getTarget().getRegisterInfo()), TRI(MF.getTarget().getRegisterInfo()),
AllocatableSet(TRI->getAllocatableSet(MF)), AllocatableSet(TRI->getAllocatableSet(MF)),
State(NULL), SavedState(NULL) { State(NULL), SavedState(NULL) {
/* Remove all registers from excluded RCs from the allocatable /* Collect a bitset of all registers that are only broken if they
register set. */ are on the critical path. */
for (unsigned i = 0, e = ExcludedRCs.size(); i < e; ++i) { for (unsigned i = 0, e = CriticalPathRCs.size(); i < e; ++i) {
BitVector NotRenameable = TRI->getAllocatableSet(MF, ExcludedRCs[i]).flip(); BitVector CPSet = TRI->getAllocatableSet(MF, CriticalPathRCs[i]);
AllocatableSet &= NotRenameable; if (CriticalPathSet.none())
} CriticalPathSet = CPSet;
else
DEBUG(errs() << "AntiDep Renameable Registers:"); CriticalPathSet |= CPSet;
DEBUG(for (int r = AllocatableSet.find_first(); r != -1; }
r = AllocatableSet.find_next(r))
DEBUG(errs() << "AntiDep Critical-Path Registers:");
DEBUG(for (int r = CriticalPathSet.find_first(); r != -1;
r = CriticalPathSet.find_next(r))
errs() << " " << TRI->getName(r)); errs() << " " << TRI->getName(r));
DEBUG(errs() << '\n');
} }
AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() { AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() {
@ -276,9 +283,11 @@ void AggressiveAntiDepBreaker::GetPassthruRegs(MachineInstr *MI,
} }
} }
/// AntiDepPathStep - Return SUnit that SU has an anti-dependence on. /// AntiDepEdges - Return in Edges the anti- and output-
static void AntiDepPathStep(SUnit *SU, AntiDepBreaker::AntiDepRegVector& Regs, /// dependencies on Regs in SU that we want to consider for breaking.
std::vector<SDep*>& Edges) { static void AntiDepEdges(SUnit *SU,
const AntiDepBreaker::AntiDepRegVector& Regs,
std::vector<SDep*>& Edges) {
AntiDepBreaker::AntiDepRegSet RegSet; AntiDepBreaker::AntiDepRegSet RegSet;
for (unsigned i = 0, e = Regs.size(); i < e; ++i) for (unsigned i = 0, e = Regs.size(); i < e; ++i)
RegSet.insert(Regs[i]); RegSet.insert(Regs[i]);
@ -297,6 +306,31 @@ static void AntiDepPathStep(SUnit *SU, AntiDepBreaker::AntiDepRegVector& Regs,
assert(RegSet.empty() && "Expected all antidep registers to be found"); assert(RegSet.empty() && "Expected all antidep registers to be found");
} }
/// CriticalPathStep - Return the next SUnit after SU on the bottom-up
/// critical path.
static SUnit *CriticalPathStep(SUnit *SU) {
SDep *Next = 0;
unsigned NextDepth = 0;
// Find the predecessor edge with the greatest depth.
if (SU != 0) {
for (SUnit::pred_iterator P = SU->Preds.begin(), PE = SU->Preds.end();
P != PE; ++P) {
SUnit *PredSU = P->getSUnit();
unsigned PredLatency = P->getLatency();
unsigned PredTotalLatency = PredSU->getDepth() + PredLatency;
// In the case of a latency tie, prefer an anti-dependency edge over
// other types of edges.
if (NextDepth < PredTotalLatency ||
(NextDepth == PredTotalLatency && P->getKind() == SDep::Anti)) {
NextDepth = PredTotalLatency;
Next = &*P;
}
}
}
return (Next) ? Next->getSUnit() : 0;
}
void AggressiveAntiDepBreaker::HandleLastUse(unsigned Reg, unsigned KillIdx, void AggressiveAntiDepBreaker::HandleLastUse(unsigned Reg, unsigned KillIdx,
const char *tag) { const char *tag) {
unsigned *KillIndices = State->GetKillIndices(); unsigned *KillIndices = State->GetKillIndices();
@ -511,11 +545,11 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>& std::multimap<unsigned, AggressiveAntiDepState::RegisterReference>&
RegRefs = State->GetRegRefs(); RegRefs = State->GetRegRefs();
// Collect all registers in the same group as AntiDepReg. These all // Collect all referenced registers in the same group as
// need to be renamed together if we are to break the // AntiDepReg. These all need to be renamed together if we are to
// anti-dependence. // break the anti-dependence.
std::vector<unsigned> Regs; std::vector<unsigned> Regs;
State->GetGroupRegs(AntiDepGroupIndex, Regs); State->GetGroupRegs(AntiDepGroupIndex, Regs, &RegRefs);
assert(Regs.size() > 0 && "Empty register group!"); assert(Regs.size() > 0 && "Empty register group!");
if (Regs.size() == 0) if (Regs.size() == 0)
return false; return false;
@ -556,9 +590,10 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
} }
// FIXME: for now just handle single register in group case... // FIXME: for now just handle single register in group case...
// FIXME: check only regs that have references... if (Regs.size() > 1) {
if (Regs.size() > 1) DEBUG(errs() << "\tMultiple rename registers in group\n");
return false; return false;
}
// Check each possible rename register for SuperReg in round-robin // Check each possible rename register for SuperReg in round-robin
// order. If that register is available, and the corresponding // order. If that register is available, and the corresponding
@ -666,6 +701,24 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(
MISUnitMap.insert(std::pair<MachineInstr *, SUnit *>(SU->getInstr(), SU)); MISUnitMap.insert(std::pair<MachineInstr *, SUnit *>(SU->getInstr(), SU));
} }
// Track progress along the critical path through the SUnit graph as
// we walk the instructions. This is needed for regclasses that only
// break critical-path anti-dependencies.
SUnit *CriticalPathSU = 0;
MachineInstr *CriticalPathMI = 0;
if (CriticalPathSet.any()) {
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
SUnit *SU = &SUnits[i];
if (!CriticalPathSU ||
((SU->getDepth() + SU->Latency) >
(CriticalPathSU->getDepth() + CriticalPathSU->Latency))) {
CriticalPathSU = SU;
}
}
CriticalPathMI = CriticalPathSU->getInstr();
}
// Even if there are no anti-dependencies we still need to go // Even if there are no anti-dependencies we still need to go
// through the instructions to update Def, Kills, etc. // through the instructions to update Def, Kills, etc.
#ifndef NDEBUG #ifndef NDEBUG
@ -700,14 +753,26 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(
// Process the defs in MI... // Process the defs in MI...
PrescanInstruction(MI, Count, PassthruRegs); PrescanInstruction(MI, Count, PassthruRegs);
// The the dependence edges that represent anti- and output-
// dependencies that are candidates for breaking.
std::vector<SDep*> Edges; std::vector<SDep*> Edges;
SUnit *PathSU = MISUnitMap[MI]; SUnit *PathSU = MISUnitMap[MI];
AntiDepBreaker::CandidateMap::iterator AntiDepBreaker::CandidateMap::iterator
citer = Candidates.find(PathSU); citer = Candidates.find(PathSU);
if (citer != Candidates.end()) if (citer != Candidates.end())
AntiDepPathStep(PathSU, citer->second, Edges); AntiDepEdges(PathSU, citer->second, Edges);
// If MI is not on the critical path, then we don't rename
// registers in the CriticalPathSet.
BitVector *ExcludeRegs = NULL;
if (MI == CriticalPathMI) {
CriticalPathSU = CriticalPathStep(CriticalPathSU);
CriticalPathMI = (CriticalPathSU) ? CriticalPathSU->getInstr() : 0;
} else {
ExcludeRegs = &CriticalPathSet;
}
// Ignore KILL instructions (they form a group in ScanInstruction // Ignore KILL instructions (they form a group in ScanInstruction
// but don't cause any anti-dependence breaking themselves) // but don't cause any anti-dependence breaking themselves)
if (MI->getOpcode() != TargetInstrInfo::KILL) { if (MI->getOpcode() != TargetInstrInfo::KILL) {
@ -727,6 +792,11 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(
// Don't break anti-dependencies on non-allocatable registers. // Don't break anti-dependencies on non-allocatable registers.
DEBUG(errs() << " (non-allocatable)\n"); DEBUG(errs() << " (non-allocatable)\n");
continue; continue;
} else if ((ExcludeRegs != NULL) && ExcludeRegs->test(AntiDepReg)) {
// Don't break anti-dependencies for critical path registers
// if not on the critical path
DEBUG(errs() << " (not critical-path)\n");
continue;
} else if (PassthruRegs.count(AntiDepReg) != 0) { } else if (PassthruRegs.count(AntiDepReg) != 0) {
// If the anti-dep register liveness "passes-thru", then // If the anti-dep register liveness "passes-thru", then
// don't try to change it. It will be changed along with // don't try to change it. It will be changed along with

View File

@ -86,8 +86,11 @@ namespace llvm {
unsigned GetGroup(unsigned Reg); unsigned GetGroup(unsigned Reg);
// GetGroupRegs - Return a vector of the registers belonging to a // GetGroupRegs - Return a vector of the registers belonging to a
// group. // group. If RegRefs is non-NULL then only included referenced registers.
void GetGroupRegs(unsigned Group, std::vector<unsigned> &Regs); void GetGroupRegs(
unsigned Group,
std::vector<unsigned> &Regs,
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference> *RegRefs);
// UnionGroups - Union Reg1's and Reg2's groups to form a new // UnionGroups - Union Reg1's and Reg2's groups to form a new
// group. Return the index of the GroupNode representing the // group. Return the index of the GroupNode representing the
@ -113,7 +116,11 @@ namespace llvm {
/// AllocatableSet - The set of allocatable registers. /// AllocatableSet - The set of allocatable registers.
/// We'll be ignoring anti-dependencies on non-allocatable registers, /// We'll be ignoring anti-dependencies on non-allocatable registers,
/// because they may not be safe to break. /// because they may not be safe to break.
BitVector AllocatableSet; const BitVector AllocatableSet;
/// CriticalPathSet - The set of registers that should only be
/// renamed if they are on the critical path.
BitVector CriticalPathSet;
/// State - The state used to identify and rename anti-dependence /// State - The state used to identify and rename anti-dependence
/// registers. /// registers.
@ -126,7 +133,7 @@ namespace llvm {
public: public:
AggressiveAntiDepBreaker(MachineFunction& MFi, AggressiveAntiDepBreaker(MachineFunction& MFi,
TargetSubtarget::ExcludedRCVector& ExcludedRCs); TargetSubtarget::RegClassVector& CriticalPathRCs);
~AggressiveAntiDepBreaker(); ~AggressiveAntiDepBreaker();
/// GetMaxTrials - As anti-dependencies are broken, additional /// GetMaxTrials - As anti-dependencies are broken, additional

View File

@ -216,14 +216,14 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
// Check for explicit enable/disable of post-ra scheduling. // Check for explicit enable/disable of post-ra scheduling.
TargetSubtarget::AntiDepBreakMode AntiDepMode = TargetSubtarget::ANTIDEP_NONE; TargetSubtarget::AntiDepBreakMode AntiDepMode = TargetSubtarget::ANTIDEP_NONE;
SmallVector<TargetRegisterClass*, 4> ExcludedRCs; SmallVector<TargetRegisterClass*, 4> CriticalPathRCs;
if (EnablePostRAScheduler.getPosition() > 0) { if (EnablePostRAScheduler.getPosition() > 0) {
if (!EnablePostRAScheduler) if (!EnablePostRAScheduler)
return false; return false;
} else { } else {
// Check that post-RA scheduling is enabled for this target. // Check that post-RA scheduling is enabled for this target.
const TargetSubtarget &ST = Fn.getTarget().getSubtarget<TargetSubtarget>(); const TargetSubtarget &ST = Fn.getTarget().getSubtarget<TargetSubtarget>();
if (!ST.enablePostRAScheduler(OptLevel, AntiDepMode, ExcludedRCs)) if (!ST.enablePostRAScheduler(OptLevel, AntiDepMode, CriticalPathRCs))
return false; return false;
} }
@ -244,7 +244,7 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
(ScheduleHazardRecognizer *)new SimpleHazardRecognizer(); (ScheduleHazardRecognizer *)new SimpleHazardRecognizer();
AntiDepBreaker *ADB = AntiDepBreaker *ADB =
((AntiDepMode == TargetSubtarget::ANTIDEP_ALL) ? ((AntiDepMode == TargetSubtarget::ANTIDEP_ALL) ?
(AntiDepBreaker *)new AggressiveAntiDepBreaker(Fn, ExcludedRCs) : (AntiDepBreaker *)new AggressiveAntiDepBreaker(Fn, CriticalPathRCs) :
((AntiDepMode == TargetSubtarget::ANTIDEP_CRITICAL) ? ((AntiDepMode == TargetSubtarget::ANTIDEP_CRITICAL) ?
(AntiDepBreaker *)new CriticalAntiDepBreaker(Fn) : NULL)); (AntiDepBreaker *)new CriticalAntiDepBreaker(Fn) : NULL));

View File

@ -164,9 +164,9 @@ ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const {
bool ARMSubtarget::enablePostRAScheduler( bool ARMSubtarget::enablePostRAScheduler(
CodeGenOpt::Level OptLevel, CodeGenOpt::Level OptLevel,
TargetSubtarget::AntiDepBreakMode& Mode, TargetSubtarget::AntiDepBreakMode& Mode,
ExcludedRCVector& ExcludedRCs) const { RegClassVector& CriticalPathRCs) const {
Mode = TargetSubtarget::ANTIDEP_CRITICAL; Mode = TargetSubtarget::ANTIDEP_CRITICAL;
ExcludedRCs.clear(); CriticalPathRCs.clear();
ExcludedRCs.push_back(&ARM::GPRRegClass); CriticalPathRCs.push_back(&ARM::GPRRegClass);
return PostRAScheduler && OptLevel >= CodeGenOpt::Default; return PostRAScheduler && OptLevel >= CodeGenOpt::Default;
} }

View File

@ -130,7 +130,7 @@ protected:
/// enablePostRAScheduler - True at 'More' optimization. /// enablePostRAScheduler - True at 'More' optimization.
bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
TargetSubtarget::AntiDepBreakMode& Mode, TargetSubtarget::AntiDepBreakMode& Mode,
ExcludedRCVector& ExcludedRCs) const; RegClassVector& CriticalPathRCs) const;
/// getInstrItins - Return the instruction itineraies based on subtarget /// getInstrItins - Return the instruction itineraies based on subtarget
/// selection. /// selection.

View File

@ -25,9 +25,9 @@ TargetSubtarget::~TargetSubtarget() {}
bool TargetSubtarget::enablePostRAScheduler( bool TargetSubtarget::enablePostRAScheduler(
CodeGenOpt::Level OptLevel, CodeGenOpt::Level OptLevel,
AntiDepBreakMode& Mode, AntiDepBreakMode& Mode,
ExcludedRCVector& ExcludedRCs) const { RegClassVector& CriticalPathRCs) const {
Mode = ANTIDEP_NONE; Mode = ANTIDEP_NONE;
ExcludedRCs.clear(); CriticalPathRCs.clear();
return false; return false;
} }

View File

@ -460,8 +460,8 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS,
bool X86Subtarget::enablePostRAScheduler( bool X86Subtarget::enablePostRAScheduler(
CodeGenOpt::Level OptLevel, CodeGenOpt::Level OptLevel,
TargetSubtarget::AntiDepBreakMode& Mode, TargetSubtarget::AntiDepBreakMode& Mode,
ExcludedRCVector& ExcludedRCs) const { RegClassVector& CriticalPathRCs) const {
Mode = TargetSubtarget::ANTIDEP_CRITICAL; Mode = TargetSubtarget::ANTIDEP_CRITICAL;
ExcludedRCs.clear(); CriticalPathRCs.clear();
return OptLevel >= CodeGenOpt::Default; return OptLevel >= CodeGenOpt::Default;
} }

View File

@ -220,7 +220,7 @@ public:
/// at 'More' optimization level. /// at 'More' optimization level.
bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
TargetSubtarget::AntiDepBreakMode& Mode, TargetSubtarget::AntiDepBreakMode& Mode,
ExcludedRCVector& ExcludedRCs) const; RegClassVector& CriticalPathRCs) const;
}; };
} // End llvm namespace } // End llvm namespace