LLVM API Documentation
00001 //===-- HexagonMachineScheduler.h - Custom Hexagon MI scheduler. ----===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Custom Hexagon MI scheduler. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H 00015 #define LLVM_LIB_TARGET_HEXAGON_HEXAGONMACHINESCHEDULER_H 00016 00017 #include "llvm/ADT/PriorityQueue.h" 00018 #include "llvm/Analysis/AliasAnalysis.h" 00019 #include "llvm/CodeGen/LiveIntervalAnalysis.h" 00020 #include "llvm/CodeGen/MachineScheduler.h" 00021 #include "llvm/CodeGen/Passes.h" 00022 #include "llvm/CodeGen/RegisterClassInfo.h" 00023 #include "llvm/CodeGen/RegisterPressure.h" 00024 #include "llvm/CodeGen/ResourcePriorityQueue.h" 00025 #include "llvm/CodeGen/ScheduleDAGInstrs.h" 00026 #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 00027 #include "llvm/Support/CommandLine.h" 00028 #include "llvm/Support/Debug.h" 00029 #include "llvm/Support/ErrorHandling.h" 00030 #include "llvm/Support/raw_ostream.h" 00031 #include "llvm/Target/TargetInstrInfo.h" 00032 00033 using namespace llvm; 00034 00035 namespace llvm { 00036 //===----------------------------------------------------------------------===// 00037 // ConvergingVLIWScheduler - Implementation of the standard 00038 // MachineSchedStrategy. 00039 //===----------------------------------------------------------------------===// 00040 00041 class VLIWResourceModel { 00042 /// ResourcesModel - Represents VLIW state. 00043 /// Not limited to VLIW targets per say, but assumes 00044 /// definition of DFA by a target. 00045 DFAPacketizer *ResourcesModel; 00046 00047 const TargetSchedModel *SchedModel; 00048 00049 /// Local packet/bundle model. Purely 00050 /// internal to the MI schedulre at the time. 00051 std::vector<SUnit*> Packet; 00052 00053 /// Total packets created. 00054 unsigned TotalPackets; 00055 00056 public: 00057 VLIWResourceModel(const TargetMachine &TM, const TargetSchedModel *SM) : 00058 SchedModel(SM), TotalPackets(0) { 00059 ResourcesModel = 00060 TM.getSubtargetImpl()->getInstrInfo()->CreateTargetScheduleState(&TM, 00061 nullptr); 00062 00063 // This hard requirement could be relaxed, 00064 // but for now do not let it proceed. 00065 assert(ResourcesModel && "Unimplemented CreateTargetScheduleState."); 00066 00067 Packet.resize(SchedModel->getIssueWidth()); 00068 Packet.clear(); 00069 ResourcesModel->clearResources(); 00070 } 00071 00072 ~VLIWResourceModel() { 00073 delete ResourcesModel; 00074 } 00075 00076 void resetPacketState() { 00077 Packet.clear(); 00078 } 00079 00080 void resetDFA() { 00081 ResourcesModel->clearResources(); 00082 } 00083 00084 void reset() { 00085 Packet.clear(); 00086 ResourcesModel->clearResources(); 00087 } 00088 00089 bool isResourceAvailable(SUnit *SU); 00090 bool reserveResources(SUnit *SU); 00091 unsigned getTotalPackets() const { return TotalPackets; } 00092 }; 00093 00094 /// Extend the standard ScheduleDAGMI to provide more context and override the 00095 /// top-level schedule() driver. 00096 class VLIWMachineScheduler : public ScheduleDAGMILive { 00097 public: 00098 VLIWMachineScheduler(MachineSchedContext *C, 00099 std::unique_ptr<MachineSchedStrategy> S) 00100 : ScheduleDAGMILive(C, std::move(S)) {} 00101 00102 /// Schedule - This is called back from ScheduleDAGInstrs::Run() when it's 00103 /// time to do some work. 00104 void schedule() override; 00105 /// Perform platform-specific DAG postprocessing. 00106 void postprocessDAG(); 00107 }; 00108 00109 /// ConvergingVLIWScheduler shrinks the unscheduled zone using heuristics 00110 /// to balance the schedule. 00111 class ConvergingVLIWScheduler : public MachineSchedStrategy { 00112 00113 /// Store the state used by ConvergingVLIWScheduler heuristics, required 00114 /// for the lifetime of one invocation of pickNode(). 00115 struct SchedCandidate { 00116 // The best SUnit candidate. 00117 SUnit *SU; 00118 00119 // Register pressure values for the best candidate. 00120 RegPressureDelta RPDelta; 00121 00122 // Best scheduling cost. 00123 int SCost; 00124 00125 SchedCandidate(): SU(nullptr), SCost(0) {} 00126 }; 00127 /// Represent the type of SchedCandidate found within a single queue. 00128 enum CandResult { 00129 NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure, 00130 BestCost}; 00131 00132 /// Each Scheduling boundary is associated with ready queues. It tracks the 00133 /// current cycle in whichever direction at has moved, and maintains the state 00134 /// of "hazards" and other interlocks at the current cycle. 00135 struct VLIWSchedBoundary { 00136 VLIWMachineScheduler *DAG; 00137 const TargetSchedModel *SchedModel; 00138 00139 ReadyQueue Available; 00140 ReadyQueue Pending; 00141 bool CheckPending; 00142 00143 ScheduleHazardRecognizer *HazardRec; 00144 VLIWResourceModel *ResourceModel; 00145 00146 unsigned CurrCycle; 00147 unsigned IssueCount; 00148 00149 /// MinReadyCycle - Cycle of the soonest available instruction. 00150 unsigned MinReadyCycle; 00151 00152 // Remember the greatest min operand latency. 00153 unsigned MaxMinLatency; 00154 00155 /// Pending queues extend the ready queues with the same ID and the 00156 /// PendingFlag set. 00157 VLIWSchedBoundary(unsigned ID, const Twine &Name): 00158 DAG(nullptr), SchedModel(nullptr), Available(ID, Name+".A"), 00159 Pending(ID << ConvergingVLIWScheduler::LogMaxQID, Name+".P"), 00160 CheckPending(false), HazardRec(nullptr), ResourceModel(nullptr), 00161 CurrCycle(0), IssueCount(0), 00162 MinReadyCycle(UINT_MAX), MaxMinLatency(0) {} 00163 00164 ~VLIWSchedBoundary() { 00165 delete ResourceModel; 00166 delete HazardRec; 00167 } 00168 00169 void init(VLIWMachineScheduler *dag, const TargetSchedModel *smodel) { 00170 DAG = dag; 00171 SchedModel = smodel; 00172 } 00173 00174 bool isTop() const { 00175 return Available.getID() == ConvergingVLIWScheduler::TopQID; 00176 } 00177 00178 bool checkHazard(SUnit *SU); 00179 00180 void releaseNode(SUnit *SU, unsigned ReadyCycle); 00181 00182 void bumpCycle(); 00183 00184 void bumpNode(SUnit *SU); 00185 00186 void releasePending(); 00187 00188 void removeReady(SUnit *SU); 00189 00190 SUnit *pickOnlyChoice(); 00191 }; 00192 00193 VLIWMachineScheduler *DAG; 00194 const TargetSchedModel *SchedModel; 00195 00196 // State of the top and bottom scheduled instruction boundaries. 00197 VLIWSchedBoundary Top; 00198 VLIWSchedBoundary Bot; 00199 00200 public: 00201 /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both) 00202 enum { 00203 TopQID = 1, 00204 BotQID = 2, 00205 LogMaxQID = 2 00206 }; 00207 00208 ConvergingVLIWScheduler() 00209 : DAG(nullptr), SchedModel(nullptr), Top(TopQID, "TopQ"), 00210 Bot(BotQID, "BotQ") {} 00211 00212 void initialize(ScheduleDAGMI *dag) override; 00213 00214 SUnit *pickNode(bool &IsTopNode) override; 00215 00216 void schedNode(SUnit *SU, bool IsTopNode) override; 00217 00218 void releaseTopNode(SUnit *SU) override; 00219 00220 void releaseBottomNode(SUnit *SU) override; 00221 00222 unsigned ReportPackets() { 00223 return Top.ResourceModel->getTotalPackets() + 00224 Bot.ResourceModel->getTotalPackets(); 00225 } 00226 00227 protected: 00228 SUnit *pickNodeBidrectional(bool &IsTopNode); 00229 00230 int SchedulingCost(ReadyQueue &Q, 00231 SUnit *SU, SchedCandidate &Candidate, 00232 RegPressureDelta &Delta, bool verbose); 00233 00234 CandResult pickNodeFromQueue(ReadyQueue &Q, 00235 const RegPressureTracker &RPTracker, 00236 SchedCandidate &Candidate); 00237 #ifndef NDEBUG 00238 void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU, 00239 PressureChange P = PressureChange()); 00240 #endif 00241 }; 00242 00243 } // namespace 00244 00245 00246 #endif