LLVM API Documentation
00001 //===---- ScheduleDAG.cpp - Implement the ScheduleDAG class ---------------===// 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 // This implements the ScheduleDAG class, which is a base class used by 00011 // scheduling implementation classes. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define DEBUG_TYPE "pre-RA-sched" 00016 #include "llvm/CodeGen/ScheduleDAG.h" 00017 #include "llvm/CodeGen/ScheduleHazardRecognizer.h" 00018 #include "llvm/Target/TargetMachine.h" 00019 #include "llvm/Target/TargetInstrInfo.h" 00020 #include "llvm/Target/TargetRegisterInfo.h" 00021 #include "llvm/Support/Debug.h" 00022 #include <climits> 00023 using namespace llvm; 00024 00025 ScheduleDAG::ScheduleDAG(MachineFunction &mf) 00026 : DAG(0), BB(0), TM(mf.getTarget()), 00027 TII(TM.getInstrInfo()), 00028 TRI(TM.getRegisterInfo()), 00029 TLI(TM.getTargetLowering()), 00030 MF(mf), MRI(mf.getRegInfo()), 00031 ConstPool(MF.getConstantPool()) { 00032 } 00033 00034 ScheduleDAG::~ScheduleDAG() {} 00035 00036 /// dump - dump the schedule. 00037 void ScheduleDAG::dumpSchedule() const { 00038 for (unsigned i = 0, e = Sequence.size(); i != e; i++) { 00039 if (SUnit *SU = Sequence[i]) 00040 SU->dump(this); 00041 else 00042 cerr << "**** NOOP ****\n"; 00043 } 00044 } 00045 00046 00047 /// Run - perform scheduling. 00048 /// 00049 void ScheduleDAG::Run(SelectionDAG *dag, MachineBasicBlock *bb, 00050 MachineBasicBlock::iterator begin, 00051 MachineBasicBlock::iterator end) { 00052 assert((!dag || begin == end) && 00053 "An instruction range was given for SelectionDAG scheduling!"); 00054 00055 SUnits.clear(); 00056 Sequence.clear(); 00057 DAG = dag; 00058 BB = bb; 00059 Begin = begin; 00060 End = end; 00061 00062 Schedule(); 00063 00064 DOUT << "*** Final schedule ***\n"; 00065 DEBUG(dumpSchedule()); 00066 DOUT << "\n"; 00067 } 00068 00069 /// addPred - This adds the specified edge as a pred of the current node if 00070 /// not already. It also adds the current node as a successor of the 00071 /// specified node. 00072 void SUnit::addPred(const SDep &D) { 00073 // If this node already has this depenence, don't add a redundant one. 00074 for (unsigned i = 0, e = (unsigned)Preds.size(); i != e; ++i) 00075 if (Preds[i] == D) 00076 return; 00077 // Now add a corresponding succ to N. 00078 SDep P = D; 00079 P.setSUnit(this); 00080 SUnit *N = D.getSUnit(); 00081 // Update the bookkeeping. 00082 if (D.getKind() == SDep::Data) { 00083 ++NumPreds; 00084 ++N->NumSuccs; 00085 } 00086 if (!N->isScheduled) 00087 ++NumPredsLeft; 00088 if (!isScheduled) 00089 ++N->NumSuccsLeft; 00090 Preds.push_back(D); 00091 N->Succs.push_back(P); 00092 if (P.getLatency() != 0) { 00093 this->setDepthDirty(); 00094 N->setHeightDirty(); 00095 } 00096 } 00097 00098 /// removePred - This removes the specified edge as a pred of the current 00099 /// node if it exists. It also removes the current node as a successor of 00100 /// the specified node. 00101 void SUnit::removePred(const SDep &D) { 00102 // Find the matching predecessor. 00103 for (SmallVector<SDep, 4>::iterator I = Preds.begin(), E = Preds.end(); 00104 I != E; ++I) 00105 if (*I == D) { 00106 bool FoundSucc = false; 00107 // Find the corresponding successor in N. 00108 SDep P = D; 00109 P.setSUnit(this); 00110 SUnit *N = D.getSUnit(); 00111 for (SmallVector<SDep, 4>::iterator II = N->Succs.begin(), 00112 EE = N->Succs.end(); II != EE; ++II) 00113 if (*II == P) { 00114 FoundSucc = true; 00115 N->Succs.erase(II); 00116 break; 00117 } 00118 assert(FoundSucc && "Mismatching preds / succs lists!"); 00119 Preds.erase(I); 00120 // Update the bookkeeping. 00121 if (P.getKind() == SDep::Data) { 00122 --NumPreds; 00123 --N->NumSuccs; 00124 } 00125 if (!N->isScheduled) 00126 --NumPredsLeft; 00127 if (!isScheduled) 00128 --N->NumSuccsLeft; 00129 if (P.getLatency() != 0) { 00130 this->setDepthDirty(); 00131 N->setHeightDirty(); 00132 } 00133 return; 00134 } 00135 } 00136 00137 void SUnit::setDepthDirty() { 00138 if (!isDepthCurrent) return; 00139 SmallVector<SUnit*, 8> WorkList; 00140 WorkList.push_back(this); 00141 do { 00142 SUnit *SU = WorkList.pop_back_val(); 00143 SU->isDepthCurrent = false; 00144 for (SUnit::const_succ_iterator I = SU->Succs.begin(), 00145 E = SU->Succs.end(); I != E; ++I) { 00146 SUnit *SuccSU = I->getSUnit(); 00147 if (SuccSU->isDepthCurrent) 00148 WorkList.push_back(SuccSU); 00149 } 00150 } while (!WorkList.empty()); 00151 } 00152 00153 void SUnit::setHeightDirty() { 00154 if (!isHeightCurrent) return; 00155 SmallVector<SUnit*, 8> WorkList; 00156 WorkList.push_back(this); 00157 do { 00158 SUnit *SU = WorkList.pop_back_val(); 00159 SU->isHeightCurrent = false; 00160 for (SUnit::const_pred_iterator I = SU->Preds.begin(), 00161 E = SU->Preds.end(); I != E; ++I) { 00162 SUnit *PredSU = I->getSUnit(); 00163 if (PredSU->isHeightCurrent) 00164 WorkList.push_back(PredSU); 00165 } 00166 } while (!WorkList.empty()); 00167 } 00168 00169 /// setDepthToAtLeast - Update this node's successors to reflect the 00170 /// fact that this node's depth just increased. 00171 /// 00172 void SUnit::setDepthToAtLeast(unsigned NewDepth) { 00173 if (NewDepth <= getDepth()) 00174 return; 00175 setDepthDirty(); 00176 Depth = NewDepth; 00177 isDepthCurrent = true; 00178 } 00179 00180 /// setHeightToAtLeast - Update this node's predecessors to reflect the 00181 /// fact that this node's height just increased. 00182 /// 00183 void SUnit::setHeightToAtLeast(unsigned NewHeight) { 00184 if (NewHeight <= getHeight()) 00185 return; 00186 setHeightDirty(); 00187 Height = NewHeight; 00188 isHeightCurrent = true; 00189 } 00190 00191 /// ComputeDepth - Calculate the maximal path from the node to the exit. 00192 /// 00193 void SUnit::ComputeDepth() { 00194 SmallVector<SUnit*, 8> WorkList; 00195 WorkList.push_back(this); 00196 do { 00197 SUnit *Cur = WorkList.back(); 00198 00199 bool Done = true; 00200 unsigned MaxPredDepth = 0; 00201 for (SUnit::const_pred_iterator I = Cur->Preds.begin(), 00202 E = Cur->Preds.end(); I != E; ++I) { 00203 SUnit *PredSU = I->getSUnit(); 00204 if (PredSU->isDepthCurrent) 00205 MaxPredDepth = std::max(MaxPredDepth, 00206 PredSU->Depth + I->getLatency()); 00207 else { 00208 Done = false; 00209 WorkList.push_back(PredSU); 00210 } 00211 } 00212 00213 if (Done) { 00214 WorkList.pop_back(); 00215 if (MaxPredDepth != Cur->Depth) { 00216 Cur->setDepthDirty(); 00217 Cur->Depth = MaxPredDepth; 00218 } 00219 Cur->isDepthCurrent = true; 00220 } 00221 } while (!WorkList.empty()); 00222 } 00223 00224 /// ComputeHeight - Calculate the maximal path from the node to the entry. 00225 /// 00226 void SUnit::ComputeHeight() { 00227 SmallVector<SUnit*, 8> WorkList; 00228 WorkList.push_back(this); 00229 do { 00230 SUnit *Cur = WorkList.back(); 00231 00232 bool Done = true; 00233 unsigned MaxSuccHeight = 0; 00234 for (SUnit::const_succ_iterator I = Cur->Succs.begin(), 00235 E = Cur->Succs.end(); I != E; ++I) { 00236 SUnit *SuccSU = I->getSUnit(); 00237 if (SuccSU->isHeightCurrent) 00238 MaxSuccHeight = std::max(MaxSuccHeight, 00239 SuccSU->Height + I->getLatency()); 00240 else { 00241 Done = false; 00242 WorkList.push_back(SuccSU); 00243 } 00244 } 00245 00246 if (Done) { 00247 WorkList.pop_back(); 00248 if (MaxSuccHeight != Cur->Height) { 00249 Cur->setHeightDirty(); 00250 Cur->Height = MaxSuccHeight; 00251 } 00252 Cur->isHeightCurrent = true; 00253 } 00254 } while (!WorkList.empty()); 00255 } 00256 00257 /// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or 00258 /// a group of nodes flagged together. 00259 void SUnit::dump(const ScheduleDAG *G) const { 00260 cerr << "SU(" << NodeNum << "): "; 00261 G->dumpNode(this); 00262 } 00263 00264 void SUnit::dumpAll(const ScheduleDAG *G) const { 00265 dump(G); 00266 00267 cerr << " # preds left : " << NumPredsLeft << "\n"; 00268 cerr << " # succs left : " << NumSuccsLeft << "\n"; 00269 cerr << " Latency : " << Latency << "\n"; 00270 cerr << " Depth : " << Depth << "\n"; 00271 cerr << " Height : " << Height << "\n"; 00272 00273 if (Preds.size() != 0) { 00274 cerr << " Predecessors:\n"; 00275 for (SUnit::const_succ_iterator I = Preds.begin(), E = Preds.end(); 00276 I != E; ++I) { 00277 cerr << " "; 00278 switch (I->getKind()) { 00279 case SDep::Data: cerr << "val "; break; 00280 case SDep::Anti: cerr << "anti"; break; 00281 case SDep::Output: cerr << "out "; break; 00282 case SDep::Order: cerr << "ch "; break; 00283 } 00284 cerr << "#"; 00285 cerr << I->getSUnit() << " - SU(" << I->getSUnit()->NodeNum << ")"; 00286 if (I->isArtificial()) 00287 cerr << " *"; 00288 cerr << "\n"; 00289 } 00290 } 00291 if (Succs.size() != 0) { 00292 cerr << " Successors:\n"; 00293 for (SUnit::const_succ_iterator I = Succs.begin(), E = Succs.end(); 00294 I != E; ++I) { 00295 cerr << " "; 00296 switch (I->getKind()) { 00297 case SDep::Data: cerr << "val "; break; 00298 case SDep::Anti: cerr << "anti"; break; 00299 case SDep::Output: cerr << "out "; break; 00300 case SDep::Order: cerr << "ch "; break; 00301 } 00302 cerr << "#"; 00303 cerr << I->getSUnit() << " - SU(" << I->getSUnit()->NodeNum << ")"; 00304 if (I->isArtificial()) 00305 cerr << " *"; 00306 cerr << "\n"; 00307 } 00308 } 00309 cerr << "\n"; 00310 } 00311 00312 #ifndef NDEBUG 00313 /// VerifySchedule - Verify that all SUnits were scheduled and that 00314 /// their state is consistent. 00315 /// 00316 void ScheduleDAG::VerifySchedule(bool isBottomUp) { 00317 bool AnyNotSched = false; 00318 unsigned DeadNodes = 0; 00319 unsigned Noops = 0; 00320 for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { 00321 if (!SUnits[i].isScheduled) { 00322 if (SUnits[i].NumPreds == 0 && SUnits[i].NumSuccs == 0) { 00323 ++DeadNodes; 00324 continue; 00325 } 00326 if (!AnyNotSched) 00327 cerr << "*** Scheduling failed! ***\n"; 00328 SUnits[i].dump(this); 00329 cerr << "has not been scheduled!\n"; 00330 AnyNotSched = true; 00331 } 00332 if (SUnits[i].isScheduled && 00333 (isBottomUp ? SUnits[i].getHeight() : SUnits[i].getHeight()) > 00334 unsigned(INT_MAX)) { 00335 if (!AnyNotSched) 00336 cerr << "*** Scheduling failed! ***\n"; 00337 SUnits[i].dump(this); 00338 cerr << "has an unexpected " 00339 << (isBottomUp ? "Height" : "Depth") << " value!\n"; 00340 AnyNotSched = true; 00341 } 00342 if (isBottomUp) { 00343 if (SUnits[i].NumSuccsLeft != 0) { 00344 if (!AnyNotSched) 00345 cerr << "*** Scheduling failed! ***\n"; 00346 SUnits[i].dump(this); 00347 cerr << "has successors left!\n"; 00348 AnyNotSched = true; 00349 } 00350 } else { 00351 if (SUnits[i].NumPredsLeft != 0) { 00352 if (!AnyNotSched) 00353 cerr << "*** Scheduling failed! ***\n"; 00354 SUnits[i].dump(this); 00355 cerr << "has predecessors left!\n"; 00356 AnyNotSched = true; 00357 } 00358 } 00359 } 00360 for (unsigned i = 0, e = Sequence.size(); i != e; ++i) 00361 if (!Sequence[i]) 00362 ++Noops; 00363 assert(!AnyNotSched); 00364 assert(Sequence.size() + DeadNodes - Noops == SUnits.size() && 00365 "The number of nodes scheduled doesn't match the expected number!"); 00366 } 00367 #endif 00368 00369 /// InitDAGTopologicalSorting - create the initial topological 00370 /// ordering from the DAG to be scheduled. 00371 /// 00372 /// The idea of the algorithm is taken from 00373 /// "Online algorithms for managing the topological order of 00374 /// a directed acyclic graph" by David J. Pearce and Paul H.J. Kelly 00375 /// This is the MNR algorithm, which was first introduced by 00376 /// A. Marchetti-Spaccamela, U. Nanni and H. Rohnert in 00377 /// "Maintaining a topological order under edge insertions". 00378 /// 00379 /// Short description of the algorithm: 00380 /// 00381 /// Topological ordering, ord, of a DAG maps each node to a topological 00382 /// index so that for all edges X->Y it is the case that ord(X) < ord(Y). 00383 /// 00384 /// This means that if there is a path from the node X to the node Z, 00385 /// then ord(X) < ord(Z). 00386 /// 00387 /// This property can be used to check for reachability of nodes: 00388 /// if Z is reachable from X, then an insertion of the edge Z->X would 00389 /// create a cycle. 00390 /// 00391 /// The algorithm first computes a topological ordering for the DAG by 00392 /// initializing the Index2Node and Node2Index arrays and then tries to keep 00393 /// the ordering up-to-date after edge insertions by reordering the DAG. 00394 /// 00395 /// On insertion of the edge X->Y, the algorithm first marks by calling DFS 00396 /// the nodes reachable from Y, and then shifts them using Shift to lie 00397 /// immediately after X in Index2Node. 00398 void ScheduleDAGTopologicalSort::InitDAGTopologicalSorting() { 00399 unsigned DAGSize = SUnits.size(); 00400 std::vector<SUnit*> WorkList; 00401 WorkList.reserve(DAGSize); 00402 00403 Index2Node.resize(DAGSize); 00404 Node2Index.resize(DAGSize); 00405 00406 // Initialize the data structures. 00407 for (unsigned i = 0, e = DAGSize; i != e; ++i) { 00408 SUnit *SU = &SUnits[i]; 00409 int NodeNum = SU->NodeNum; 00410 unsigned Degree = SU->Succs.size(); 00411 // Temporarily use the Node2Index array as scratch space for degree counts. 00412 Node2Index[NodeNum] = Degree; 00413 00414 // Is it a node without dependencies? 00415 if (Degree == 0) { 00416 assert(SU->Succs.empty() && "SUnit should have no successors"); 00417 // Collect leaf nodes. 00418 WorkList.push_back(SU); 00419 } 00420 } 00421 00422 int Id = DAGSize; 00423 while (!WorkList.empty()) { 00424 SUnit *SU = WorkList.back(); 00425 WorkList.pop_back(); 00426 Allocate(SU->NodeNum, --Id); 00427 for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); 00428 I != E; ++I) { 00429 SUnit *SU = I->getSUnit(); 00430 if (!--Node2Index[SU->NodeNum]) 00431 // If all dependencies of the node are processed already, 00432 // then the node can be computed now. 00433 WorkList.push_back(SU); 00434 } 00435 } 00436 00437 Visited.resize(DAGSize); 00438 00439 #ifndef NDEBUG 00440 // Check correctness of the ordering 00441 for (unsigned i = 0, e = DAGSize; i != e; ++i) { 00442 SUnit *SU = &SUnits[i]; 00443 for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); 00444 I != E; ++I) { 00445 assert(Node2Index[SU->NodeNum] > Node2Index[I->getSUnit()->NodeNum] && 00446 "Wrong topological sorting"); 00447 } 00448 } 00449 #endif 00450 } 00451 00452 /// AddPred - Updates the topological ordering to accomodate an edge 00453 /// to be added from SUnit X to SUnit Y. 00454 void ScheduleDAGTopologicalSort::AddPred(SUnit *Y, SUnit *X) { 00455 int UpperBound, LowerBound; 00456 LowerBound = Node2Index[Y->NodeNum]; 00457 UpperBound = Node2Index[X->NodeNum]; 00458 bool HasLoop = false; 00459 // Is Ord(X) < Ord(Y) ? 00460 if (LowerBound < UpperBound) { 00461 // Update the topological order. 00462 Visited.reset(); 00463 DFS(Y, UpperBound, HasLoop); 00464 assert(!HasLoop && "Inserted edge creates a loop!"); 00465 // Recompute topological indexes. 00466 Shift(Visited, LowerBound, UpperBound); 00467 } 00468 } 00469 00470 /// RemovePred - Updates the topological ordering to accomodate an 00471 /// an edge to be removed from the specified node N from the predecessors 00472 /// of the current node M. 00473 void ScheduleDAGTopologicalSort::RemovePred(SUnit *M, SUnit *N) { 00474 // InitDAGTopologicalSorting(); 00475 } 00476 00477 /// DFS - Make a DFS traversal to mark all nodes reachable from SU and mark 00478 /// all nodes affected by the edge insertion. These nodes will later get new 00479 /// topological indexes by means of the Shift method. 00480 void ScheduleDAGTopologicalSort::DFS(const SUnit *SU, int UpperBound, 00481 bool& HasLoop) { 00482 std::vector<const SUnit*> WorkList; 00483 WorkList.reserve(SUnits.size()); 00484 00485 WorkList.push_back(SU); 00486 do { 00487 SU = WorkList.back(); 00488 WorkList.pop_back(); 00489 Visited.set(SU->NodeNum); 00490 for (int I = SU->Succs.size()-1; I >= 0; --I) { 00491 int s = SU->Succs[I].getSUnit()->NodeNum; 00492 if (Node2Index[s] == UpperBound) { 00493 HasLoop = true; 00494 return; 00495 } 00496 // Visit successors if not already and in affected region. 00497 if (!Visited.test(s) && Node2Index[s] < UpperBound) { 00498 WorkList.push_back(SU->Succs[I].getSUnit()); 00499 } 00500 } 00501 } while (!WorkList.empty()); 00502 } 00503 00504 /// Shift - Renumber the nodes so that the topological ordering is 00505 /// preserved. 00506 void ScheduleDAGTopologicalSort::Shift(BitVector& Visited, int LowerBound, 00507 int UpperBound) { 00508 std::vector<int> L; 00509 int shift = 0; 00510 int i; 00511 00512 for (i = LowerBound; i <= UpperBound; ++i) { 00513 // w is node at topological index i. 00514 int w = Index2Node[i]; 00515 if (Visited.test(w)) { 00516 // Unmark. 00517 Visited.reset(w); 00518 L.push_back(w); 00519 shift = shift + 1; 00520 } else { 00521 Allocate(w, i - shift); 00522 } 00523 } 00524 00525 for (unsigned j = 0; j < L.size(); ++j) { 00526 Allocate(L[j], i - shift); 00527 i = i + 1; 00528 } 00529 } 00530 00531 00532 /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will 00533 /// create a cycle. 00534 bool ScheduleDAGTopologicalSort::WillCreateCycle(SUnit *SU, SUnit *TargetSU) { 00535 if (IsReachable(TargetSU, SU)) 00536 return true; 00537 for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); 00538 I != E; ++I) 00539 if (I->isAssignedRegDep() && 00540 IsReachable(TargetSU, I->getSUnit())) 00541 return true; 00542 return false; 00543 } 00544 00545 /// IsReachable - Checks if SU is reachable from TargetSU. 00546 bool ScheduleDAGTopologicalSort::IsReachable(const SUnit *SU, 00547 const SUnit *TargetSU) { 00548 // If insertion of the edge SU->TargetSU would create a cycle 00549 // then there is a path from TargetSU to SU. 00550 int UpperBound, LowerBound; 00551 LowerBound = Node2Index[TargetSU->NodeNum]; 00552 UpperBound = Node2Index[SU->NodeNum]; 00553 bool HasLoop = false; 00554 // Is Ord(TargetSU) < Ord(SU) ? 00555 if (LowerBound < UpperBound) { 00556 Visited.reset(); 00557 // There may be a path from TargetSU to SU. Check for it. 00558 DFS(TargetSU, UpperBound, HasLoop); 00559 } 00560 return HasLoop; 00561 } 00562 00563 /// Allocate - assign the topological index to the node n. 00564 void ScheduleDAGTopologicalSort::Allocate(int n, int index) { 00565 Node2Index[n] = index; 00566 Index2Node[index] = n; 00567 } 00568 00569 ScheduleDAGTopologicalSort::ScheduleDAGTopologicalSort( 00570 std::vector<SUnit> &sunits) 00571 : SUnits(sunits) {} 00572 00573 ScheduleHazardRecognizer::~ScheduleHazardRecognizer() {}