52 #define DEBUG_TYPE "misched"
72 const SUnit &Inst1,
const SUnit &Inst2)
const {
83 SUnit* LastSequentialCall =
nullptr;
84 unsigned VRegHoldingRet = 0;
86 SUnit* LastUseOfRet =
nullptr;
92 for (
unsigned su = 0, e = DAG->
SUnits.size(); su != e; ++su) {
94 if (DAG->
SUnits[su].getInstr()->isCall())
95 LastSequentialCall = &DAG->
SUnits[su];
97 else if (DAG->
SUnits[su].getInstr()->isCompare() && LastSequentialCall)
101 shouldTFRICallBind(HII, DAG->
SUnits[su], DAG->
SUnits[su+1]))
121 LastUseOfRet =
nullptr;
124 LastUseOfRet = &DAG->
SUnits[su];
153 case TargetOpcode::EXTRACT_SUBREG:
154 case TargetOpcode::INSERT_SUBREG:
155 case TargetOpcode::SUBREG_TO_REG:
156 case TargetOpcode::REG_SEQUENCE:
157 case TargetOpcode::IMPLICIT_DEF:
158 case TargetOpcode::COPY:
168 for (
unsigned i = 0, e = Packet.size();
i != e; ++
i) {
169 if (Packet[
i]->Succs.size() == 0)
173 if (QII.mayBeCurLoad(*Packet[
i]->getInstr()))
177 E = Packet[
i]->Succs.end();
I !=
E; ++
I) {
183 if (
I->getSUnit() == SU)
192 bool startNewCycle =
false;
208 startNewCycle =
true;
215 case TargetOpcode::EXTRACT_SUBREG:
216 case TargetOpcode::INSERT_SUBREG:
217 case TargetOpcode::SUBREG_TO_REG:
218 case TargetOpcode::REG_SEQUENCE:
219 case TargetOpcode::IMPLICIT_DEF:
221 case TargetOpcode::CFI_INSTRUCTION:
223 case TargetOpcode::COPY:
227 Packet.push_back(SU);
230 DEBUG(
dbgs() <<
"Packet[" << TotalPackets <<
"]:\n");
231 for (
unsigned i = 0, e = Packet.size();
i != e; ++
i) {
245 startNewCycle =
true;
248 return startNewCycle;
256 <<
"********** MI Converging Scheduling VLIW BB#" <<
BB->
getNumber()
270 DEBUG(
unsigned maxH = 0;
271 for (
unsigned su = 0, e =
SUnits.size(); su != e; ++su)
272 if (
SUnits[su].getHeight() > maxH)
273 maxH =
SUnits[su].getHeight();
274 dbgs() <<
"Max Height " << maxH <<
"\n";);
275 DEBUG(
unsigned maxD = 0;
276 for (
unsigned su = 0, e =
SUnits.size(); su != e; ++su)
277 if (
SUnits[su].getDepth() > maxD)
278 maxD =
SUnits[su].getDepth();
279 dbgs() <<
"Max Depth " << maxD <<
"\n";);
280 DEBUG(
for (
unsigned su = 0, e =
SUnits.size(); su != e; ++su)
281 SUnits[su].dumpAll(
this));
285 bool IsTopNode =
false;
287 DEBUG(
dbgs() <<
"** VLIWMachineScheduler::schedule picking next node\n");
306 unsigned BBNum =
begin()->getParent()->getNumber();
307 dbgs() <<
"*** Final schedule for BB#" << BBNum <<
" ***\n";
317 Top.init(DAG, SchedModel);
318 Bot.init(DAG, SchedModel);
325 delete Top.HazardRec;
326 delete Bot.HazardRec;
330 delete Top.ResourceModel;
331 delete Bot.ResourceModel;
336 "-misched-topdown incompatible with -misched-bottomup");
338 DAG->addMutation(make_unique<HexagonSubtarget::HexagonDAGMutation>());
339 DAG->addMutation(make_unique<HexagonCallMutation>());
350 Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
366 unsigned SuccReadyCycle =
I->getSUnit()->BotReadyCycle;
367 unsigned MinLatency =
I->getLatency();
369 Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
390 bool ConvergingVLIWScheduler::VLIWSchedBoundary::checkHazard(
SUnit *SU) {
391 if (HazardRec->isEnabled())
394 unsigned uops = SchedModel->getNumMicroOps(SU->
getInstr());
395 if (IssueCount + uops > SchedModel->getIssueWidth())
401 void ConvergingVLIWScheduler::VLIWSchedBoundary::releaseNode(
SUnit *SU,
402 unsigned ReadyCycle) {
403 if (ReadyCycle < MinReadyCycle)
404 MinReadyCycle = ReadyCycle;
408 if (ReadyCycle > CurrCycle || checkHazard(SU))
416 void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpCycle() {
417 unsigned Width = SchedModel->getIssueWidth();
418 IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width;
420 assert(MinReadyCycle < UINT_MAX &&
"MinReadyCycle uninitialized");
421 unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle);
423 if (!HazardRec->isEnabled()) {
425 CurrCycle = NextCycle;
428 for (; CurrCycle != NextCycle; ++CurrCycle) {
430 HazardRec->AdvanceCycle();
432 HazardRec->RecedeCycle();
437 DEBUG(
dbgs() <<
"*** Next cycle " << Available.getName() <<
" cycle "
438 << CurrCycle <<
'\n');
442 void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpNode(
SUnit *SU) {
443 bool startNewCycle =
false;
446 if (HazardRec->isEnabled()) {
447 if (!isTop() && SU->
isCall) {
452 HazardRec->EmitInstruction(SU);
456 startNewCycle = ResourceModel->reserveResources(SU);
460 IssueCount += SchedModel->getNumMicroOps(SU->
getInstr());
462 DEBUG(
dbgs() <<
"*** Max instrs at cycle " << CurrCycle <<
'\n');
466 DEBUG(
dbgs() <<
"*** IssueCount " << IssueCount
467 <<
" at cycle " << CurrCycle <<
'\n');
472 void ConvergingVLIWScheduler::VLIWSchedBoundary::releasePending() {
474 if (Available.empty())
475 MinReadyCycle = UINT_MAX;
479 for (
unsigned i = 0, e = Pending.size();
i != e; ++
i) {
480 SUnit *SU = *(Pending.begin()+
i);
483 if (ReadyCycle < MinReadyCycle)
484 MinReadyCycle = ReadyCycle;
486 if (ReadyCycle > CurrCycle)
493 Pending.remove(Pending.begin()+
i);
496 CheckPending =
false;
500 void ConvergingVLIWScheduler::VLIWSchedBoundary::removeReady(
SUnit *SU) {
501 if (Available.isInQueue(SU))
502 Available.remove(Available.find(SU));
504 assert(Pending.isInQueue(SU) &&
"bad ready count");
505 Pending.remove(Pending.find(SU));
512 SUnit *ConvergingVLIWScheduler::VLIWSchedBoundary::pickOnlyChoice() {
516 for (
unsigned i = 0; Available.empty(); ++
i) {
517 assert(
i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
518 "permanent hazard"); (void)
i;
519 ResourceModel->reserveResources(
nullptr);
523 if (Available.size() == 1)
524 return *Available.begin();
537 dbgs() <<
"cost(" << Cost <<
")\t";
551 DAG->getRegionCriticalPSets(),
552 DAG->getRegPressure().MaxSetPressure);
553 std::stringstream dbgstr;
554 dbgstr <<
"SU(" << std::setw(3) << (*I)->NodeNum <<
")";
555 dbgs() << dbgstr.str();
558 (*I)->getInstr()->dump();
567 SUnit *OnlyAvailablePred =
nullptr;
570 SUnit &Pred = *
I->getSUnit();
574 if (OnlyAvailablePred && OnlyAvailablePred != &Pred)
576 OnlyAvailablePred = &Pred;
579 return OnlyAvailablePred;
585 SUnit *OnlyAvailableSucc =
nullptr;
588 SUnit &Succ = *
I->getSUnit();
592 if (OnlyAvailableSucc && OnlyAvailableSucc != &Succ)
594 OnlyAvailableSucc = &Succ;
597 return OnlyAvailableSucc;
611 SchedCandidate &Candidate,
635 std::stringstream dbgstr;
636 dbgstr <<
"h" << std::setw(3) << SU->
getHeight() <<
"|";
637 dbgs() << dbgstr.str();
642 if (Top.ResourceModel->isResourceAvailable(SU)) {
652 std::stringstream dbgstr;
653 dbgstr <<
"d" << std::setw(3) << SU->
getDepth() <<
"|";
654 dbgs() << dbgstr.str();
659 if (Bot.ResourceModel->isResourceAvailable(SU)) {
667 unsigned NumNodesBlocking = 0;
682 ResCount += (NumNodesBlocking *
ScaleTwo);
685 std::stringstream dbgstr;
686 dbgstr <<
"blk " << std::setw(2) << NumNodesBlocking <<
")|";
687 dbgs() << dbgstr.str();
711 if (Q.
getID() ==
TopQID && Top.ResourceModel->isResourceAvailable(SU)) {
715 Bot.ResourceModel->isResourceAvailable(SU)) {
727 Top.ResourceModel->isInPacket(PI.
getSUnit())) {
736 Bot.ResourceModel->isInPacket(SI.
getSUnit())) {
745 if (QII.isV60VectorInstruction(Instr)) {
748 for (
auto J : Top.ResourceModel->OldPacket)
749 if (QII.producesStall(*J->getInstr(), Instr))
752 for (
auto J : Bot.ResourceModel->OldPacket)
753 if (QII.producesStall(Instr, *J->getInstr()))
765 for (
const auto &PI : SU->
Preds) {
766 if (PI.getLatency() > 0 &&
767 Top.ResourceModel->isInPacket(PI.getSUnit())) {
773 for (
const auto &
SI : SU->
Succs) {
774 if (
SI.getLatency() > 0 &&
775 Bot.ResourceModel->isInPacket(
SI.getSUnit())) {
784 std::stringstream dbgstr;
785 dbgstr <<
"Total " << std::setw(4) << ResCount <<
")";
786 dbgs() << dbgstr.str();
799 SchedCandidate &Candidate) {
808 CandResult FoundCandidate = NoCand;
811 TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
812 DAG->getRegionCriticalPSets(),
813 DAG->getRegPressure().MaxSetPressure);
821 Candidate.RPDelta = RPDelta;
822 Candidate.SCost = CurrentCost;
823 FoundCandidate = NodeOrder;
828 if (CurrentCost > Candidate.SCost) {
831 Candidate.RPDelta = RPDelta;
832 Candidate.SCost = CurrentCost;
833 FoundCandidate = BestCost;
846 unsigned InstrLatency = QII.getInstrTimingClassLatency(InstrItins, *MI);
847 unsigned CandLatency = QII.getInstrTimingClassLatency(InstrItins, *CandI);
849 << CandLatency <<
" Instr:" << InstrLatency <<
"\n"
850 << *MI << *CandI <<
"\n");
851 if (Q.
getID() ==
TopQID && CurrentCost == Candidate.SCost) {
854 Candidate.RPDelta = RPDelta;
855 Candidate.SCost = CurrentCost;
856 FoundCandidate = BestCost;
857 DEBUG(
dbgs() <<
"Used top shorter tie breaker\n");
861 Candidate.RPDelta = RPDelta;
862 Candidate.SCost = CurrentCost;
863 FoundCandidate = BestCost;
864 DEBUG(
dbgs() <<
"Used top longer tie breaker\n");
867 }
else if (Q.
getID() ==
BotQID && CurrentCost == Candidate.SCost) {
870 Candidate.RPDelta = RPDelta;
871 Candidate.SCost = CurrentCost;
872 FoundCandidate = BestCost;
873 DEBUG(
dbgs() <<
"Used Bot shorter tie breaker\n");
877 Candidate.RPDelta = RPDelta;
878 Candidate.SCost = CurrentCost;
879 FoundCandidate = BestCost;
880 DEBUG(
dbgs() <<
"Used Bot longer tie breaker\n");
886 if (CurrentCost == Candidate.SCost) {
888 (*I)->Succs.size() > Candidate.SU->Succs.size()) ||
890 (*I)->Preds.size() < Candidate.SU->Preds.size())) {
893 Candidate.RPDelta = RPDelta;
894 Candidate.SCost = CurrentCost;
895 FoundCandidate = BestCost;
902 if (FoundCandidate == NoCand)
905 return FoundCandidate;
912 if (
SUnit *SU = Bot.pickOnlyChoice()) {
917 if (
SUnit *SU = Top.pickOnlyChoice()) {
922 SchedCandidate BotCand;
925 DAG->getBotRPTracker(), BotCand);
926 assert(BotResult != NoCand &&
"failed to find the first candidate");
935 if (BotResult == SingleExcess || BotResult == SingleCritical) {
936 DEBUG(
dbgs() <<
"Prefered Bottom Node\n");
941 SchedCandidate TopCand;
943 DAG->getTopRPTracker(), TopCand);
944 assert(TopResult != NoCand &&
"failed to find the first candidate");
946 if (TopResult == SingleExcess || TopResult == SingleCritical) {
953 if (BotResult == SingleMax) {
954 DEBUG(
dbgs() <<
"Prefered Bottom Node SingleMax\n");
958 if (TopResult == SingleMax) {
959 DEBUG(
dbgs() <<
"Prefered Top Node SingleMax\n");
963 if (TopCand.SCost > BotCand.SCost) {
964 DEBUG(
dbgs() <<
"Prefered Top Node Cost\n");
969 DEBUG(
dbgs() <<
"Prefered Bottom in Node order\n");
976 if (DAG->top() == DAG->bottom()) {
977 assert(Top.Available.empty() && Top.Pending.empty() &&
978 Bot.Available.empty() && Bot.Pending.empty() &&
"ReadyQ garbage");
983 SU = Top.pickOnlyChoice();
985 SchedCandidate TopCand;
986 CandResult TopResult =
988 assert(TopResult != NoCand &&
"failed to find the first candidate");
994 SU = Bot.pickOnlyChoice();
996 SchedCandidate BotCand;
997 CandResult BotResult =
999 assert(BotResult != NoCand &&
"failed to find the first candidate");
1008 Top.removeReady(SU);
1010 Bot.removeReady(SU);
1012 DEBUG(
dbgs() <<
"*** " << (IsTopNode ?
"Top" :
"Bottom")
1013 <<
" Scheduling Instruction in cycle "
1014 << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) <<
'\n';
bool canReserveResources(const llvm::MCInstrDesc *MID)
virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const
Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void schedule() override
Schedule - This is called back from ScheduleDAGInstrs::Run() when it's time to do some work...
Extend the standard ScheduleDAGMI to provide more context and override the top-level schedule() drive...
static cl::opt< unsigned > SchedDebugVerboseLevel("misched-verbose-level", cl::Hidden, cl::ZeroOrMore, cl::init(1))
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
void readyQueueVerboseDump(const RegPressureTracker &RPTracker, SchedCandidate &Candidate, ReadyQueue &Q)
int SchedulingCost(ReadyQueue &Q, SUnit *SU, SchedCandidate &Candidate, RegPressureDelta &Delta, bool verbose)
Single point to compute overall scheduling cost.
MachineBasicBlock::iterator CurrentTop
The top of the unscheduled zone.
bool isPseudo(QueryType Type=IgnoreBundle) const
Return true if this is a pseudo instruction that doesn't correspond to a real machine instruction...
MachineInstr * getInstr() const
getInstr - Return the representative MachineInstr for this SUnit.
CandResult pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker, SchedCandidate &Candidate)
Pick the best candidate from the top queue.
static cl::opt< bool > TopUseShorterTie("top-use-shorter-tie", cl::Hidden, cl::ZeroOrMore, cl::init(false))
bool readsVirtualRegister(unsigned Reg) const
Return true if the MachineInstr reads the specified virtual register.
MachineBasicBlock::iterator begin() const
begin - Return an iterator to the top of the current scheduling region.
void savePacket()
Save the last formed packet.
bool isInstr() const
isInstr - Return true if this SUnit refers to a machine instruction as opposed to an SDNode...
Mutate the DAG as a postpass after normal DAG building.
static SUnit * getSingleUnscheduledPred(SUnit *SU)
getSingleUnscheduledPred - If there is exactly one unscheduled predecessor of SU, return it...
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
bool isAssignedRegDep() const
isAssignedRegDep - Test if this is a Data dependence that is associated with a register.
std::unique_ptr< MachineSchedStrategy > SchedImpl
void updateQueues(SUnit *SU, bool IsTopNode)
Update scheduler DAG and queues after scheduling an instruction.
SmallVector< SDep, 4 > Preds
StringRef getName() const
Return a constant reference to the value's name.
const TargetSchedModel * getSchedModel() const
Get the machine model for instruction scheduling.
unsigned getHeight() const
getHeight - Return the height of this node, which is the length of the maximum path down to any node ...
SUnit * pickNodeBidrectional(bool &IsTopNode)
Pick the best candidate node from either the top or bottom queue.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static const unsigned ScaleTwo
const HexagonInstrInfo * TII
virtual const char * getRegPressureSetName(unsigned Idx) const =0
Get the name of this register unit pressure set.
static cl::opt< bool > IgnoreBBRegPressure("ignore-bb-reg-pressure", cl::Hidden, cl::ZeroOrMore, cl::init(false))
SUnit * pickNode(bool &IsTopNode) override
Pick the best node to balance the schedule. Implements MachineSchedStrategy.
INLINEASM - Represents an inline asm block.
static SUnit * getSingleUnscheduledSucc(SUnit *SU)
getSingleUnscheduledSucc - If there is exactly one unscheduled successor of SU, return it...
static cl::opt< bool > BotUseShorterTie("bot-use-shorter-tie", cl::Hidden, cl::ZeroOrMore, cl::init(false))
void scheduleMI(SUnit *SU, bool IsTopNode)
Move an instruction and update register pressure.
void releaseTopNode(SUnit *SU) override
When all predecessor dependencies have been resolved, free this node for top-down scheduling...
void buildDAGWithRegPressure()
Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking enabled.
Itinerary data supplied by a subtarget to be used by a target.
void reserveResources(const llvm::MCInstrDesc *MID)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
TargetInstrInfo - Interface to description of machine instruction set.
std::vector< SUnit * >::iterator iterator
SDep - Scheduling dependency.
initializer< Ty > init(const Ty &Val)
void initQueues(ArrayRef< SUnit * > TopRoots, ArrayRef< SUnit * > BotRoots)
Release ExitSU predecessors and setup scheduler queues.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Helpers for implementing custom MachineSchedStrategy classes.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
PressureChange CurrentMax
const InstrItineraryData * getInstrItineraries() const
void dumpSchedule() const
dump the scheduled Sequence.
const MachineOperand & getOperand(unsigned i) const
unsigned getLatency() const
getLatency - Return the latency value for this edge, which roughly means the minimum number of cycles...
Track the current register pressure at some position in the instruction stream, and remember the high...
void findRootsAndBiasEdges(SmallVectorImpl< SUnit * > &TopRoots, SmallVectorImpl< SUnit * > &BotRoots)
bool isResourceAvailable(SUnit *SU)
Check if scheduling of this SU is possible in the current packet.
static cl::opt< bool > SchedPredsCloser("sched-preds-closer", cl::Hidden, cl::ZeroOrMore, cl::init(true))
void apply(Opt *O, const Mod &M, const Mods &...Ms)
static const unsigned FactorOne
bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr fully defines the specified register.
EH_LABEL - Represents a label in mid basic block used to track locations needed for debug and excepti...
An unknown scheduling barrier.
bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI=nullptr) const
Return true if the MachineInstr reads the specified register.
void schedNode(SUnit *SU, bool IsTopNode) override
Update the scheduler's state after scheduling a node.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
const MachineLoopInfo * MLI
void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta, ArrayRef< PressureChange > CriticalPSets, ArrayRef< unsigned > MaxPressureLimit)
Find the pressure set with the most change beyond its pressure limit after traversing this instructio...
void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU, int Cost, PressureChange P=PressureChange())
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or "(null)".
PressureChange CriticalMax
unsigned getDepth() const
getDepth - Return the depth of this node, which is the length of the maximum path up to any node whic...
TargetSubtargetInfo - Generic base class for all target subtargets.
ScheduleDAGInstrs - A ScheduleDAG subclass for scheduling lists of MachineInstrs. ...
Representation of each machine instruction.
const TargetRegisterInfo * TRI
static const unsigned PriorityOne
cl::opt< bool > ForceBottomUp
static cl::opt< bool > SchedRetvalOptimization("sched-retval-optimization", cl::Hidden, cl::ZeroOrMore, cl::init(true))
Capture a change in pressure for a single pressure set.
void placeDebugValues()
Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
bool reserveResources(SUnit *SU)
Keep track of available resources.
static const unsigned PriorityThree
void releaseBottomNode(SUnit *SU) override
When all successor dependencies have been resolved, free this node for bottom-up scheduling.
unsigned getLoopDepth(const MachineBasicBlock *BB) const
Return the loop nesting level of the specified block.
unsigned getReg() const
getReg - Returns the register number.
MachineBasicBlock::iterator CurrentBottom
The bottom of the unscheduled zone.
Store the effects of a change in pressure on things that MI scheduler cares about.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< SUnit * > OldPacket
Save the last formed packet.
virtual const TargetInstrInfo * getInstrInfo() const
static cl::opt< bool > CheckEarlyAvail("check-early-avail", cl::Hidden, cl::ZeroOrMore, cl::init(true))
static const unsigned PriorityTwo
const HexagonInstrInfo * getInstrInfo() const override
SmallVector< SDep, 4 > Succs
unsigned getIssueWidth() const
Maximum number of micro-ops that may be scheduled per cycle.
bool isBottomReady() const
static cl::opt< bool > DisableTCTie("disable-tc-tie", cl::Hidden, cl::ZeroOrMore, cl::init(false))
StringRef getName() const
MachineBasicBlock * BB
State specific to the current scheduling region.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
std::vector< SUnit > SUnits
uint64_t getType(const MachineInstr &MI) const
void dump(const ScheduleDAG *G) const
SUnit - Scheduling unit.
SUnit - Scheduling unit. This is a node in the scheduling DAG.
cl::opt< bool > ForceTopDown
void initialize(ScheduleDAGMI *dag) override
Initialize the strategy after building the DAG for a new region.