File indexing completed on 2026-05-10 08:43:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 #ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
0075 #define LLVM_CODEGEN_MACHINESCHEDULER_H
0076
0077 #include "llvm/ADT/APInt.h"
0078 #include "llvm/ADT/ArrayRef.h"
0079 #include "llvm/ADT/BitVector.h"
0080 #include "llvm/ADT/STLExtras.h"
0081 #include "llvm/ADT/SmallVector.h"
0082 #include "llvm/ADT/StringRef.h"
0083 #include "llvm/ADT/Twine.h"
0084 #include "llvm/CodeGen/MachineBasicBlock.h"
0085 #include "llvm/CodeGen/MachinePassRegistry.h"
0086 #include "llvm/CodeGen/RegisterPressure.h"
0087 #include "llvm/CodeGen/ScheduleDAG.h"
0088 #include "llvm/CodeGen/ScheduleDAGInstrs.h"
0089 #include "llvm/CodeGen/ScheduleDAGMutation.h"
0090 #include "llvm/CodeGen/TargetSchedule.h"
0091 #include "llvm/Support/CommandLine.h"
0092 #include "llvm/Support/ErrorHandling.h"
0093 #include <algorithm>
0094 #include <cassert>
0095 #include <llvm/Support/raw_ostream.h>
0096 #include <memory>
0097 #include <string>
0098 #include <vector>
0099
0100 namespace llvm {
0101
0102 namespace MISched {
0103 enum Direction {
0104 Unspecified,
0105 TopDown,
0106 BottomUp,
0107 Bidirectional,
0108 };
0109 }
0110
0111 extern cl::opt<MISched::Direction> PreRADirection;
0112 extern cl::opt<bool> VerifyScheduling;
0113 #ifndef NDEBUG
0114 extern cl::opt<bool> ViewMISchedDAGs;
0115 extern cl::opt<bool> PrintDAGs;
0116 #else
0117 extern const bool ViewMISchedDAGs;
0118 extern const bool PrintDAGs;
0119 #endif
0120
0121 class AAResults;
0122 class LiveIntervals;
0123 class MachineDominatorTree;
0124 class MachineFunction;
0125 class MachineInstr;
0126 class MachineLoopInfo;
0127 class RegisterClassInfo;
0128 class SchedDFSResult;
0129 class ScheduleHazardRecognizer;
0130 class TargetInstrInfo;
0131 class TargetPassConfig;
0132 class TargetRegisterInfo;
0133
0134
0135
0136 struct MachineSchedContext {
0137 MachineFunction *MF = nullptr;
0138 const MachineLoopInfo *MLI = nullptr;
0139 const MachineDominatorTree *MDT = nullptr;
0140 const TargetPassConfig *PassConfig = nullptr;
0141 AAResults *AA = nullptr;
0142 LiveIntervals *LIS = nullptr;
0143
0144 RegisterClassInfo *RegClassInfo;
0145
0146 MachineSchedContext();
0147 MachineSchedContext &operator=(const MachineSchedContext &other) = delete;
0148 MachineSchedContext(const MachineSchedContext &other) = delete;
0149 virtual ~MachineSchedContext();
0150 };
0151
0152
0153
0154 class MachineSchedRegistry
0155 : public MachinePassRegistryNode<
0156 ScheduleDAGInstrs *(*)(MachineSchedContext *)> {
0157 public:
0158 using ScheduleDAGCtor = ScheduleDAGInstrs *(*)(MachineSchedContext *);
0159
0160
0161 using FunctionPassCtor = ScheduleDAGCtor;
0162
0163 static MachinePassRegistry<ScheduleDAGCtor> Registry;
0164
0165 MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
0166 : MachinePassRegistryNode(N, D, C) {
0167 Registry.Add(this);
0168 }
0169
0170 ~MachineSchedRegistry() { Registry.Remove(this); }
0171
0172
0173
0174 MachineSchedRegistry *getNext() const {
0175 return (MachineSchedRegistry *)MachinePassRegistryNode::getNext();
0176 }
0177
0178 static MachineSchedRegistry *getList() {
0179 return (MachineSchedRegistry *)Registry.getList();
0180 }
0181
0182 static void setListener(MachinePassRegistryListener<FunctionPassCtor> *L) {
0183 Registry.setListener(L);
0184 }
0185 };
0186
0187 class ScheduleDAGMI;
0188
0189
0190
0191
0192 struct MachineSchedPolicy {
0193
0194 bool ShouldTrackPressure = false;
0195
0196
0197 bool ShouldTrackLaneMasks = false;
0198
0199
0200
0201 bool OnlyTopDown = false;
0202 bool OnlyBottomUp = false;
0203
0204
0205
0206 bool DisableLatencyHeuristic = false;
0207
0208
0209 bool ComputeDFSResult = false;
0210
0211 MachineSchedPolicy() = default;
0212 };
0213
0214
0215
0216
0217
0218
0219 class MachineSchedStrategy {
0220 virtual void anchor();
0221
0222 public:
0223 virtual ~MachineSchedStrategy() = default;
0224
0225
0226 virtual void initPolicy(MachineBasicBlock::iterator Begin,
0227 MachineBasicBlock::iterator End,
0228 unsigned NumRegionInstrs) {}
0229
0230 virtual MachineSchedPolicy getPolicy() const { return {}; }
0231 virtual void dumpPolicy() const {}
0232
0233
0234
0235 virtual bool shouldTrackPressure() const { return true; }
0236
0237
0238
0239
0240 virtual bool shouldTrackLaneMasks() const { return false; }
0241
0242
0243
0244
0245 virtual bool doMBBSchedRegionsTopDown() const { return false; }
0246
0247
0248 virtual void initialize(ScheduleDAGMI *DAG) = 0;
0249
0250
0251 virtual void enterMBB(MachineBasicBlock *MBB) {};
0252
0253
0254 virtual void leaveMBB() {};
0255
0256
0257
0258 virtual void registerRoots() {}
0259
0260
0261
0262
0263 virtual SUnit *pickNode(bool &IsTopNode) = 0;
0264
0265
0266 virtual void scheduleTree(unsigned SubtreeID) {}
0267
0268
0269
0270 virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
0271
0272
0273
0274 virtual void releaseTopNode(SUnit *SU) = 0;
0275
0276
0277
0278 virtual void releaseBottomNode(SUnit *SU) = 0;
0279 };
0280
0281
0282
0283
0284
0285 class ScheduleDAGMI : public ScheduleDAGInstrs {
0286 protected:
0287 AAResults *AA;
0288 LiveIntervals *LIS;
0289 std::unique_ptr<MachineSchedStrategy> SchedImpl;
0290
0291
0292 std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
0293
0294
0295 MachineBasicBlock::iterator CurrentTop;
0296
0297
0298 MachineBasicBlock::iterator CurrentBottom;
0299
0300
0301 const SUnit *NextClusterPred = nullptr;
0302 const SUnit *NextClusterSucc = nullptr;
0303
0304 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0305
0306
0307 unsigned NumInstrsScheduled = 0;
0308 #endif
0309
0310 public:
0311 ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
0312 bool RemoveKillFlags)
0313 : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA),
0314 LIS(C->LIS), SchedImpl(std::move(S)) {}
0315
0316
0317 ~ScheduleDAGMI() override;
0318
0319
0320
0321
0322 bool doMBBSchedRegionsTopDown() const override {
0323 return SchedImpl->doMBBSchedRegionsTopDown();
0324 }
0325
0326
0327 LiveIntervals *getLIS() const { return LIS; }
0328
0329
0330 virtual bool hasVRegLiveness() const { return false; }
0331
0332
0333
0334
0335
0336
0337 void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
0338 if (Mutation)
0339 Mutations.push_back(std::move(Mutation));
0340 }
0341
0342 MachineBasicBlock::iterator top() const { return CurrentTop; }
0343 MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
0344
0345
0346
0347
0348 void enterRegion(MachineBasicBlock *bb,
0349 MachineBasicBlock::iterator begin,
0350 MachineBasicBlock::iterator end,
0351 unsigned regioninstrs) override;
0352
0353
0354
0355 void schedule() override;
0356
0357 void startBlock(MachineBasicBlock *bb) override;
0358 void finishBlock() override;
0359
0360
0361
0362 void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
0363
0364 const SUnit *getNextClusterPred() const { return NextClusterPred; }
0365
0366 const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
0367
0368 void viewGraph(const Twine &Name, const Twine &Title) override;
0369 void viewGraph() override;
0370
0371 protected:
0372
0373
0374
0375
0376 void postProcessDAG();
0377
0378
0379 void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
0380
0381
0382 void updateQueues(SUnit *SU, bool IsTopNode);
0383
0384
0385 void placeDebugValues();
0386
0387
0388 void dumpSchedule() const;
0389
0390 void dumpScheduleTraceTopDown() const;
0391 void dumpScheduleTraceBottomUp() const;
0392
0393
0394 bool checkSchedLimit();
0395
0396 void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
0397 SmallVectorImpl<SUnit*> &BotRoots);
0398
0399 void releaseSucc(SUnit *SU, SDep *SuccEdge);
0400 void releaseSuccessors(SUnit *SU);
0401 void releasePred(SUnit *SU, SDep *PredEdge);
0402 void releasePredecessors(SUnit *SU);
0403 };
0404
0405
0406
0407 class ScheduleDAGMILive : public ScheduleDAGMI {
0408 protected:
0409 RegisterClassInfo *RegClassInfo;
0410
0411
0412
0413 SchedDFSResult *DFSResult = nullptr;
0414 BitVector ScheduledTrees;
0415
0416 MachineBasicBlock::iterator LiveRegionEnd;
0417
0418
0419 VReg2SUnitMultiMap VRegUses;
0420
0421
0422
0423
0424 PressureDiffs SUPressureDiffs;
0425
0426
0427 bool ShouldTrackPressure = false;
0428 bool ShouldTrackLaneMasks = false;
0429 IntervalPressure RegPressure;
0430 RegPressureTracker RPTracker;
0431
0432
0433
0434
0435 std::vector<PressureChange> RegionCriticalPSets;
0436
0437
0438 IntervalPressure TopPressure;
0439 RegPressureTracker TopRPTracker;
0440
0441
0442 IntervalPressure BotPressure;
0443 RegPressureTracker BotRPTracker;
0444
0445 public:
0446 ScheduleDAGMILive(MachineSchedContext *C,
0447 std::unique_ptr<MachineSchedStrategy> S)
0448 : ScheduleDAGMI(C, std::move(S), false),
0449 RegClassInfo(C->RegClassInfo), RPTracker(RegPressure),
0450 TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
0451
0452 ~ScheduleDAGMILive() override;
0453
0454
0455 bool hasVRegLiveness() const override { return true; }
0456
0457
0458 bool isTrackingPressure() const { return ShouldTrackPressure; }
0459
0460
0461 const IntervalPressure &getTopPressure() const { return TopPressure; }
0462 const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
0463
0464
0465 const IntervalPressure &getBotPressure() const { return BotPressure; }
0466 const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
0467
0468
0469 const IntervalPressure &getRegPressure() const { return RegPressure; }
0470
0471 const std::vector<PressureChange> &getRegionCriticalPSets() const {
0472 return RegionCriticalPSets;
0473 }
0474
0475 PressureDiff &getPressureDiff(const SUnit *SU) {
0476 return SUPressureDiffs[SU->NodeNum];
0477 }
0478 const PressureDiff &getPressureDiff(const SUnit *SU) const {
0479 return SUPressureDiffs[SU->NodeNum];
0480 }
0481
0482
0483
0484 void computeDFSResult();
0485
0486
0487 const SchedDFSResult *getDFSResult() const { return DFSResult; }
0488
0489 BitVector &getScheduledTrees() { return ScheduledTrees; }
0490
0491
0492
0493
0494 void enterRegion(MachineBasicBlock *bb,
0495 MachineBasicBlock::iterator begin,
0496 MachineBasicBlock::iterator end,
0497 unsigned regioninstrs) override;
0498
0499
0500
0501 void schedule() override;
0502
0503
0504 unsigned computeCyclicCriticalPath();
0505
0506 void dump() const override;
0507
0508 protected:
0509
0510
0511
0512
0513
0514
0515 void buildDAGWithRegPressure();
0516
0517
0518
0519 void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
0520
0521
0522 void scheduleMI(SUnit *SU, bool IsTopNode);
0523
0524
0525
0526 void initRegPressure();
0527
0528 void updatePressureDiffs(ArrayRef<VRegMaskOrUnit> LiveUses);
0529
0530 void updateScheduledPressure(const SUnit *SU,
0531 const std::vector<unsigned> &NewMaxPressure);
0532
0533 void collectVRegUses(SUnit &SU);
0534 };
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549 class ReadyQueue {
0550 unsigned ID;
0551 std::string Name;
0552 std::vector<SUnit*> Queue;
0553
0554 public:
0555 ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
0556
0557 unsigned getID() const { return ID; }
0558
0559 StringRef getName() const { return Name; }
0560
0561
0562 bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
0563
0564 bool empty() const { return Queue.empty(); }
0565
0566 void clear() { Queue.clear(); }
0567
0568 unsigned size() const { return Queue.size(); }
0569
0570 using iterator = std::vector<SUnit*>::iterator;
0571
0572 iterator begin() { return Queue.begin(); }
0573
0574 iterator end() { return Queue.end(); }
0575
0576 ArrayRef<SUnit*> elements() { return Queue; }
0577
0578 iterator find(SUnit *SU) { return llvm::find(Queue, SU); }
0579
0580 void push(SUnit *SU) {
0581 Queue.push_back(SU);
0582 SU->NodeQueueId |= ID;
0583 }
0584
0585 iterator remove(iterator I) {
0586 (*I)->NodeQueueId &= ~ID;
0587 *I = Queue.back();
0588 unsigned idx = I - Queue.begin();
0589 Queue.pop_back();
0590 return Queue.begin() + idx;
0591 }
0592
0593 void dump() const;
0594 };
0595
0596
0597 struct SchedRemainder {
0598
0599 unsigned CriticalPath;
0600 unsigned CyclicCritPath;
0601
0602
0603 unsigned RemIssueCount;
0604
0605 bool IsAcyclicLatencyLimited;
0606
0607
0608 SmallVector<unsigned, 16> RemainingCounts;
0609
0610 SchedRemainder() { reset(); }
0611
0612 void reset() {
0613 CriticalPath = 0;
0614 CyclicCritPath = 0;
0615 RemIssueCount = 0;
0616 IsAcyclicLatencyLimited = false;
0617 RemainingCounts.clear();
0618 }
0619
0620 void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel);
0621 };
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636 class ResourceSegments {
0637 public:
0638
0639
0640 typedef std::pair<int64_t, int64_t> IntervalTy;
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657 void add(IntervalTy A, const unsigned CutOff = 10);
0658
0659 public:
0660
0661 static bool intersects(IntervalTy A, IntervalTy B);
0662
0663
0664
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726 static IntervalTy getResourceIntervalBottom(unsigned C, unsigned AcquireAtCycle,
0727 unsigned ReleaseAtCycle) {
0728 return std::make_pair<long, long>((long)C - (long)ReleaseAtCycle + 1L,
0729 (long)C - (long)AcquireAtCycle + 1L);
0730 }
0731 static IntervalTy getResourceIntervalTop(unsigned C, unsigned AcquireAtCycle,
0732 unsigned ReleaseAtCycle) {
0733 return std::make_pair<long, long>((long)C + (long)AcquireAtCycle,
0734 (long)C + (long)ReleaseAtCycle);
0735 }
0736
0737 private:
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784 unsigned getFirstAvailableAt(
0785 unsigned CurrCycle, unsigned AcquireAtCycle, unsigned ReleaseAtCycle,
0786 std::function<IntervalTy(unsigned, unsigned, unsigned)> IntervalBuilder)
0787 const;
0788
0789 public:
0790
0791
0792
0793 unsigned getFirstAvailableAtFromBottom(unsigned CurrCycle,
0794 unsigned AcquireAtCycle,
0795 unsigned ReleaseAtCycle) const {
0796 return getFirstAvailableAt(CurrCycle, AcquireAtCycle, ReleaseAtCycle,
0797 getResourceIntervalBottom);
0798 }
0799 unsigned getFirstAvailableAtFromTop(unsigned CurrCycle,
0800 unsigned AcquireAtCycle,
0801 unsigned ReleaseAtCycle) const {
0802 return getFirstAvailableAt(CurrCycle, AcquireAtCycle, ReleaseAtCycle,
0803 getResourceIntervalTop);
0804 }
0805
0806 private:
0807 std::list<IntervalTy> _Intervals;
0808
0809
0810
0811
0812
0813 void sortAndMerge();
0814
0815 public:
0816
0817 explicit ResourceSegments(){};
0818 bool empty() const { return _Intervals.empty(); }
0819 explicit ResourceSegments(const std::list<IntervalTy> &Intervals)
0820 : _Intervals(Intervals) {
0821 sortAndMerge();
0822 }
0823
0824 friend bool operator==(const ResourceSegments &c1,
0825 const ResourceSegments &c2) {
0826 return c1._Intervals == c2._Intervals;
0827 }
0828 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
0829 const ResourceSegments &Segments) {
0830 os << "{ ";
0831 for (auto p : Segments._Intervals)
0832 os << "[" << p.first << ", " << p.second << "), ";
0833 os << "}\n";
0834 return os;
0835 }
0836 };
0837
0838
0839
0840
0841 class SchedBoundary {
0842 public:
0843
0844 enum {
0845 TopQID = 1,
0846 BotQID = 2,
0847 LogMaxQID = 2
0848 };
0849
0850 ScheduleDAGMI *DAG = nullptr;
0851 const TargetSchedModel *SchedModel = nullptr;
0852 SchedRemainder *Rem = nullptr;
0853
0854 ReadyQueue Available;
0855 ReadyQueue Pending;
0856
0857 ScheduleHazardRecognizer *HazardRec = nullptr;
0858
0859 private:
0860
0861
0862 bool CheckPending;
0863
0864
0865
0866
0867 unsigned CurrCycle;
0868
0869
0870 unsigned CurrMOps;
0871
0872
0873 unsigned MinReadyCycle;
0874
0875
0876 unsigned ExpectedLatency;
0877
0878
0879
0880
0881 unsigned DependentLatency;
0882
0883
0884
0885 unsigned RetiredMOps;
0886
0887
0888
0889
0890
0891
0892 SmallVector<unsigned, 16> ExecutedResCounts;
0893
0894
0895 unsigned MaxExecutedResCount;
0896
0897
0898 unsigned ZoneCritResIdx;
0899
0900
0901 bool IsResourceLimited;
0902
0903 public:
0904 private:
0905
0906
0907 std::map<unsigned, ResourceSegments> ReservedResourceSegments;
0908 std::vector<unsigned> ReservedCycles;
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938 SmallVector<unsigned, 16> ReservedCyclesIndex;
0939
0940
0941 SmallVector<APInt, 16> ResourceGroupSubUnitMasks;
0942
0943 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0944
0945
0946 unsigned MaxObservedStall;
0947 #endif
0948
0949 public:
0950
0951
0952 SchedBoundary(unsigned ID, const Twine &Name):
0953 Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") {
0954 reset();
0955 }
0956 SchedBoundary &operator=(const SchedBoundary &other) = delete;
0957 SchedBoundary(const SchedBoundary &other) = delete;
0958 ~SchedBoundary();
0959
0960 void reset();
0961
0962 void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel,
0963 SchedRemainder *rem);
0964
0965 bool isTop() const {
0966 return Available.getID() == TopQID;
0967 }
0968
0969
0970 unsigned getCurrCycle() const { return CurrCycle; }
0971
0972
0973 unsigned getCurrMOps() const { return CurrMOps; }
0974
0975
0976 unsigned getDependentLatency() const { return DependentLatency; }
0977
0978
0979
0980
0981 unsigned getScheduledLatency() const {
0982 return std::max(ExpectedLatency, CurrCycle);
0983 }
0984
0985 unsigned getUnscheduledLatency(SUnit *SU) const {
0986 return isTop() ? SU->getHeight() : SU->getDepth();
0987 }
0988
0989 unsigned getResourceCount(unsigned ResIdx) const {
0990 return ExecutedResCounts[ResIdx];
0991 }
0992
0993
0994
0995 unsigned getCriticalCount() const {
0996 if (!ZoneCritResIdx)
0997 return RetiredMOps * SchedModel->getMicroOpFactor();
0998 return getResourceCount(ZoneCritResIdx);
0999 }
1000
1001
1002
1003
1004 unsigned getExecutedCount() const {
1005 return std::max(CurrCycle * SchedModel->getLatencyFactor(),
1006 MaxExecutedResCount);
1007 }
1008
1009 unsigned getZoneCritResIdx() const { return ZoneCritResIdx; }
1010
1011
1012 bool isResourceLimited() const { return IsResourceLimited; }
1013
1014
1015
1016 unsigned getLatencyStallCycles(SUnit *SU);
1017
1018 unsigned getNextResourceCycleByInstance(unsigned InstanceIndex,
1019 unsigned ReleaseAtCycle,
1020 unsigned AcquireAtCycle);
1021
1022 std::pair<unsigned, unsigned> getNextResourceCycle(const MCSchedClassDesc *SC,
1023 unsigned PIdx,
1024 unsigned ReleaseAtCycle,
1025 unsigned AcquireAtCycle);
1026
1027 bool isUnbufferedGroup(unsigned PIdx) const {
1028 return SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin &&
1029 !SchedModel->getProcResource(PIdx)->BufferSize;
1030 }
1031
1032 bool checkHazard(SUnit *SU);
1033
1034 unsigned findMaxLatency(ArrayRef<SUnit*> ReadySUs);
1035
1036 unsigned getOtherResourceCount(unsigned &OtherCritIdx);
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046 void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue,
1047 unsigned Idx = 0);
1048
1049 void bumpCycle(unsigned NextCycle);
1050
1051 void incExecutedResources(unsigned PIdx, unsigned Count);
1052
1053 unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx,
1054 unsigned Cycles, unsigned ReadyCycle,
1055 unsigned StartAtCycle);
1056
1057 void bumpNode(SUnit *SU);
1058
1059 void releasePending();
1060
1061 void removeReady(SUnit *SU);
1062
1063
1064
1065
1066 SUnit *pickOnlyChoice();
1067
1068
1069 void dumpReservedCycles() const;
1070 void dumpScheduledState() const;
1071 };
1072
1073
1074
1075
1076 class GenericSchedulerBase : public MachineSchedStrategy {
1077 public:
1078
1079
1080 enum CandReason : uint8_t {
1081 NoCand, Only1, PhysReg, RegExcess, RegCritical, Stall, Cluster, Weak,
1082 RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
1083 TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
1084
1085 #ifndef NDEBUG
1086 static const char *getReasonStr(GenericSchedulerBase::CandReason Reason);
1087 #endif
1088
1089
1090 struct CandPolicy {
1091 bool ReduceLatency = false;
1092 unsigned ReduceResIdx = 0;
1093 unsigned DemandResIdx = 0;
1094
1095 CandPolicy() = default;
1096
1097 bool operator==(const CandPolicy &RHS) const {
1098 return ReduceLatency == RHS.ReduceLatency &&
1099 ReduceResIdx == RHS.ReduceResIdx &&
1100 DemandResIdx == RHS.DemandResIdx;
1101 }
1102 bool operator!=(const CandPolicy &RHS) const {
1103 return !(*this == RHS);
1104 }
1105 };
1106
1107
1108 struct SchedResourceDelta {
1109
1110 unsigned CritResources = 0;
1111
1112
1113 unsigned DemandedResources = 0;
1114
1115 SchedResourceDelta() = default;
1116
1117 bool operator==(const SchedResourceDelta &RHS) const {
1118 return CritResources == RHS.CritResources
1119 && DemandedResources == RHS.DemandedResources;
1120 }
1121 bool operator!=(const SchedResourceDelta &RHS) const {
1122 return !operator==(RHS);
1123 }
1124 };
1125
1126
1127
1128 struct SchedCandidate {
1129 CandPolicy Policy;
1130
1131
1132 SUnit *SU;
1133
1134
1135 CandReason Reason;
1136
1137
1138 bool AtTop;
1139
1140
1141 RegPressureDelta RPDelta;
1142
1143
1144 SchedResourceDelta ResDelta;
1145
1146 SchedCandidate() { reset(CandPolicy()); }
1147 SchedCandidate(const CandPolicy &Policy) { reset(Policy); }
1148
1149 void reset(const CandPolicy &NewPolicy) {
1150 Policy = NewPolicy;
1151 SU = nullptr;
1152 Reason = NoCand;
1153 AtTop = false;
1154 RPDelta = RegPressureDelta();
1155 ResDelta = SchedResourceDelta();
1156 }
1157
1158 bool isValid() const { return SU; }
1159
1160
1161 void setBest(SchedCandidate &Best) {
1162 assert(Best.Reason != NoCand && "uninitialized Sched candidate");
1163 SU = Best.SU;
1164 Reason = Best.Reason;
1165 AtTop = Best.AtTop;
1166 RPDelta = Best.RPDelta;
1167 ResDelta = Best.ResDelta;
1168 }
1169
1170 void initResourceDelta(const ScheduleDAGMI *DAG,
1171 const TargetSchedModel *SchedModel);
1172 };
1173
1174 protected:
1175 const MachineSchedContext *Context;
1176 const TargetSchedModel *SchedModel = nullptr;
1177 const TargetRegisterInfo *TRI = nullptr;
1178
1179 MachineSchedPolicy RegionPolicy;
1180
1181 SchedRemainder Rem;
1182
1183 GenericSchedulerBase(const MachineSchedContext *C) : Context(C) {}
1184
1185 void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone,
1186 SchedBoundary *OtherZone);
1187
1188 MachineSchedPolicy getPolicy() const override { return RegionPolicy; }
1189
1190 #ifndef NDEBUG
1191 void traceCandidate(const SchedCandidate &Cand);
1192 #endif
1193
1194 private:
1195 bool shouldReduceLatency(const CandPolicy &Policy, SchedBoundary &CurrZone,
1196 bool ComputeRemLatency, unsigned &RemLatency) const;
1197 };
1198
1199
1200 bool tryLess(int TryVal, int CandVal,
1201 GenericSchedulerBase::SchedCandidate &TryCand,
1202 GenericSchedulerBase::SchedCandidate &Cand,
1203 GenericSchedulerBase::CandReason Reason);
1204 bool tryGreater(int TryVal, int CandVal,
1205 GenericSchedulerBase::SchedCandidate &TryCand,
1206 GenericSchedulerBase::SchedCandidate &Cand,
1207 GenericSchedulerBase::CandReason Reason);
1208 bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
1209 GenericSchedulerBase::SchedCandidate &Cand,
1210 SchedBoundary &Zone);
1211 bool tryPressure(const PressureChange &TryP,
1212 const PressureChange &CandP,
1213 GenericSchedulerBase::SchedCandidate &TryCand,
1214 GenericSchedulerBase::SchedCandidate &Cand,
1215 GenericSchedulerBase::CandReason Reason,
1216 const TargetRegisterInfo *TRI,
1217 const MachineFunction &MF);
1218 unsigned getWeakLeft(const SUnit *SU, bool isTop);
1219 int biasPhysReg(const SUnit *SU, bool isTop);
1220
1221
1222
1223 class GenericScheduler : public GenericSchedulerBase {
1224 public:
1225 GenericScheduler(const MachineSchedContext *C):
1226 GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
1227 Bot(SchedBoundary::BotQID, "BotQ") {}
1228
1229 void initPolicy(MachineBasicBlock::iterator Begin,
1230 MachineBasicBlock::iterator End,
1231 unsigned NumRegionInstrs) override;
1232
1233 void dumpPolicy() const override;
1234
1235 bool shouldTrackPressure() const override {
1236 return RegionPolicy.ShouldTrackPressure;
1237 }
1238
1239 bool shouldTrackLaneMasks() const override {
1240 return RegionPolicy.ShouldTrackLaneMasks;
1241 }
1242
1243 void initialize(ScheduleDAGMI *dag) override;
1244
1245 SUnit *pickNode(bool &IsTopNode) override;
1246
1247 void schedNode(SUnit *SU, bool IsTopNode) override;
1248
1249 void releaseTopNode(SUnit *SU) override {
1250 if (SU->isScheduled)
1251 return;
1252
1253 Top.releaseNode(SU, SU->TopReadyCycle, false);
1254 TopCand.SU = nullptr;
1255 }
1256
1257 void releaseBottomNode(SUnit *SU) override {
1258 if (SU->isScheduled)
1259 return;
1260
1261 Bot.releaseNode(SU, SU->BotReadyCycle, false);
1262 BotCand.SU = nullptr;
1263 }
1264
1265 void registerRoots() override;
1266
1267 protected:
1268 ScheduleDAGMILive *DAG = nullptr;
1269
1270
1271 SchedBoundary Top;
1272 SchedBoundary Bot;
1273
1274
1275 SchedCandidate TopCand;
1276
1277 SchedCandidate BotCand;
1278
1279 void checkAcyclicLatency();
1280
1281 void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
1282 const RegPressureTracker &RPTracker,
1283 RegPressureTracker &TempTracker);
1284
1285 virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
1286 SchedBoundary *Zone) const;
1287
1288 SUnit *pickNodeBidirectional(bool &IsTopNode);
1289
1290 void pickNodeFromQueue(SchedBoundary &Zone,
1291 const CandPolicy &ZonePolicy,
1292 const RegPressureTracker &RPTracker,
1293 SchedCandidate &Candidate);
1294
1295 void reschedulePhysReg(SUnit *SU, bool isTop);
1296 };
1297
1298
1299
1300
1301
1302
1303 class PostGenericScheduler : public GenericSchedulerBase {
1304 protected:
1305 ScheduleDAGMI *DAG = nullptr;
1306 SchedBoundary Top;
1307 SchedBoundary Bot;
1308
1309
1310 SchedCandidate TopCand;
1311
1312 SchedCandidate BotCand;
1313
1314 public:
1315 PostGenericScheduler(const MachineSchedContext *C)
1316 : GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
1317 Bot(SchedBoundary::BotQID, "BotQ") {}
1318
1319 ~PostGenericScheduler() override = default;
1320
1321 void initPolicy(MachineBasicBlock::iterator Begin,
1322 MachineBasicBlock::iterator End,
1323 unsigned NumRegionInstrs) override;
1324
1325
1326 bool shouldTrackPressure() const override { return false; }
1327
1328 void initialize(ScheduleDAGMI *Dag) override;
1329
1330 void registerRoots() override;
1331
1332 SUnit *pickNode(bool &IsTopNode) override;
1333
1334 SUnit *pickNodeBidirectional(bool &IsTopNode);
1335
1336 void scheduleTree(unsigned SubtreeID) override {
1337 llvm_unreachable("PostRA scheduler does not support subtree analysis.");
1338 }
1339
1340 void schedNode(SUnit *SU, bool IsTopNode) override;
1341
1342 void releaseTopNode(SUnit *SU) override {
1343 if (SU->isScheduled)
1344 return;
1345 Top.releaseNode(SU, SU->TopReadyCycle, false);
1346 TopCand.SU = nullptr;
1347 }
1348
1349 void releaseBottomNode(SUnit *SU) override {
1350 if (SU->isScheduled)
1351 return;
1352 Bot.releaseNode(SU, SU->BotReadyCycle, false);
1353 BotCand.SU = nullptr;
1354 }
1355
1356 protected:
1357 virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand);
1358
1359 void pickNodeFromQueue(SchedBoundary &Zone, SchedCandidate &Cand);
1360 };
1361
1362
1363
1364
1365 ScheduleDAGMILive *createGenericSchedLive(MachineSchedContext *C);
1366
1367
1368 ScheduleDAGMI *createGenericSchedPostRA(MachineSchedContext *C);
1369
1370
1371
1372 std::unique_ptr<ScheduleDAGMutation>
1373 createLoadClusterDAGMutation(const TargetInstrInfo *TII,
1374 const TargetRegisterInfo *TRI,
1375 bool ReorderWhileClustering = false);
1376
1377
1378
1379 std::unique_ptr<ScheduleDAGMutation>
1380 createStoreClusterDAGMutation(const TargetInstrInfo *TII,
1381 const TargetRegisterInfo *TRI,
1382 bool ReorderWhileClustering = false);
1383
1384 std::unique_ptr<ScheduleDAGMutation>
1385 createCopyConstrainDAGMutation(const TargetInstrInfo *TII,
1386 const TargetRegisterInfo *TRI);
1387
1388 }
1389
1390 #endif