forked from OSchip/llvm-project
Add "blocked" heuristic to the Hexagon MI scheduler.
Improve AQ instruction selection in the Hexagon MI scheduler. llvm-svn: 163523
This commit is contained in:
parent
ca8b950317
commit
ef4cc11cf9
|
@ -190,6 +190,9 @@ void VLIWMachineScheduler::initRegPressure() {
|
|||
std::vector<unsigned> RegionPressure = RPTracker.getPressure().MaxSetPressure;
|
||||
for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
|
||||
unsigned Limit = TRI->getRegPressureSetLimit(i);
|
||||
DEBUG(dbgs() << TRI->getRegPressureSetName(i)
|
||||
<< "Limit " << Limit
|
||||
<< " Actual " << RegionPressure[i] << "\n");
|
||||
if (RegionPressure[i] > Limit)
|
||||
RegionCriticalPSets.push_back(PressureElement(i, 0));
|
||||
}
|
||||
|
@ -199,11 +202,6 @@ void VLIWMachineScheduler::initRegPressure() {
|
|||
RegionCriticalPSets[i].PSetID) << " ";
|
||||
dbgs() << "\n");
|
||||
|
||||
// Reset resource state.
|
||||
TopResourceModel->resetPacketState();
|
||||
TopResourceModel->resetDFA();
|
||||
BotResourceModel->resetPacketState();
|
||||
BotResourceModel->resetDFA();
|
||||
TotalPackets = 0;
|
||||
}
|
||||
|
||||
|
@ -264,13 +262,15 @@ bool VLIWResourceModel::isResourceAvailable(SUnit *SU) {
|
|||
}
|
||||
|
||||
/// Keep track of available resources.
|
||||
void VLIWResourceModel::reserveResources(SUnit *SU) {
|
||||
bool VLIWResourceModel::reserveResources(SUnit *SU) {
|
||||
bool startNewCycle = false;
|
||||
// If this SU does not fit in the packet
|
||||
// start a new one.
|
||||
if (!isResourceAvailable(SU)) {
|
||||
ResourcesModel->clearResources();
|
||||
Packet.clear();
|
||||
TotalPackets++;
|
||||
startNewCycle = true;
|
||||
}
|
||||
|
||||
switch (SU->getInstr()->getOpcode()) {
|
||||
|
@ -295,7 +295,8 @@ void VLIWResourceModel::reserveResources(SUnit *SU) {
|
|||
DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n");
|
||||
for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
|
||||
DEBUG(dbgs() << "\t[" << i << "] SU(");
|
||||
DEBUG(dbgs() << Packet[i]->NodeNum << ")\n");
|
||||
DEBUG(dbgs() << Packet[i]->NodeNum << ")\t");
|
||||
DEBUG(Packet[i]->getInstr()->dump());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -305,7 +306,10 @@ void VLIWResourceModel::reserveResources(SUnit *SU) {
|
|||
ResourcesModel->clearResources();
|
||||
Packet.clear();
|
||||
TotalPackets++;
|
||||
startNewCycle = true;
|
||||
}
|
||||
|
||||
return startNewCycle;
|
||||
}
|
||||
|
||||
// Release all DAG roots for scheduling.
|
||||
|
@ -352,6 +356,17 @@ void VLIWMachineScheduler::schedule() {
|
|||
// Initialize top/bottom trackers after computing region pressure.
|
||||
initRegPressure();
|
||||
|
||||
// To view Height/Depth correctly, they should be accessed at least once.
|
||||
DEBUG(unsigned maxH = 0;
|
||||
for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
|
||||
if (SUnits[su].getHeight() > maxH)
|
||||
maxH = SUnits[su].getHeight();
|
||||
dbgs() << "Max Height " << maxH << "\n";);
|
||||
DEBUG(unsigned maxD = 0;
|
||||
for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
|
||||
if (SUnits[su].getDepth() > maxD)
|
||||
maxD = SUnits[su].getDepth();
|
||||
dbgs() << "Max Depth " << maxD << "\n";);
|
||||
DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
|
||||
SUnits[su].dumpAll(this));
|
||||
|
||||
|
@ -390,13 +405,9 @@ void VLIWMachineScheduler::schedule() {
|
|||
assert(TopRPTracker.getPos() == CurrentTop && "out of sync");
|
||||
updateScheduledPressure(TopRPTracker.getPressure().MaxSetPressure);
|
||||
|
||||
// Update DFA state.
|
||||
TopResourceModel->reserveResources(SU);
|
||||
|
||||
// Release dependent instructions for scheduling.
|
||||
releaseSuccessors(SU);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
assert(SU->isBottomReady() && "node still has unscheduled dependencies");
|
||||
MachineBasicBlock::iterator priorII =
|
||||
priorNonDebug(CurrentBottom, CurrentTop);
|
||||
|
@ -415,9 +426,6 @@ void VLIWMachineScheduler::schedule() {
|
|||
assert(BotRPTracker.getPos() == CurrentBottom && "out of sync");
|
||||
updateScheduledPressure(BotRPTracker.getPressure().MaxSetPressure);
|
||||
|
||||
// Update DFA state.
|
||||
BotResourceModel->reserveResources(SU);
|
||||
|
||||
// Release dependent instructions for scheduling.
|
||||
releasePredecessors(SU);
|
||||
}
|
||||
|
@ -426,9 +434,6 @@ void VLIWMachineScheduler::schedule() {
|
|||
}
|
||||
assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
|
||||
|
||||
DEBUG(dbgs() << "Final schedule has " << TopResourceModel->getTotalPackets() +
|
||||
BotResourceModel->getTotalPackets()<< "packets.\n");
|
||||
|
||||
placeDebugValues();
|
||||
}
|
||||
|
||||
|
@ -465,6 +470,9 @@ void ConvergingVLIWScheduler::initialize(VLIWMachineScheduler *dag) {
|
|||
Top.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG);
|
||||
Bot.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG);
|
||||
|
||||
Top.ResourceModel = new VLIWResourceModel(TM);
|
||||
Bot.ResourceModel = new VLIWResourceModel(TM);
|
||||
|
||||
assert((!ForceTopDown || !ForceBottomUp) &&
|
||||
"-misched-topdown incompatible with -misched-bottomup");
|
||||
}
|
||||
|
@ -553,8 +561,7 @@ void ConvergingVLIWScheduler::SchedBoundary::bumpCycle() {
|
|||
if (!HazardRec->isEnabled()) {
|
||||
// Bypass HazardRec virtual calls.
|
||||
CurrCycle = NextCycle;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// Bypass getHazardType calls in case of long latency.
|
||||
for (; CurrCycle != NextCycle; ++CurrCycle) {
|
||||
if (isTop())
|
||||
|
@ -571,6 +578,7 @@ void ConvergingVLIWScheduler::SchedBoundary::bumpCycle() {
|
|||
|
||||
/// Move the boundary of scheduled code by one SUnit.
|
||||
void ConvergingVLIWScheduler::SchedBoundary::bumpNode(SUnit *SU) {
|
||||
bool startNewCycle = false;
|
||||
|
||||
// Update the reservation table.
|
||||
if (HazardRec->isEnabled()) {
|
||||
|
@ -581,13 +589,20 @@ void ConvergingVLIWScheduler::SchedBoundary::bumpNode(SUnit *SU) {
|
|||
}
|
||||
HazardRec->EmitInstruction(SU);
|
||||
}
|
||||
|
||||
// Update DFA model.
|
||||
startNewCycle = ResourceModel->reserveResources(SU);
|
||||
|
||||
// Check the instruction group dispatch limit.
|
||||
// TODO: Check if this SU must end a dispatch group.
|
||||
IssueCount += DAG->getNumMicroOps(SU->getInstr());
|
||||
if (IssueCount >= DAG->getIssueWidth()) {
|
||||
if (startNewCycle) {
|
||||
DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n');
|
||||
bumpCycle();
|
||||
}
|
||||
else
|
||||
DEBUG(dbgs() << "*** IssueCount " << IssueCount
|
||||
<< " at cycle " << CurrCycle << '\n');
|
||||
}
|
||||
|
||||
/// Release pending ready nodes in to the available queue. This makes them
|
||||
|
@ -648,8 +663,9 @@ SUnit *ConvergingVLIWScheduler::SchedBoundary::pickOnlyChoice() {
|
|||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void ConvergingVLIWScheduler::traceCandidate(const char *Label, const ReadyQueue &Q,
|
||||
SUnit *SU, PressureElement P) {
|
||||
void ConvergingVLIWScheduler::traceCandidate(const char *Label,
|
||||
const ReadyQueue &Q,
|
||||
SUnit *SU, PressureElement P) {
|
||||
dbgs() << Label << " " << Q.getName() << " ";
|
||||
if (P.isValid())
|
||||
dbgs() << TRI->getRegPressureSetName(P.PSetID) << ":" << P.UnitIncrease
|
||||
|
@ -660,10 +676,48 @@ void ConvergingVLIWScheduler::traceCandidate(const char *Label, const ReadyQueue
|
|||
}
|
||||
#endif
|
||||
|
||||
/// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor
|
||||
/// of SU, return it, otherwise return null.
|
||||
static SUnit *getSingleUnscheduledPred(SUnit *SU) {
|
||||
SUnit *OnlyAvailablePred = 0;
|
||||
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
||||
I != E; ++I) {
|
||||
SUnit &Pred = *I->getSUnit();
|
||||
if (!Pred.isScheduled) {
|
||||
// We found an available, but not scheduled, predecessor. If it's the
|
||||
// only one we have found, keep track of it... otherwise give up.
|
||||
if (OnlyAvailablePred && OnlyAvailablePred != &Pred)
|
||||
return 0;
|
||||
OnlyAvailablePred = &Pred;
|
||||
}
|
||||
}
|
||||
return OnlyAvailablePred;
|
||||
}
|
||||
|
||||
/// getSingleUnscheduledSucc - If there is exactly one unscheduled successor
|
||||
/// of SU, return it, otherwise return null.
|
||||
static SUnit *getSingleUnscheduledSucc(SUnit *SU) {
|
||||
SUnit *OnlyAvailableSucc = 0;
|
||||
for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
|
||||
I != E; ++I) {
|
||||
SUnit &Succ = *I->getSUnit();
|
||||
if (!Succ.isScheduled) {
|
||||
// We found an available, but not scheduled, successor. If it's the
|
||||
// only one we have found, keep track of it... otherwise give up.
|
||||
if (OnlyAvailableSucc && OnlyAvailableSucc != &Succ)
|
||||
return 0;
|
||||
OnlyAvailableSucc = &Succ;
|
||||
}
|
||||
}
|
||||
return OnlyAvailableSucc;
|
||||
}
|
||||
|
||||
// Constants used to denote relative importance of
|
||||
// heuristic components for cost computation.
|
||||
static const unsigned PriorityOne = 200;
|
||||
static const unsigned PriorityTwo = 100;
|
||||
static const unsigned PriorityThree = 50;
|
||||
static const unsigned PriorityFour = 20;
|
||||
static const unsigned ScaleTwo = 10;
|
||||
static const unsigned FactorOne = 2;
|
||||
|
||||
|
@ -685,19 +739,44 @@ int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
|
|||
ResCount += PriorityOne;
|
||||
|
||||
// Critical path first.
|
||||
if (Q.getID() == TopQID)
|
||||
if (Q.getID() == TopQID) {
|
||||
ResCount += (SU->getHeight() * ScaleTwo);
|
||||
else
|
||||
|
||||
// If resources are available for it, multiply the
|
||||
// chance of scheduling.
|
||||
if (Top.ResourceModel->isResourceAvailable(SU))
|
||||
ResCount <<= FactorOne;
|
||||
} else {
|
||||
ResCount += (SU->getDepth() * ScaleTwo);
|
||||
|
||||
// If resources are available for it, multiply the
|
||||
// chance of scheduling.
|
||||
if (DAG->getTopResourceModel()->isResourceAvailable(SU))
|
||||
ResCount <<= FactorOne;
|
||||
// If resources are available for it, multiply the
|
||||
// chance of scheduling.
|
||||
if (Bot.ResourceModel->isResourceAvailable(SU))
|
||||
ResCount <<= FactorOne;
|
||||
}
|
||||
|
||||
unsigned NumNodesBlocking = 0;
|
||||
if (Q.getID() == TopQID) {
|
||||
// How many SUs does it block from scheduling?
|
||||
// Look at all of the successors of this node.
|
||||
// Count the number of nodes that
|
||||
// this node is the sole unscheduled node for.
|
||||
for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
|
||||
I != E; ++I)
|
||||
if (getSingleUnscheduledPred(I->getSUnit()) == SU)
|
||||
++NumNodesBlocking;
|
||||
} else {
|
||||
// How many unscheduled predecessors block this node?
|
||||
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
||||
I != E; ++I)
|
||||
if (getSingleUnscheduledSucc(I->getSUnit()) == SU)
|
||||
++NumNodesBlocking;
|
||||
}
|
||||
ResCount += (NumNodesBlocking * ScaleTwo);
|
||||
|
||||
// Factor in reg pressure as a heuristic.
|
||||
ResCount -= (Delta.Excess.UnitIncrease * PriorityThree);
|
||||
ResCount -= (Delta.CriticalMax.UnitIncrease * PriorityThree);
|
||||
ResCount -= (Delta.Excess.UnitIncrease*PriorityThree);
|
||||
ResCount -= (Delta.CriticalMax.UnitIncrease*PriorityThree);
|
||||
|
||||
DEBUG(if (verbose) dbgs() << " Total(" << ResCount << ")");
|
||||
|
||||
|
@ -736,7 +815,6 @@ pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker,
|
|||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Best cost.
|
||||
if (CurrentCost > Candidate.SCost) {
|
||||
DEBUG(traceCandidate("CCAND", Q, *I));
|
||||
|
@ -859,14 +937,14 @@ SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) {
|
|||
}
|
||||
|
||||
/// Update the scheduler's state after scheduling a node. This is the same node
|
||||
/// that was just returned by pickNode(). However, VLIWMachineScheduler needs to update
|
||||
/// it's state based on the current cycle before MachineSchedStrategy does.
|
||||
/// that was just returned by pickNode(). However, VLIWMachineScheduler needs
|
||||
/// to update it's state based on the current cycle before MachineSchedStrategy
|
||||
/// does.
|
||||
void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) {
|
||||
if (IsTopNode) {
|
||||
SU->TopReadyCycle = Top.CurrCycle;
|
||||
Top.bumpNode(SU);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
SU->BotReadyCycle = Bot.CurrCycle;
|
||||
Bot.bumpNode(SU);
|
||||
}
|
||||
|
|
|
@ -40,11 +40,10 @@ using namespace llvm;
|
|||
namespace llvm {
|
||||
class VLIWMachineScheduler;
|
||||
|
||||
/// MachineSchedStrategy - Interface used by VLIWMachineScheduler to drive the selected
|
||||
/// scheduling algorithm.
|
||||
/// MachineSchedStrategy - Interface used by VLIWMachineScheduler to drive
|
||||
/// the selected scheduling algorithm.
|
||||
///
|
||||
/// If this works well and targets wish to reuse VLIWMachineScheduler, we may expose it
|
||||
/// in ScheduleDAGInstrs.h
|
||||
/// TODO: Move this to ScheduleDAGInstrs.h
|
||||
class MachineSchedStrategy {
|
||||
public:
|
||||
virtual ~MachineSchedStrategy() {}
|
||||
|
@ -57,7 +56,8 @@ public:
|
|||
/// be scheduled at the bottom.
|
||||
virtual SUnit *pickNode(bool &IsTopNode) = 0;
|
||||
|
||||
/// Notify MachineSchedStrategy that VLIWMachineScheduler has scheduled a node.
|
||||
/// Notify MachineSchedStrategy that VLIWMachineScheduler has
|
||||
/// scheduled a node.
|
||||
virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
|
||||
|
||||
/// When all predecessor dependencies have been resolved, free this node for
|
||||
|
@ -69,7 +69,8 @@ public:
|
|||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConvergingVLIWScheduler - Implementation of the standard MachineSchedStrategy.
|
||||
// ConvergingVLIWScheduler - Implementation of the standard
|
||||
// MachineSchedStrategy.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
|
||||
|
@ -123,12 +124,197 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics to balance
|
||||
/// the schedule.
|
||||
class VLIWResourceModel {
|
||||
/// ResourcesModel - Represents VLIW state.
|
||||
/// Not limited to VLIW targets per say, but assumes
|
||||
/// definition of DFA by a target.
|
||||
DFAPacketizer *ResourcesModel;
|
||||
|
||||
const InstrItineraryData *InstrItins;
|
||||
|
||||
/// Local packet/bundle model. Purely
|
||||
/// internal to the MI schedulre at the time.
|
||||
std::vector<SUnit*> Packet;
|
||||
|
||||
/// Total packets created.
|
||||
unsigned TotalPackets;
|
||||
|
||||
public:
|
||||
VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) :
|
||||
InstrItins(IID), TotalPackets(0) {
|
||||
const TargetMachine &TM = C->MF->getTarget();
|
||||
ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
|
||||
|
||||
// This hard requirement could be relaxed,
|
||||
// but for now do not let it proceed.
|
||||
assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
|
||||
|
||||
Packet.resize(InstrItins->SchedModel->IssueWidth);
|
||||
Packet.clear();
|
||||
ResourcesModel->clearResources();
|
||||
}
|
||||
|
||||
VLIWResourceModel(const TargetMachine &TM) :
|
||||
InstrItins(TM.getInstrItineraryData()), TotalPackets(0) {
|
||||
ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
|
||||
|
||||
// This hard requirement could be relaxed,
|
||||
// but for now do not let it proceed.
|
||||
assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
|
||||
|
||||
Packet.resize(InstrItins->SchedModel->IssueWidth);
|
||||
Packet.clear();
|
||||
ResourcesModel->clearResources();
|
||||
}
|
||||
|
||||
~VLIWResourceModel() {
|
||||
delete ResourcesModel;
|
||||
}
|
||||
|
||||
void resetPacketState() {
|
||||
Packet.clear();
|
||||
}
|
||||
|
||||
void resetDFA() {
|
||||
ResourcesModel->clearResources();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
Packet.clear();
|
||||
ResourcesModel->clearResources();
|
||||
}
|
||||
|
||||
bool isResourceAvailable(SUnit *SU);
|
||||
bool reserveResources(SUnit *SU);
|
||||
unsigned getTotalPackets() const { return TotalPackets; }
|
||||
};
|
||||
|
||||
class VLIWMachineScheduler : public ScheduleDAGInstrs {
|
||||
/// AA - AliasAnalysis for making memory reference queries.
|
||||
AliasAnalysis *AA;
|
||||
|
||||
RegisterClassInfo *RegClassInfo;
|
||||
MachineSchedStrategy *SchedImpl;
|
||||
|
||||
MachineBasicBlock::iterator LiveRegionEnd;
|
||||
|
||||
/// Register pressure in this region computed by buildSchedGraph.
|
||||
IntervalPressure RegPressure;
|
||||
RegPressureTracker RPTracker;
|
||||
|
||||
/// List of pressure sets that exceed the target's pressure limit before
|
||||
/// scheduling, listed in increasing set ID order. Each pressure set is paired
|
||||
/// with its max pressure in the currently scheduled regions.
|
||||
std::vector<PressureElement> RegionCriticalPSets;
|
||||
|
||||
/// The top of the unscheduled zone.
|
||||
MachineBasicBlock::iterator CurrentTop;
|
||||
IntervalPressure TopPressure;
|
||||
RegPressureTracker TopRPTracker;
|
||||
|
||||
/// The bottom of the unscheduled zone.
|
||||
MachineBasicBlock::iterator CurrentBottom;
|
||||
IntervalPressure BotPressure;
|
||||
RegPressureTracker BotRPTracker;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// The number of instructions scheduled so far. Used to cut off the
|
||||
/// scheduler at the point determined by misched-cutoff.
|
||||
unsigned NumInstrsScheduled;
|
||||
#endif
|
||||
|
||||
/// Total packets in the region.
|
||||
unsigned TotalPackets;
|
||||
|
||||
const MachineLoopInfo *MLI;
|
||||
public:
|
||||
VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S):
|
||||
ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
|
||||
AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S),
|
||||
RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure),
|
||||
CurrentBottom(), BotRPTracker(BotPressure), MLI(C->MLI) {
|
||||
#ifndef NDEBUG
|
||||
NumInstrsScheduled = 0;
|
||||
#endif
|
||||
TotalPackets = 0;
|
||||
}
|
||||
|
||||
virtual ~VLIWMachineScheduler() {
|
||||
delete SchedImpl;
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator top() const { return CurrentTop; }
|
||||
MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
|
||||
|
||||
/// Implement the ScheduleDAGInstrs interface for handling the next scheduling
|
||||
/// region. This covers all instructions in a block, while schedule() may only
|
||||
/// cover a subset.
|
||||
void enterRegion(MachineBasicBlock *bb,
|
||||
MachineBasicBlock::iterator begin,
|
||||
MachineBasicBlock::iterator end,
|
||||
unsigned endcount);
|
||||
|
||||
/// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
|
||||
/// time to do some work.
|
||||
void schedule();
|
||||
|
||||
unsigned CurCycle;
|
||||
|
||||
/// Get current register pressure for the top scheduled instructions.
|
||||
const IntervalPressure &getTopPressure() const { return TopPressure; }
|
||||
const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
|
||||
|
||||
/// Get current register pressure for the bottom scheduled instructions.
|
||||
const IntervalPressure &getBotPressure() const { return BotPressure; }
|
||||
const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
|
||||
|
||||
/// Get register pressure for the entire scheduling region before scheduling.
|
||||
const IntervalPressure &getRegPressure() const { return RegPressure; }
|
||||
|
||||
const std::vector<PressureElement> &getRegionCriticalPSets() const {
|
||||
return RegionCriticalPSets;
|
||||
}
|
||||
|
||||
/// getIssueWidth - Return the max instructions per scheduling group.
|
||||
unsigned getIssueWidth() const {
|
||||
return (InstrItins && InstrItins->SchedModel)
|
||||
? InstrItins->SchedModel->IssueWidth : 1;
|
||||
}
|
||||
|
||||
/// getNumMicroOps - Return the number of issue slots required for this MI.
|
||||
unsigned getNumMicroOps(MachineInstr *MI) const {
|
||||
return 1;
|
||||
//if (!InstrItins) return 1;
|
||||
//int UOps = InstrItins->getNumMicroOps(MI->getDesc().getSchedClass());
|
||||
//return (UOps >= 0) ? UOps : TII->getNumMicroOps(InstrItins, MI);
|
||||
}
|
||||
|
||||
private:
|
||||
void scheduleNodeTopDown(SUnit *SU);
|
||||
void listScheduleTopDown();
|
||||
|
||||
void initRegPressure();
|
||||
void updateScheduledPressure(std::vector<unsigned> NewMaxPressure);
|
||||
|
||||
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
|
||||
bool checkSchedLimit();
|
||||
|
||||
void releaseRoots();
|
||||
|
||||
void releaseSucc(SUnit *SU, SDep *SuccEdge);
|
||||
void releaseSuccessors(SUnit *SU);
|
||||
void releasePred(SUnit *SU, SDep *PredEdge);
|
||||
void releasePredecessors(SUnit *SU);
|
||||
|
||||
void placeDebugValues();
|
||||
};
|
||||
|
||||
/// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics
|
||||
/// to balance the schedule.
|
||||
class ConvergingVLIWScheduler : public MachineSchedStrategy {
|
||||
|
||||
/// Store the state used by ConvergingVLIWScheduler heuristics, required for the
|
||||
/// lifetime of one invocation of pickNode().
|
||||
/// Store the state used by ConvergingVLIWScheduler heuristics, required
|
||||
/// for the lifetime of one invocation of pickNode().
|
||||
struct SchedCandidate {
|
||||
// The best SUnit candidate.
|
||||
SUnit *SU;
|
||||
|
@ -157,6 +343,7 @@ class ConvergingVLIWScheduler : public MachineSchedStrategy {
|
|||
bool CheckPending;
|
||||
|
||||
ScheduleHazardRecognizer *HazardRec;
|
||||
VLIWResourceModel *ResourceModel;
|
||||
|
||||
unsigned CurrCycle;
|
||||
unsigned IssueCount;
|
||||
|
@ -172,10 +359,14 @@ class ConvergingVLIWScheduler : public MachineSchedStrategy {
|
|||
SchedBoundary(unsigned ID, const Twine &Name):
|
||||
DAG(0), Available(ID, Name+".A"),
|
||||
Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"),
|
||||
CheckPending(false), HazardRec(0), CurrCycle(0), IssueCount(0),
|
||||
CheckPending(false), HazardRec(0), ResourceModel(0),
|
||||
CurrCycle(0), IssueCount(0),
|
||||
MinReadyCycle(UINT_MAX), MaxMinLatency(0) {}
|
||||
|
||||
~SchedBoundary() { delete HazardRec; }
|
||||
~SchedBoundary() {
|
||||
delete ResourceModel;
|
||||
delete HazardRec;
|
||||
}
|
||||
|
||||
bool isTop() const {
|
||||
return Available.getID() == ConvergingVLIWScheduler::TopQID;
|
||||
|
@ -240,183 +431,6 @@ protected:
|
|||
#endif
|
||||
};
|
||||
|
||||
class VLIWResourceModel {
|
||||
/// ResourcesModel - Represents VLIW state.
|
||||
/// Not limited to VLIW targets per say, but assumes
|
||||
/// definition of DFA by a target.
|
||||
DFAPacketizer *ResourcesModel;
|
||||
|
||||
const InstrItineraryData *InstrItins;
|
||||
|
||||
/// Local packet/bundle model. Purely
|
||||
/// internal to the MI schedulre at the time.
|
||||
std::vector<SUnit*> Packet;
|
||||
|
||||
/// Total packets created.
|
||||
unsigned TotalPackets;
|
||||
|
||||
public:
|
||||
VLIWResourceModel(MachineSchedContext *C, const InstrItineraryData *IID) :
|
||||
InstrItins(IID), TotalPackets(0) {
|
||||
const TargetMachine &TM = C->MF->getTarget();
|
||||
ResourcesModel = TM.getInstrInfo()->CreateTargetScheduleState(&TM,NULL);
|
||||
|
||||
// This hard requirement could be relaxed, but for now do not let it proceed.
|
||||
assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
|
||||
|
||||
Packet.resize(InstrItins->SchedModel->IssueWidth);
|
||||
Packet.clear();
|
||||
ResourcesModel->clearResources();
|
||||
}
|
||||
|
||||
~VLIWResourceModel() {
|
||||
delete ResourcesModel;
|
||||
}
|
||||
|
||||
void resetPacketState() {
|
||||
Packet.clear();
|
||||
}
|
||||
|
||||
void resetDFA() {
|
||||
ResourcesModel->clearResources();
|
||||
}
|
||||
|
||||
bool isResourceAvailable(SUnit *SU);
|
||||
void reserveResources(SUnit *SU);
|
||||
unsigned getTotalPackets() const { return TotalPackets; }
|
||||
};
|
||||
|
||||
class VLIWMachineScheduler : public ScheduleDAGInstrs {
|
||||
/// AA - AliasAnalysis for making memory reference queries.
|
||||
AliasAnalysis *AA;
|
||||
|
||||
RegisterClassInfo *RegClassInfo;
|
||||
MachineSchedStrategy *SchedImpl;
|
||||
|
||||
/// state separatly for top/bottom sectioins.
|
||||
VLIWResourceModel *TopResourceModel;
|
||||
VLIWResourceModel *BotResourceModel;
|
||||
|
||||
MachineBasicBlock::iterator LiveRegionEnd;
|
||||
|
||||
/// Register pressure in this region computed by buildSchedGraph.
|
||||
IntervalPressure RegPressure;
|
||||
RegPressureTracker RPTracker;
|
||||
|
||||
/// List of pressure sets that exceed the target's pressure limit before
|
||||
/// scheduling, listed in increasing set ID order. Each pressure set is paired
|
||||
/// with its max pressure in the currently scheduled regions.
|
||||
std::vector<PressureElement> RegionCriticalPSets;
|
||||
|
||||
/// The top of the unscheduled zone.
|
||||
MachineBasicBlock::iterator CurrentTop;
|
||||
IntervalPressure TopPressure;
|
||||
RegPressureTracker TopRPTracker;
|
||||
|
||||
/// The bottom of the unscheduled zone.
|
||||
MachineBasicBlock::iterator CurrentBottom;
|
||||
IntervalPressure BotPressure;
|
||||
RegPressureTracker BotRPTracker;
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// The number of instructions scheduled so far. Used to cut off the
|
||||
/// scheduler at the point determined by misched-cutoff.
|
||||
unsigned NumInstrsScheduled;
|
||||
#endif
|
||||
|
||||
/// Total packets in the region.
|
||||
unsigned TotalPackets;
|
||||
|
||||
const MachineLoopInfo *MLI;
|
||||
public:
|
||||
VLIWMachineScheduler(MachineSchedContext *C, MachineSchedStrategy *S):
|
||||
ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
|
||||
AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S),
|
||||
RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure),
|
||||
CurrentBottom(), BotRPTracker(BotPressure), MLI(C->MLI) {
|
||||
|
||||
TopResourceModel = new VLIWResourceModel(C, InstrItins);
|
||||
BotResourceModel = new VLIWResourceModel(C, InstrItins);
|
||||
|
||||
#ifndef NDEBUG
|
||||
NumInstrsScheduled = 0;
|
||||
#endif
|
||||
TotalPackets = 0;
|
||||
}
|
||||
|
||||
virtual ~VLIWMachineScheduler() {
|
||||
delete SchedImpl;
|
||||
delete TopResourceModel;
|
||||
delete BotResourceModel;
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator top() const { return CurrentTop; }
|
||||
MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
|
||||
|
||||
/// Implement the ScheduleDAGInstrs interface for handling the next scheduling
|
||||
/// region. This covers all instructions in a block, while schedule() may only
|
||||
/// cover a subset.
|
||||
void enterRegion(MachineBasicBlock *bb,
|
||||
MachineBasicBlock::iterator begin,
|
||||
MachineBasicBlock::iterator end,
|
||||
unsigned endcount);
|
||||
|
||||
/// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's
|
||||
/// time to do some work.
|
||||
void schedule();
|
||||
|
||||
unsigned CurCycle;
|
||||
|
||||
/// Get current register pressure for the top scheduled instructions.
|
||||
const IntervalPressure &getTopPressure() const { return TopPressure; }
|
||||
const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
|
||||
|
||||
/// Get current register pressure for the bottom scheduled instructions.
|
||||
const IntervalPressure &getBotPressure() const { return BotPressure; }
|
||||
const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
|
||||
|
||||
/// Get register pressure for the entire scheduling region before scheduling.
|
||||
const IntervalPressure &getRegPressure() const { return RegPressure; }
|
||||
|
||||
const std::vector<PressureElement> &getRegionCriticalPSets() const {
|
||||
return RegionCriticalPSets;
|
||||
}
|
||||
|
||||
VLIWResourceModel *getTopResourceModel() { return TopResourceModel; }
|
||||
VLIWResourceModel *getBotResourceModel() { return BotResourceModel; }
|
||||
|
||||
/// getIssueWidth - Return the max instructions per scheduling group.
|
||||
unsigned getIssueWidth() const {
|
||||
return (InstrItins && InstrItins->SchedModel)
|
||||
? InstrItins->SchedModel->IssueWidth : 1;
|
||||
}
|
||||
|
||||
/// getNumMicroOps - Return the number of issue slots required for this MI.
|
||||
unsigned getNumMicroOps(MachineInstr *MI) const {
|
||||
if (!InstrItins) return 1;
|
||||
int UOps = InstrItins->getNumMicroOps(MI->getDesc().getSchedClass());
|
||||
return (UOps >= 0) ? UOps : TII->getNumMicroOps(InstrItins, MI);
|
||||
}
|
||||
|
||||
private:
|
||||
void scheduleNodeTopDown(SUnit *SU);
|
||||
void listScheduleTopDown();
|
||||
|
||||
void initRegPressure();
|
||||
void updateScheduledPressure(std::vector<unsigned> NewMaxPressure);
|
||||
|
||||
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
|
||||
bool checkSchedLimit();
|
||||
|
||||
void releaseRoots();
|
||||
|
||||
void releaseSucc(SUnit *SU, SDep *SuccEdge);
|
||||
void releaseSuccessors(SUnit *SU);
|
||||
void releasePred(SUnit *SU, SDep *PredEdge);
|
||||
void releasePredecessors(SUnit *SU);
|
||||
|
||||
void placeDebugValues();
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue