@@ -270,6 +270,7 @@ void AIEPostRASchedStrategy::initializeBotScoreBoard(ScoreboardTrust Trust) {
270270 assert (!doMBBSchedRegionsTopDown ());
271271 AIEHazardRecognizer *BotHazardRec = getAIEHazardRecognizer (Bot);
272272 const int Depth = BotHazardRec->getMaxLookAhead ();
273+ assert (unsigned (Depth) >= BotHazardRec->getPipelineDepth ());
273274
274275 // / These lambdas are an abstraction of the scoreboard manipulations,
275276 // / hiding the details of the implementation. In particular, we need to
@@ -479,27 +480,82 @@ SUnit *AIEPostRASchedStrategy::pickNodeAndCycle(
479480}
480481
481482int AIEPostRASchedStrategy::getMaxDeltaCycles (const SchedBoundary &Zone) const {
482- assert (!Zone. isTop ());
483- if (Zone.getCurrCycle () >= RegionBottomUpCycles - 1 )
483+ // Top-down scheduling does not support DeltaCycles
484+ if (Zone.isTop () || Zone. getCurrCycle () >= RegionBottomUpCycles - 1 )
484485 return 0 ;
485486 return std::min ({int (RegionBottomUpCycles - 1 - Zone.getCurrCycle ()),
486487 int (getAIEHazardRecognizer (Zone)->getMaxLookAhead ()),
487488 BottomUpDelta.getValue ()});
488489}
489490
491+ // / Returns the number of emitted instructions in the Top or Bot zone.
492+ unsigned getNumEmittedInstrs (ScheduleDAGMI *DAG, bool IsTop) {
493+ if (IsTop)
494+ return DAG->top ().isValid () ? std::distance (DAG->begin (), DAG->top ()) : 0 ;
495+ return DAG->bottom ().isValid () ? std::distance (DAG->bottom (), DAG->end ()) : 0 ;
496+ }
497+
498+ SUnit *AIEPostRASchedStrategy::getNextUnscheduledFixedInstr (
499+ const SchedBoundary &Zone) const {
500+ if (Zone.isTop ())
501+ return nullptr ;
502+ const Region &Reg = InterBlock.getBlockState (CurMBB).getCurrentRegion ();
503+ const unsigned NumEmitted = getNumEmittedInstrs (DAG, /* IsTop=*/ false );
504+
505+ // If the zone still has unscheduled fixed instructions, the next one to pick
506+ // is (DAG->bottom() - 1) for bottom-up, or DAG->top() for top-down.
507+ if (NumEmitted < Reg.getBotFixedBundles ().size ()) {
508+ MachineInstr &NextMI =
509+ *std::prev (DAG->bottom ().isValid () ? DAG->bottom () : DAG->end ());
510+ SUnit *NextSU = DAG->getSUnit (&NextMI);
511+ assert (NextSU);
512+ assert (NextSU->BotReadyCycle == NextSU->getHeight () &&
513+ " Fixed instruction won't be placed at the correct cycle" );
514+ assert (Zone.getCurrCycle () <= NextSU->BotReadyCycle );
515+ return NextSU;
516+ }
517+ return nullptr ;
518+ }
519+
520+ bool AIEPostRASchedStrategy::isFixedSU (const SUnit &SU, bool IsTop) const {
521+ if (IsTop) {
522+ return FirstTopFixedSU && SU.NodeNum >= *FirstTopFixedSU &&
523+ SU.NodeNum < FirstBotFixedSU.value_or (DAG->SUnits .size ());
524+ }
525+ return FirstBotFixedSU && SU.NodeNum >= *FirstBotFixedSU &&
526+ SU.NodeNum <= LastBotFixedSU.value ();
527+ }
528+
529+ bool AIEPostRASchedStrategy::isFreeSU (const SUnit &SU) const {
530+ const unsigned NumUpperBound = DAG->SUnits .size ();
531+ return SU.NodeNum < FirstTopFixedSU.value_or (NumUpperBound) &&
532+ SU.NodeNum < FirstBotFixedSU.value_or (NumUpperBound);
533+ }
534+
490535bool AIEPostRASchedStrategy::isAvailableNode (SUnit &SU, SchedBoundary &Zone,
491536 bool /* VerifyReadyCycle*/ ) {
537+ // Note we use signed integers to avoid wrap-around behavior.
538+ const int MinDelta = -getMaxDeltaCycles (Zone);
539+ const int ReadyCycle = std::max (Zone.getCurrCycle (), SU.BotReadyCycle );
540+ const int CurrCycle = Zone.getCurrCycle ();
541+
542+ // If the Zone has remaining fixed instructions, only one SU is available.
543+ if (SUnit *FixedSU = getNextUnscheduledFixedInstr (Zone)) {
544+ assert (!Zone.isTop () && " Fixed instructions only expected in Bot zone" );
545+ const int DeltaCycles = CurrCycle - ReadyCycle;
546+ return FixedSU == &SU && DeltaCycles >= MinDelta;
547+ }
548+
549+ // If SU is a fixed instruction in the other zone, it isn't available
550+ if (isFixedSU (SU, !Zone.isTop ()))
551+ return false ;
552+
492553 // Whether or not the zone is Top or Bot, verify if SU is ready to be
493554 // scheduled in terms of cycle.
494555 if (Zone.isTop ())
495556 return MachineSchedStrategy::isAvailableNode (SU, Zone,
496557 /* VerifyReadyCycle=*/ true );
497558
498- // Note we use signed integers to avoid wrap-around behavior.
499- const int MinDelta = -getMaxDeltaCycles (Zone);
500- const int ReadyCycle = std::max (Zone.getCurrCycle (), SU.BotReadyCycle );
501- const int CurrCycle = Zone.getCurrCycle ();
502-
503559 for (int DeltaCycles = CurrCycle - ReadyCycle; DeltaCycles >= MinDelta;
504560 --DeltaCycles) {
505561 // ReadyCycle is always greater or equal to the current cycle,
@@ -542,6 +598,10 @@ void AIEPostRASchedStrategy::enterMBB(MachineBasicBlock *MBB) {
542598 // from a block is the bottom one. We reset this when leaving any
543599 // region
544600 IsBottomRegion = true ;
601+
602+ // The block may have a timed region, append its instructions.
603+ auto &BS = InterBlock.getBlockState (MBB);
604+ InterBlock.emitInterBlockBottom (BS);
545605}
546606
547607void AIEPostRASchedStrategy::commitBlockSchedule (MachineBasicBlock *BB) {
@@ -551,10 +611,11 @@ void AIEPostRASchedStrategy::commitBlockSchedule(MachineBasicBlock *BB) {
551611 // scheduling region.
552612 assert (BS.getRegions ().empty () ||
553613 0 == BS.getTop ().getTopFixedBundles ().size ());
554- assert (BS.getRegions () .empty () ||
555- 0 == BS.getBottom ().getBotFixedBundles ().size ());
614+ assert (BS.BottomInsert .empty () ||
615+ BS. BottomInsert . size () == BS.getBottom ().getBotFixedBundles ().size ());
556616
557617 // Safety margin, swp epilogue
618+ // Note that the prologue is handled in a different way. See enterMBB.
558619 InterBlock.emitInterBlockTop (BS);
559620
560621 if (BS.isPipelined ()) {
@@ -582,8 +643,6 @@ void AIEPostRASchedStrategy::commitBlockSchedule(MachineBasicBlock *BB) {
582643 AIEHazardRecognizer::applyBundles (Region.Bundles , BS.TheBlock );
583644 }
584645 }
585- // swp prologue
586- InterBlock.emitInterBlockBottom (BS);
587646}
588647
589648void AIEPostRASchedStrategy::leaveMBB () {
@@ -634,6 +693,9 @@ void AIEPostRASchedStrategy::leaveRegion(const SUnit &ExitSU) {
634693 RegionBegin = nullptr ;
635694 RegionEnd = nullptr ;
636695 IsBottomRegion = false ;
696+ FirstTopFixedSU = {};
697+ FirstBotFixedSU = {};
698+ LastBotFixedSU = {};
637699 BS.advanceRegion ();
638700 DEBUG_BLOCKS (dbgs () << " << leaveRegion\n " );
639701}
@@ -758,6 +820,11 @@ bool AIEPostRASchedStrategy::tryCandidate(SchedCandidate &Cand,
758820 return true ;
759821 }
760822
823+ SchedBoundary &Zone = getSchedZone ();
824+ assert (!getNextUnscheduledFixedInstr (Zone) &&
825+ " More than one available SUnit while not all fixed instructions have "
826+ " been emitted." );
827+
761828 // Instructions with delay slots are critical and should be scheduled
762829 // as soon as they are ready.
763830 if (TryCand.SU ->getInstr ()->hasDelaySlot ()) {
@@ -770,8 +837,6 @@ bool AIEPostRASchedStrategy::tryCandidate(SchedCandidate &Cand,
770837 return false ;
771838 }
772839
773- SchedBoundary &Zone = getSchedZone ();
774-
775840 // Avoid serializing long latency dependence chains.
776841 if (Cand.Policy .ReduceLatency && Zone.isTop () &&
777842 tryLatency (TryCand, Cand, Zone)) {
@@ -1237,6 +1302,11 @@ void llvm::AIEPostRASchedStrategy::buildGraph(ScheduleDAGMI &DAG, AAResults *AA,
12371302 PressureDiffs *PDiffs,
12381303 LiveIntervals *LIS,
12391304 bool TrackLaneMasks) {
1305+
1306+ // Let's save the DAG already instead of waiting for initialize().
1307+ // Some DAG mutators might require a DAG to be set.
1308+ this ->DAG = &DAG;
1309+
12401310 // / We are called after enterRegion, which will have recorded the semantic
12411311 // / order. We can't use the basic block order, since this may have changed
12421312 // / in earlier iterations of scheduling
@@ -1267,6 +1337,28 @@ void llvm::AIEPostRASchedStrategy::buildGraph(ScheduleDAGMI &DAG, AAResults *AA,
12671337 static_cast <AIEScheduleDAGMI &>(DAG).recordDbgInstrs (Region);
12681338}
12691339
1340+ SUnit &AIEPostRASchedStrategy::addFixedSUnit (MachineInstr &MI, bool IsTop) {
1341+ DEBUG_BLOCKS (dbgs () << " Adding Fixed MI: " << MI);
1342+ DEBUG_BLOCKS (dbgs () << " DAG size=" << DAG->SUnits .size ()
1343+ << " capacity=" << DAG->SUnits .capacity () << " \n " );
1344+ assert (!(IsTop && FirstBotFixedSU) && " Top-fixed SUnits must be added first" );
1345+ assert (DAG->SUnits .size () < DAG->SUnits .capacity () &&
1346+ " SUnits need to be re-allocated." );
1347+ unsigned SUNum = DAG->initSUnit (MI).value ();
1348+ SUnit &SU = DAG->SUnits [SUNum];
1349+
1350+ if (IsTop) {
1351+ if (!FirstTopFixedSU)
1352+ FirstTopFixedSU = SUNum;
1353+ } else {
1354+ if (!FirstBotFixedSU)
1355+ FirstBotFixedSU = SUNum;
1356+ LastBotFixedSU = SUNum;
1357+ }
1358+
1359+ return SU;
1360+ }
1361+
12701362bool AIEScheduleDAGMI::mayAlias (SUnit *SUa, SUnit *SUb, bool UseTBAA) {
12711363 BlockState &BS = getSchedImpl ()->getInterBlock ().getBlockState (getBB ());
12721364 if (BS.FixPoint .Stage == SchedulingStage::Pipelining) {
0 commit comments