LLVM API Documentation
00001 //===---- LatencyPriorityQueue.cpp - A latency-oriented priority queue ----===// 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 file implements the LatencyPriorityQueue class, which is a 00011 // SchedulingPriorityQueue that schedules using latency information to 00012 // reduce the length of the critical path through the basic block. 00013 // 00014 //===----------------------------------------------------------------------===// 00015 00016 #define DEBUG_TYPE "scheduler" 00017 #include "llvm/CodeGen/LatencyPriorityQueue.h" 00018 #include "llvm/Support/Debug.h" 00019 #include "llvm/Support/raw_ostream.h" 00020 using namespace llvm; 00021 00022 bool latency_sort::operator()(const SUnit *LHS, const SUnit *RHS) const { 00023 // The isScheduleHigh flag allows nodes with wraparound dependencies that 00024 // cannot easily be modeled as edges with latencies to be scheduled as 00025 // soon as possible in a top-down schedule. 00026 if (LHS->isScheduleHigh && !RHS->isScheduleHigh) 00027 return false; 00028 if (!LHS->isScheduleHigh && RHS->isScheduleHigh) 00029 return true; 00030 00031 unsigned LHSNum = LHS->NodeNum; 00032 unsigned RHSNum = RHS->NodeNum; 00033 00034 // The most important heuristic is scheduling the critical path. 00035 unsigned LHSLatency = PQ->getLatency(LHSNum); 00036 unsigned RHSLatency = PQ->getLatency(RHSNum); 00037 if (LHSLatency < RHSLatency) return true; 00038 if (LHSLatency > RHSLatency) return false; 00039 00040 // After that, if two nodes have identical latencies, look to see if one will 00041 // unblock more other nodes than the other. 00042 unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum); 00043 unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum); 00044 if (LHSBlocked < RHSBlocked) return true; 00045 if (LHSBlocked > RHSBlocked) return false; 00046 00047 // Finally, just to provide a stable ordering, use the node number as a 00048 // deciding factor. 00049 return RHSNum < LHSNum; 00050 } 00051 00052 00053 /// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor 00054 /// of SU, return it, otherwise return null. 00055 SUnit *LatencyPriorityQueue::getSingleUnscheduledPred(SUnit *SU) { 00056 SUnit *OnlyAvailablePred = 0; 00057 for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); 00058 I != E; ++I) { 00059 SUnit &Pred = *I->getSUnit(); 00060 if (!Pred.isScheduled) { 00061 // We found an available, but not scheduled, predecessor. If it's the 00062 // only one we have found, keep track of it... otherwise give up. 00063 if (OnlyAvailablePred && OnlyAvailablePred != &Pred) 00064 return 0; 00065 OnlyAvailablePred = &Pred; 00066 } 00067 } 00068 00069 return OnlyAvailablePred; 00070 } 00071 00072 void LatencyPriorityQueue::push(SUnit *SU) { 00073 // Look at all of the successors of this node. Count the number of nodes that 00074 // this node is the sole unscheduled node for. 00075 unsigned NumNodesBlocking = 0; 00076 for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); 00077 I != E; ++I) { 00078 if (getSingleUnscheduledPred(I->getSUnit()) == SU) 00079 ++NumNodesBlocking; 00080 } 00081 NumNodesSolelyBlocking[SU->NodeNum] = NumNodesBlocking; 00082 00083 Queue.push_back(SU); 00084 } 00085 00086 00087 // scheduledNode - As nodes are scheduled, we look to see if there are any 00088 // successor nodes that have a single unscheduled predecessor. If so, that 00089 // single predecessor has a higher priority, since scheduling it will make 00090 // the node available. 00091 void LatencyPriorityQueue::scheduledNode(SUnit *SU) { 00092 for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); 00093 I != E; ++I) { 00094 AdjustPriorityOfUnscheduledPreds(I->getSUnit()); 00095 } 00096 } 00097 00098 /// AdjustPriorityOfUnscheduledPreds - One of the predecessors of SU was just 00099 /// scheduled. If SU is not itself available, then there is at least one 00100 /// predecessor node that has not been scheduled yet. If SU has exactly ONE 00101 /// unscheduled predecessor, we want to increase its priority: it getting 00102 /// scheduled will make this node available, so it is better than some other 00103 /// node of the same priority that will not make a node available. 00104 void LatencyPriorityQueue::AdjustPriorityOfUnscheduledPreds(SUnit *SU) { 00105 if (SU->isAvailable) return; // All preds scheduled. 00106 00107 SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU); 00108 if (OnlyAvailablePred == 0 || !OnlyAvailablePred->isAvailable) return; 00109 00110 // Okay, we found a single predecessor that is available, but not scheduled. 00111 // Since it is available, it must be in the priority queue. First remove it. 00112 remove(OnlyAvailablePred); 00113 00114 // Reinsert the node into the priority queue, which recomputes its 00115 // NumNodesSolelyBlocking value. 00116 push(OnlyAvailablePred); 00117 } 00118 00119 SUnit *LatencyPriorityQueue::pop() { 00120 if (empty()) return NULL; 00121 std::vector<SUnit *>::iterator Best = Queue.begin(); 00122 for (std::vector<SUnit *>::iterator I = llvm::next(Queue.begin()), 00123 E = Queue.end(); I != E; ++I) 00124 if (Picker(*Best, *I)) 00125 Best = I; 00126 SUnit *V = *Best; 00127 if (Best != prior(Queue.end())) 00128 std::swap(*Best, Queue.back()); 00129 Queue.pop_back(); 00130 return V; 00131 } 00132 00133 void LatencyPriorityQueue::remove(SUnit *SU) { 00134 assert(!Queue.empty() && "Queue is empty!"); 00135 std::vector<SUnit *>::iterator I = std::find(Queue.begin(), Queue.end(), SU); 00136 if (I != prior(Queue.end())) 00137 std::swap(*I, Queue.back()); 00138 Queue.pop_back(); 00139 } 00140 00141 #ifdef NDEBUG 00142 void LatencyPriorityQueue::dump(ScheduleDAG *DAG) const {} 00143 #else 00144 void LatencyPriorityQueue::dump(ScheduleDAG *DAG) const { 00145 LatencyPriorityQueue q = *this; 00146 while (!q.empty()) { 00147 SUnit *su = q.pop(); 00148 dbgs() << "Height " << su->getHeight() << ": "; 00149 su->dump(DAG); 00150 } 00151 } 00152 #endif