@@ -356,27 +356,17 @@ class RegionEndEdges : public ScheduleDAGMutation {
356356class EmitFixedSUnits : public ScheduleDAGMutation {
357357 AAResults *AA;
358358
359- public:
360- EmitFixedSUnits (AAResults *AA) : AA(AA) {}
361-
362- void apply (ScheduleDAGInstrs *DAG) override {
363- AIEPostRASchedStrategy *Scheduler =
364- static_cast <AIEScheduleDAGMI *>(DAG)->getSchedImpl ();
365- auto *TII = static_cast <const AIEBaseInstrInfo *>(DAG->TII );
366- auto *ItinData = DAG->MF .getSubtarget ().getInstrItineraryData ();
367- const TargetRegisterInfo *TRI = DAG->MF .getSubtarget ().getRegisterInfo ();
368- const BlockState &BS =
369- Scheduler->getInterBlock ().getBlockState (DAG->getBB ());
370- const Region &CurRegion = BS.getCurrentRegion ();
371- AIERegMemEventTracker RET{ItinData, TRI, TII, AA};
372-
359+ private:
360+ void createFixedSUDAGNodes (ScheduleDAGInstrs *DAG,
361+ AIEPostRASchedStrategy *Scheduler,
362+ const Region &CurRegion) {
373363 // First, create SUnits for all "fixed" instructions
374364 // Those will be chained from/to the EntrySU/ExitSU to ensure they are
375365 // placed in the correct cycle. The scheduler will enforce that these fixed
376366 // SUnits get placed exactly at their depth (for the Top zone) or height
377367 // (for the Bot zone).
378368 SUnit *Pred = &DAG->EntrySU ;
379- // We itarate over BUNDLEs or standalone instructions.
369+ // We iterate over BUNDLEs or standalone instructions.
380370 for (MachineInstr &MI : CurRegion.top_fixed_instrs ()) {
381371 SUnit &FixedSU = Scheduler->addFixedSUnit (MI, /* IsTop=*/ true );
382372 SDep Dep (Pred, SDep::Artificial);
@@ -394,89 +384,105 @@ class EmitFixedSUnits : public ScheduleDAGMutation {
394384 Succ = &FixedSU;
395385 }
396386 DAG->makeMaps ();
387+ }
388+
389+ void establishSafeFreeSUToPrologueDistances (
390+ ScheduleDAGInstrs *DAG, AIEPostRASchedStrategy *Scheduler,
391+ const TargetRegisterInfo *TRI, const AIEBaseInstrInfo *TII,
392+ const InstrItineraryData *ItinData) {
393+
394+ MachineBasicBlock *LoopSucc = nullptr ;
395+ for (MachineBasicBlock *Succ : DAG->getBB ()->successors ()) {
396+ const BlockState &SuccBS = Scheduler->getInterBlock ().getBlockState (Succ);
397+ if (SuccBS.Kind == BlockType::Loop && SuccBS.isPipelined ()) {
398+ LoopSucc = Succ;
399+ break ;
400+ }
401+ }
402+
403+ if (!LoopSucc)
404+ return ;
405+
406+ const BlockState &LoopBS =
407+ Scheduler->getInterBlock ().getBlockState (LoopSucc);
408+
409+ const BlockState &BS =
410+ Scheduler->getInterBlock ().getBlockState (DAG->getBB ());
411+
412+ const Region &CurRegion = BS.getCurrentRegion ();
397413
398414 ArrayRef<AIE::MachineBundle> BotFixedBundles =
399415 CurRegion.getBotFixedBundles ();
400- ArrayRef<AIE::MachineBundle> TopFixedBundles =
401- CurRegion.getTopFixedBundles ();
402416
403- // Handle bot-fixed instructions (prologue) with backward tracking
404- // Only handle prologues (preheader blocks), not epilogues here
405- if (!BotFixedBundles.empty () && BS.Kind != BlockType::Epilogue) {
406- AIERegMemEventTracker BackwardRET{ItinData, TRI, TII, AA};
407-
408- // Track bot-fixed bundles backward (this sets BotFixedRegionSize)
409- BackwardRET.computeUseDefBackward (BotFixedBundles,
410- /* InSeparateRegion=*/ false );
411-
412- // Find the loop successor - must exist if we have bot-fixed bundles in a
413- // prologue
414- MachineBasicBlock *LoopSucc = nullptr ;
415- for (MachineBasicBlock *Succ : DAG->getBB ()->successors ()) {
416- const BlockState &SuccBS =
417- Scheduler->getInterBlock ().getBlockState (Succ);
418- if (SuccBS.Kind == BlockType::Loop && SuccBS.isPipelined ()) {
419- LoopSucc = Succ;
420- break ;
421- }
422- }
423- assert (LoopSucc &&
424- " Bot-fixed bundles present but no pipelined loop successor found" );
425-
426- const BlockState &LoopBS =
427- Scheduler->getInterBlock ().getBlockState (LoopSucc);
428- ArrayRef<AIE::MachineBundle> LoopTimedBundles = LoopBS.getTop ().Bundles ;
429- BackwardRET.computeUseDefBackward (LoopTimedBundles,
430- /* InSeparateRegion=*/ true );
431-
432- // Create dependencies from free instructions to ExitSU
433- // Side-effect instructions are now handled automatically by
434- // getSafeOperandsDistanceFromEnd()
435- auto IsNonBotFixedSU = [Scheduler](const SUnit &SU) {
436- return !Scheduler->isFixedSU (SU, /* IsTop*/ false );
437- };
417+ ArrayRef<AIE::MachineBundle> LoopTimedBundles = LoopBS.getTop ().Bundles ;
438418
439- for (SUnit &SU : make_filter_range (DAG->SUnits , IsNonBotFixedSU)) {
440- const MachineInstr &MI = *SU.getInstr ();
441- if (const unsigned Latency =
442- BackwardRET.getSafeOperandsDistanceFromBottom (MI)) {
443- LLVM_DEBUG (dbgs ()
444- << " Prologue: SU(" << SU.NodeNum << " ) needs latency "
445- << Latency << " to ExitSU: " << MI);
446- LLVM_DEBUG (dbgs () << " Adding new edge\n " );
447- SDep Dep (&SU, SDep::Artificial);
448- Dep.setLatency (Latency);
449- DAG->ExitSU .addPred (Dep, /* Required=*/ true );
450- }
419+ AIERegMemEventTracker BackwardRET{ItinData, TRI, TII, AA};
420+
421+ // Track bot-fixed bundles backward (this sets BotFixedRegionSize)
422+ BackwardRET.computeUseDefBackward (BotFixedBundles,
423+ /* InSeparateRegion=*/ false );
424+
425+ BackwardRET.computeUseDefBackward (LoopTimedBundles,
426+ /* InSeparateRegion=*/ true );
427+
428+ // Create dependencies from free instructions to ExitSU
429+ // Side-effect instructions are now handled automatically by
430+ // getSafeOperandsDistanceFromEnd()
431+ auto IsNonBotFixedSU = [Scheduler](const SUnit &SU) {
432+ return !Scheduler->isFixedSU (SU, /* IsTop*/ false );
433+ };
434+
435+ for (SUnit &SU : make_filter_range (DAG->SUnits , IsNonBotFixedSU)) {
436+ const MachineInstr &MI = *SU.getInstr ();
437+ if (const unsigned Latency =
438+ BackwardRET.getSafeOperandsDistanceFromBottom (MI)) {
439+ LLVM_DEBUG (dbgs () << " Prologue: SU(" << SU.NodeNum << " ) needs latency "
440+ << Latency << " to ExitSU: " << MI);
441+ LLVM_DEBUG (dbgs () << " Adding new edge\n " );
442+ SDep Dep (&SU, SDep::Artificial);
443+ Dep.setLatency (Latency);
444+ DAG->ExitSU .addPred (Dep, /* Required=*/ true );
451445 }
452446 }
447+ }
448+
449+ void establishSafeFreeSUToEpilogueDistances (
450+ ScheduleDAGInstrs *DAG, AIEPostRASchedStrategy *Scheduler,
451+ const TargetRegisterInfo *TRI, const AIEBaseInstrInfo *TII,
452+ const InstrItineraryData *ItinData) {
453+
454+ const BlockState &BS =
455+ Scheduler->getInterBlock ().getBlockState (DAG->getBB ());
453456
454- // We only need to focus on top-fixed instructions when there is an Epilogue
455- // block.
456457 if (BS.Kind != BlockType::Epilogue)
457458 return ;
458459
459460 MachineBasicBlock *Loop = AIELoopUtils::getLoopPredecessor (*DAG->getBB ());
460- assert (Loop);
461461 const BlockState &LBS = Scheduler->getInterBlock ().getBlockState (Loop);
462- assert (LBS.Kind == BlockType::Loop);
463462
464- if (!LBS.isPipelined ()) {
465- assert (CurRegion.getTopFixedBundles ().empty ());
463+ if (!LBS.isPipelined ())
466464 return ;
467- }
465+
466+ const Region &CurRegion = BS.getCurrentRegion ();
467+
468+ ArrayRef<AIE::MachineBundle> TopFixedBundles =
469+ CurRegion.getTopFixedBundles ();
468470
469471 ArrayRef<AIE::MachineBundle> LoopTimedBundles = LBS.getTop ().Bundles ;
470472
471- RET.computeUseDefForward (TopFixedBundles, /* InSeparateRegion=*/ false );
473+ AIERegMemEventTracker ForwardRET{ItinData, TRI, TII, AA};
474+
475+ ForwardRET.computeUseDefForward (TopFixedBundles,
476+ /* InSeparateRegion=*/ false );
472477 // It is more cost-effective to reuse the RET to establish individual safety
473478 // margins between the pipelined loop and the free instructions. This
474479 // approach allows us to manage all dependencies related to EntrySU in one
475480 // centralized location. While it is possible to implement this as a
476481 // separate mutator, doing so could be costly, as it would prevent the
477482 // creation of multiple edges from EntrySU to each free instruction that
478483 // depends on both timed regions (TopFixed and LoopTimed).
479- RET.computeUseDefForward (LoopTimedBundles, /* InSeparateRegion=*/ true );
484+ ForwardRET.computeUseDefForward (LoopTimedBundles,
485+ /* InSeparateRegion=*/ true );
480486
481487 auto IsNonTopFixedSU = [Scheduler](const SUnit &SU) {
482488 return !Scheduler->isFixedSU (SU, /* IsTop*/ true );
@@ -486,17 +492,22 @@ class EmitFixedSUnits : public ScheduleDAGMutation {
486492 // account the def/use cycle of each operand.
487493 for (SUnit &SU : make_filter_range (DAG->SUnits , IsNonTopFixedSU)) {
488494 const MachineInstr &MI = *SU.getInstr ();
489- if (const unsigned Latency = RET.getSafeOperandsDistanceFromTop (MI)) {
495+ if (const unsigned Latency =
496+ ForwardRET.getSafeOperandsDistanceFromTop (MI)) {
490497 SDep Dep (&DAG->EntrySU , SDep::Artificial);
491498 Dep.setLatency (Latency);
492499 SU.addPred (Dep, /* Required=*/ true );
493500 }
494501 }
502+ }
503+
504+ void establishSafeFixedSUToExitSUDistances (
505+ ScheduleDAGInstrs *DAG, AIEPostRASchedStrategy *Scheduler,
506+ const AIEBaseInstrInfo *TII, const InstrItineraryData *ItinData) {
495507
496508 auto IsTopFixedSU = [Scheduler](const SUnit &SU) {
497509 return Scheduler->isFixedSU (SU, true );
498510 };
499-
500511 // TODO: this is pessimistic, we can handle this in RegionEndEdges after
501512 // a mutation reordering.
502513 // Establish dependencies to ExitSU for each top-fixed sched. unit by taking
@@ -509,6 +520,28 @@ class EmitFixedSUnits : public ScheduleDAGMutation {
509520 DAG->ExitSU .addPred (Dep, /* Required=*/ true );
510521 }
511522 }
523+
524+ public:
525+ EmitFixedSUnits (AAResults *AA) : AA(AA) {}
526+
527+ void apply (ScheduleDAGInstrs *DAG) override {
528+ AIEPostRASchedStrategy *Scheduler =
529+ static_cast <AIEScheduleDAGMI *>(DAG)->getSchedImpl ();
530+ auto *TII = static_cast <const AIEBaseInstrInfo *>(DAG->TII );
531+ auto *ItinData = DAG->MF .getSubtarget ().getInstrItineraryData ();
532+ const TargetRegisterInfo *TRI = DAG->MF .getSubtarget ().getRegisterInfo ();
533+ const BlockState &BS =
534+ Scheduler->getInterBlock ().getBlockState (DAG->getBB ());
535+ const Region &CurRegion = BS.getCurrentRegion ();
536+
537+ createFixedSUDAGNodes (DAG, Scheduler, CurRegion);
538+
539+ establishSafeFreeSUToPrologueDistances (DAG, Scheduler, TRI, TII, ItinData);
540+
541+ establishSafeFreeSUToEpilogueDistances (DAG, Scheduler, TRI, TII, ItinData);
542+
543+ establishSafeFixedSUToExitSUDistances (DAG, Scheduler, TII, ItinData);
544+ }
512545};
513546
514547// / Collect all "weak" edges in a separate vector. This allows modifying
0 commit comments