1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "list_scheduler.h"
17
18 namespace maplebe {
19 uint32 ListScheduler::lastSchedInsnId = 0;
20
DoListScheduling()21 void ListScheduler::DoListScheduling()
22 {
23 Init();
24
25 if (doDelayHeuristics) {
26 /* Compute delay priority of all candidates */
27 ComputeDelayPriority();
28 }
29
30 if (LIST_SCHEDULE_DUMP || isUnitTest) {
31 LogInfo::MapleLogger() << "## --- schedule bb_" << curCDGNode->GetBB()->GetId() << " ---\n\n";
32 if (doDelayHeuristics) {
33 DumpDelay();
34 }
35 LogInfo::MapleLogger() << " >> dependencies resolved: ";
36 }
37
38 // Push depNodes whose dependencies resolved into waitingQueue
39 CandidateToWaitingQueue();
40
41 ComputeEStart(currCycle);
42
43 // Iterate until the instructions in the current BB are scheduled
44 while (scheduledNodeNum < curCDGNode->GetInsnNum()) {
45 UpdateInfoBeforeSelectNode();
46
47 if (LIST_SCHEDULE_DUMP || isUnitTest) {
48 LogInfo::MapleLogger() << "\n\n '' current cycle: " << currCycle << "\n\n";
49 DumpWaitingQueue();
50 }
51
52 // Push depNodes whose resources are free from waitingQueue into readyList
53 WaitingQueueToReadyList();
54
55 if (LIST_SCHEDULE_DUMP || isUnitTest) {
56 LogInfo::MapleLogger() << " >> After waitingQueue to readyList: {";
57 DumpReadyList();
58 }
59
60 // If there are no ready insns, stall until one is ready
61 if (readyList.empty()) {
62 advancedCycle = 1;
63 continue;
64 }
65
66 CalculateMostUsedUnitKindCount();
67
68 if (!doDelayHeuristics) {
69 // Update LStart
70 ComputeLStart();
71 if (LIST_SCHEDULE_DUMP || isUnitTest) {
72 DumpEStartLStartOfAllNodes();
73 }
74 }
75
76 // Sort the readyList by priority from highest to lowest
77 SortReadyList();
78
79 if (LIST_SCHEDULE_DUMP || isUnitTest) {
80 LogInfo::MapleLogger() << " >> ReadyList after sort: {";
81 DumpReadyList();
82 }
83
84 // Select the ready node with the highest priority
85 DepNode *schedNode = *readyList.begin();
86 CHECK_FATAL(schedNode != nullptr, "select readyNode failed");
87 if (LIST_SCHEDULE_DUMP || isUnitTest) {
88 LogInfo::MapleLogger() << " >> Select node: insn_" << schedNode->GetInsn()->GetId() << "\n\n";
89 }
90
91 if (schedNode->GetInsn()->GetBB()->GetId() == curCDGNode->GetBB()->GetId()) {
92 scheduledNodeNum++;
93 }
94 UpdateInfoAfterSelectNode(*schedNode);
95 }
96 commonSchedInfo = nullptr;
97 }
98
Init()99 void ListScheduler::Init()
100 {
101 DEBUG_ASSERT(region != nullptr, "invalid region");
102 DEBUG_ASSERT(curCDGNode != nullptr, "invalid cdgNode");
103 DEBUG_ASSERT(commonSchedInfo != nullptr, "invalid common scheduling info");
104
105 mad = Globals::GetInstance()->GetMAD();
106
107 waitingQueue.clear();
108 readyList.clear();
109
110 mad->ReleaseAllUnits();
111 currCycle = 0;
112 advancedCycle = 0;
113 scheduledNodeNum = 0;
114
115 MapleVector<DepNode *> &candidates = commonSchedInfo->GetCandidates();
116 // Set the initial earliest time of all nodes to 0
117 for (auto *depNode : candidates) {
118 depNode->SetEStart(0);
119 }
120
121 lastSchedInsnId = 0;
122 }
123
CandidateToWaitingQueue()124 void ListScheduler::CandidateToWaitingQueue()
125 {
126 MapleVector<DepNode *> &candidates = commonSchedInfo->GetCandidates();
127 auto candiIter = candidates.begin();
128 while (candiIter != candidates.end()) {
129 DepNode *candiNode = *candiIter;
130 // dependencies resolved
131 if (candiNode->GetValidPredsSize() == 0) {
132 if (LIST_SCHEDULE_DUMP || isUnitTest) {
133 LogInfo::MapleLogger() << "insn_" << candiNode->GetInsn()->GetId() << ", ";
134 }
135 (void)waitingQueue.emplace_back(candiNode);
136 candiNode->SetState(kWaiting);
137 candiIter = commonSchedInfo->EraseIterFromCandidates(candiIter);
138 } else {
139 ++candiIter;
140 }
141 }
142 }
143
WaitingQueueToReadyList()144 void ListScheduler::WaitingQueueToReadyList()
145 {
146 auto waitingIter = waitingQueue.begin();
147 while (waitingIter != waitingQueue.end()) {
148 DepNode *waitingNode = *waitingIter;
149 // Just check whether the current cycle is free, because
150 // the rightmost bit of occupyTable always indicates curCycle
151 if (((cgFunc.IsAfterRegAlloc() && waitingNode->IsResourceIdle()) || !cgFunc.IsAfterRegAlloc()) &&
152 waitingNode->GetEStart() <= currCycle) {
153 (void)readyList.emplace_back(waitingNode);
154 waitingNode->SetState(kReady);
155 waitingIter = EraseIterFromWaitingQueue(waitingIter);
156 } else {
157 ++waitingIter;
158 }
159 }
160 }
161
162 static uint32 kMaxUnitIdx = 0;
163 // Sort by priority in descending order, which use LStart as algorithm of computing priority,
164 // that is the first node in list has the highest priority
CriticalPathRankScheduleInsns(const DepNode * node1,const DepNode * node2)165 bool ListScheduler::CriticalPathRankScheduleInsns(const DepNode *node1, const DepNode *node2)
166 {
167 // p as an acronym for priority
168 CompareLStart compareLStart;
169 int p1 = compareLStart(*node1, *node2);
170 if (p1 != 0) {
171 return p1 > 0;
172 }
173
174 CompareCost compareCost;
175 int p2 = compareCost(*node1, *node2);
176 if (p2 != 0) {
177 return p2 > 0;
178 }
179
180 CompareEStart compareEStart;
181 int p3 = compareEStart(*node1, *node2);
182 if (p3 != 0) {
183 return p3 > 0;
184 }
185
186 CompareSuccNodeSize compareSuccNodeSize;
187 int p4 = compareSuccNodeSize(*node1, *node2);
188 if (p4 != 0) {
189 return p4 > 0;
190 }
191
192 CompareUnitKindNum compareUnitKindNum(kMaxUnitIdx);
193 int p5 = compareUnitKindNum(*node1, *node2);
194 if (p5 != 0) {
195 return p5 > 0;
196 }
197
198 CompareSlotType compareSlotType;
199 int p6 = compareSlotType(*node1, *node2);
200 if (p6 != 0) {
201 return p6 > 0;
202 }
203
204 CompareInsnID compareInsnId;
205 int p7 = compareInsnId(*node1, *node2);
206 if (p7 != 0) {
207 return p7 > 0;
208 }
209
210 // default
211 return true;
212 }
213
UpdateInfoBeforeSelectNode()214 void ListScheduler::UpdateInfoBeforeSelectNode()
215 {
216 while (advancedCycle > 0) {
217 currCycle++;
218 // Update the occupation of cpu units
219 mad->AdvanceOneCycleForAll();
220 advancedCycle--;
221 }
222 // Fall back to the waitingQueue if the depNode in readyList has resources conflict
223 UpdateNodesInReadyList();
224 }
225
SortReadyList()226 void ListScheduler::SortReadyList()
227 {
228 // Use default rank rules
229 if (rankScheduleInsns == nullptr) {
230 if (doDelayHeuristics) {
231 std::sort(readyList.begin(), readyList.end(), DelayRankScheduleInsns);
232 } else {
233 std::sort(readyList.begin(), readyList.end(), CriticalPathRankScheduleInsns);
234 }
235 } else {
236 // Use custom rank rules
237 std::sort(readyList.begin(), readyList.end(), rankScheduleInsns);
238 }
239 }
240
UpdateEStart(DepNode & schedNode)241 void ListScheduler::UpdateEStart(DepNode &schedNode)
242 {
243 std::vector<DepNode *> traversalList;
244 (void)traversalList.emplace_back(&schedNode);
245
246 while (!traversalList.empty()) {
247 DepNode *curNode = traversalList.front();
248 traversalList.erase(traversalList.begin());
249
250 for (auto succLink : curNode->GetSuccs()) {
251 DepNode &succNode = succLink->GetTo();
252 DEBUG_ASSERT(succNode.GetState() != kScheduled, "invalid state of depNode");
253 succNode.SetEStart(std::max(succNode.GetEStart(), schedNode.GetSchedCycle() + succLink->GetLatency()));
254 maxEStart = std::max(maxEStart, succNode.GetEStart());
255 if (!succNode.GetSuccs().empty() &&
256 std::find(traversalList.begin(), traversalList.end(), &succNode) == traversalList.end()) {
257 (void)traversalList.emplace_back(&succNode);
258 }
259 }
260 }
261 }
262
UpdateInfoAfterSelectNode(DepNode & schedNode)263 void ListScheduler::UpdateInfoAfterSelectNode(DepNode &schedNode)
264 {
265 schedNode.SetState(kScheduled);
266 schedNode.SetSchedCycle(currCycle);
267 if (cgFunc.IsAfterRegAlloc()) {
268 schedNode.OccupyRequiredUnits();
269 }
270 schedNode.SetEStart(currCycle);
271 commonSchedInfo->AddSchedResults(&schedNode);
272 lastSchedInsnId = schedNode.GetInsn()->GetId();
273 lastSchedNode = &schedNode;
274 EraseNodeFromReadyList(&schedNode);
275 UpdateAdvanceCycle(schedNode);
276
277 if (LIST_SCHEDULE_DUMP || isUnitTest) {
278 LogInfo::MapleLogger() << " >> dependencies resolved: {";
279 }
280 for (auto succLink : schedNode.GetSuccs()) {
281 DepNode &succNode = succLink->GetTo();
282 succNode.DecreaseValidPredsSize();
283 // Push depNodes whose dependencies resolved from candidates into waitingQueue
284 if (succNode.GetValidPredsSize() == 0 && succNode.GetState() == kCandidate) {
285 if (LIST_SCHEDULE_DUMP || isUnitTest) {
286 LogInfo::MapleLogger() << "insn_" << succNode.GetInsn()->GetId() << ", ";
287 }
288 (void)waitingQueue.emplace_back(&succNode);
289 commonSchedInfo->EraseNodeFromCandidates(&succNode);
290 succNode.SetState(kWaiting);
291 }
292 }
293
294 UpdateEStart(schedNode);
295
296 if (LIST_SCHEDULE_DUMP || isUnitTest) {
297 LogInfo::MapleLogger() << "}\n\n";
298 DumpScheduledResult();
299 LogInfo::MapleLogger() << "'' issue insn_" << schedNode.GetInsn()->GetId() << " [ ";
300 schedNode.GetInsn()->Dump();
301 LogInfo::MapleLogger() << " ] "
302 << " at cycle " << currCycle << "\n\n";
303 }
304
305 // Add comment
306 Insn *schedInsn = schedNode.GetInsn();
307 DEBUG_ASSERT(schedInsn != nullptr, "get schedInsn from schedNode failed");
308 Reservation *res = schedNode.GetReservation();
309 DEBUG_ASSERT(res != nullptr, "get reservation of insn failed");
310 schedInsn->AppendComment(std::string("run on cycle: ")
311 .append(std::to_string(schedNode.GetSchedCycle()))
312 .append("; ")
313 .append(std::string("cost: "))
314 .append(std::to_string(res->GetLatency()))
315 .append("; "));
316 schedInsn->AppendComment(std::string("from bb: ").append(std::to_string(schedInsn->GetBB()->GetId())));
317 }
318
UpdateNodesInReadyList()319 void ListScheduler::UpdateNodesInReadyList()
320 {
321 auto readyIter = readyList.begin();
322 while (readyIter != readyList.end()) {
323 DepNode *readyNode = *readyIter;
324 CHECK_NULL_FATAL(lastSchedNode);
325 // In globalSchedule before RA, we do not consider resource conflict in pipeline
326 if ((cgFunc.IsAfterRegAlloc() && !readyNode->IsResourceIdle()) || readyNode->GetEStart() > currCycle) {
327 if (LIST_SCHEDULE_DUMP || isUnitTest) {
328 LogInfo::MapleLogger() << " >> ReadyList -> WaitingQueue: insn_" << readyNode->GetInsn()->GetId()
329 << " (resource conflict)\n\n";
330 }
331 (void)waitingQueue.emplace_back(readyNode);
332 readyNode->SetState(kWaiting);
333 readyIter = EraseIterFromReadyList(readyIter);
334 } else {
335 ++readyIter;
336 }
337 }
338 }
339
UpdateAdvanceCycle(const DepNode & schedNode)340 void ListScheduler::UpdateAdvanceCycle(const DepNode &schedNode)
341 {
342 switch (schedNode.GetInsn()->GetLatencyType()) {
343 case kLtClinit:
344 advancedCycle = kClinitAdvanceCycle;
345 break;
346 case kLtAdrpLdr:
347 advancedCycle = kAdrpLdrAdvanceCycle;
348 break;
349 case kLtClinitTail:
350 advancedCycle = kClinitTailAdvanceCycle;
351 break;
352 default:
353 break;
354 }
355
356 if (advancedCycle == 0 && mad->IsFullIssued()) {
357 advancedCycle = 1;
358 }
359 }
360
361 // Compute the delay of the depNode by postorder, which is calculated only once before scheduling,
362 // and the delay of the leaf node is initially set to 0 or execTime
ComputeDelayPriority()363 void ListScheduler::ComputeDelayPriority()
364 {
365 std::vector<DepNode *> traversalList;
366 MapleVector<DepNode *> &candidates = commonSchedInfo->GetCandidates();
367 for (auto *depNode : candidates) {
368 if (depNode->GetSuccs().empty()) { // Leaf node
369 depNode->SetDelay(static_cast<uint32>(depNode->GetReservation()->GetLatency()));
370 (void)traversalList.emplace_back(depNode);
371 } else {
372 depNode->SetDelay(0);
373 }
374 }
375
376 // Compute delay from leaf node to root node
377 while (!traversalList.empty()) {
378 DepNode *depNode = traversalList.front();
379 traversalList.erase(traversalList.begin());
380
381 for (const auto *predLink : depNode->GetPreds()) {
382 DepNode &predNode = predLink->GetFrom();
383 // Consider the cumulative effect of nodes on the critical path
384 predNode.SetDelay(std::max(predLink->GetLatency() + depNode->GetDelay(), predNode.GetDelay()));
385 maxDelay = std::max(maxDelay, predNode.GetDelay());
386 predNode.DecreaseValidSuccsSize();
387 if (predNode.GetValidSuccsSize() == 0) {
388 (void)traversalList.emplace_back(&predNode);
389 }
390 }
391 }
392 }
393
InitInfoBeforeCompEStart(uint32 cycle,std::vector<DepNode * > & traversalList)394 void ListScheduler::InitInfoBeforeCompEStart(uint32 cycle, std::vector<DepNode *> &traversalList)
395 {
396 for (CDGNode *cdgNode : region->GetRegionNodes()) {
397 for (auto *depNode : cdgNode->GetAllDataNodes()) {
398 depNode->SetTopoPredsSize(static_cast<uint32>(depNode->GetPreds().size()));
399 if (depNode->GetState() != kScheduled) {
400 depNode->SetEStart(cycle);
401 }
402 if (depNode->GetTopoPredsSize() == 0) {
403 (void)traversalList.emplace_back(depNode);
404 }
405 }
406 }
407 }
408
409 // Compute the earliest start cycle of the instruction.
410 // Regardless of whether the LStart heuristic is used, EStart always needs to be calculated,
411 // which indicates the cycles required for an insn to wait because of the resource conflict.
ComputeEStart(uint32 cycle)412 void ListScheduler::ComputeEStart(uint32 cycle)
413 {
414 std::vector<DepNode *> traversalList;
415 InitInfoBeforeCompEStart(cycle, traversalList);
416
417 // Compute the eStart of each depNode in the topology sequence
418 while (!traversalList.empty()) {
419 DepNode *depNode = traversalList.front();
420 traversalList.erase(traversalList.begin());
421
422 for (const auto *succLink : depNode->GetSuccs()) {
423 DepNode &succNode = succLink->GetTo();
424 succNode.DecreaseTopoPredsSize();
425
426 if (succNode.GetState() != kScheduled) {
427 succNode.SetEStart(std::max(depNode->GetEStart() + succLink->GetLatency(), succNode.GetEStart()));
428 }
429 maxEStart = std::max(succNode.GetEStart(), maxEStart);
430
431 if (succNode.GetTopoPredsSize() == 0) {
432 (void)traversalList.emplace_back(&succNode);
433 }
434 }
435 }
436 if (maxEStart < cycle) {
437 maxEStart = cycle;
438 }
439 }
440
InitInfoBeforeCompLStart(std::vector<DepNode * > & traversalList)441 void ListScheduler::InitInfoBeforeCompLStart(std::vector<DepNode *> &traversalList)
442 {
443 for (CDGNode *cdgNode : region->GetRegionNodes()) {
444 for (auto *depNode : cdgNode->GetAllDataNodes()) {
445 if (depNode->GetState() != kScheduled) {
446 depNode->SetLStart(maxEStart);
447 }
448 depNode->SetValidSuccsSize(static_cast<uint32>(depNode->GetSuccs().size()));
449 if (depNode->GetSuccs().empty()) {
450 (void)traversalList.emplace_back(depNode);
451 }
452 }
453 }
454 }
455
456 // Compute the latest start cycle of the instruction, which
457 // is dynamically recalculated based on the current maxEStart during scheduling.
ComputeLStart()458 void ListScheduler::ComputeLStart()
459 {
460 maxLStart = maxEStart;
461
462 MapleVector<DepNode *> &candidates = commonSchedInfo->GetCandidates();
463 if (candidates.empty() && waitingQueue.empty()) {
464 return;
465 }
466
467 // Push leaf nodes into traversalList
468 std::vector<DepNode *> traversalList;
469 InitInfoBeforeCompLStart(traversalList);
470
471 // Compute the lStart of all nodes in the topology sequence
472 while (!traversalList.empty()) {
473 DepNode *depNode = traversalList.front();
474 traversalList.erase(traversalList.begin());
475
476 for (const auto predLink : depNode->GetPreds()) {
477 DepNode &predNode = predLink->GetFrom();
478
479 if (predNode.GetState() != kScheduled) {
480 predNode.SetLStart(std::min(depNode->GetLStart() - predLink->GetLatency(), predNode.GetLStart()));
481 }
482 maxLStart = std::max(maxLStart, predNode.GetLStart());
483
484 predNode.DecreaseValidSuccsSize();
485 if (predNode.GetValidSuccsSize() == 0) {
486 traversalList.emplace_back(&predNode);
487 }
488 }
489 }
490 }
491
492 // Calculate the most used unitKind index
CalculateMostUsedUnitKindCount()493 void ListScheduler::CalculateMostUsedUnitKindCount()
494 {
495 std::array<uint32, kUnitKindLast> unitKindCount = {0};
496 for (auto *depNode : readyList) {
497 CountUnitKind(*depNode, unitKindCount);
498 }
499
500 uint32 maxCount = 0;
501 kMaxUnitIdx = 0;
502 for (uint32 i = 1; i < kUnitKindLast; ++i) {
503 if (maxCount < unitKindCount[i]) {
504 maxCount = unitKindCount[i];
505 kMaxUnitIdx = i;
506 }
507 }
508 }
509
510 // The index of unitKindCount is unitKind, the element of unitKindCount is count of the unitKind
CountUnitKind(const DepNode & depNode,std::array<uint32,kUnitKindLast> & unitKindCount) const511 void ListScheduler::CountUnitKind(const DepNode &depNode, std::array<uint32, kUnitKindLast> &unitKindCount) const
512 {
513 uint32 unitKind = depNode.GetUnitKind();
514 auto index = static_cast<uint32>(__builtin_ffs(static_cast<int>(unitKind)));
515 while (index != 0) {
516 DEBUG_ASSERT(index < kUnitKindLast, "invalid unitKind index");
517 ++unitKindCount[index];
518 unitKind &= ~(1u << (index - 1u));
519 index = static_cast<uint32>(__builtin_ffs(static_cast<int>(unitKind)));
520 }
521 }
522
DumpWaitingQueue() const523 void ListScheduler::DumpWaitingQueue() const
524 {
525 LogInfo::MapleLogger() << " >> waitingQueue: {";
526 for (uint32 i = 0; i < waitingQueue.size(); ++i) {
527 Insn *waitInsn = waitingQueue[i]->GetInsn();
528 DEBUG_ASSERT(waitInsn != nullptr, "get insn from depNode failed");
529 LogInfo::MapleLogger() << "insn_" << waitInsn->GetId();
530 CHECK_FATAL(waitingQueue.size() > 0, "must not be zero");
531 if (i != waitingQueue.size() - 1) {
532 LogInfo::MapleLogger() << ", ";
533 }
534 }
535 LogInfo::MapleLogger() << "}\n\n";
536 }
537
DumpReadyList() const538 void ListScheduler::DumpReadyList() const
539 {
540 for (uint32 i = 0; i < readyList.size(); ++i) {
541 Insn *readyInsn = readyList[i]->GetInsn();
542 DEBUG_ASSERT(readyInsn != nullptr, "get insn from depNode failed");
543 if (doDelayHeuristics) {
544 LogInfo::MapleLogger() << "insn_" << readyInsn->GetId() << "(Delay = " << readyList[i]->GetDelay() << ")";
545 } else {
546 LogInfo::MapleLogger() << "insn_" << readyInsn->GetId() << "(EStart = " << readyList[i]->GetEStart()
547 << ", LStart = " << readyList[i]->GetLStart() << ")";
548 }
549 CHECK_FATAL(readyList.size() > 0, "must not be zero");
550 if (i != readyList.size() - 1) {
551 LogInfo::MapleLogger() << ", ";
552 }
553 }
554 LogInfo::MapleLogger() << "}\n\n";
555 }
556
DumpScheduledResult() const557 void ListScheduler::DumpScheduledResult() const
558 {
559 LogInfo::MapleLogger() << " >> scheduledResult: {";
560 for (uint32 i = 0; i < commonSchedInfo->GetSchedResultsSize(); ++i) {
561 Insn *schedInsn = commonSchedInfo->GetSchedResults()[i]->GetInsn();
562 DEBUG_ASSERT(schedInsn != nullptr, "get insn from depNode failed");
563 LogInfo::MapleLogger() << "insn_" << schedInsn->GetId();
564 CHECK_FATAL(commonSchedInfo->GetSchedResultsSize() > 0, "must not be zero");
565 if (i != commonSchedInfo->GetSchedResultsSize() - 1) {
566 LogInfo::MapleLogger() << ", ";
567 }
568 }
569 LogInfo::MapleLogger() << "}\n\n";
570 }
571
DumpDelay() const572 void ListScheduler::DumpDelay() const
573 {
574 BB *curBB = curCDGNode->GetBB();
575 DEBUG_ASSERT(curBB != nullptr, "get bb from cdgNode failed");
576 LogInfo::MapleLogger() << " >> Delay priority of readyList in bb_" << curBB->GetId() << "\n";
577 LogInfo::MapleLogger() << " --------------------------------------------------------\n";
578 (void)LogInfo::MapleLogger().fill(' ');
579 LogInfo::MapleLogger() << " " << std::setiosflags(std::ios::left) << std::setw(kNumEight) << "insn"
580 << std::resetiosflags(std::ios::left) << std::setiosflags(std::ios::right)
581 << std::setw(kNumFour) << "bb" << std::resetiosflags(std::ios::right)
582 << std::setiosflags(std::ios::right) << std::setw(kNumTen) << "predDepSize"
583 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
584 << std::setw(kNumTen) << "delay" << std::resetiosflags(std::ios::right)
585 << std::setiosflags(std::ios::right) << std::setw(kNumEight) << "cost"
586 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
587 << std::setw(kNumFifteen) << "reservation" << std::resetiosflags(std::ios::right) << "\n";
588 LogInfo::MapleLogger() << " --------------------------------------------------------\n";
589 for (auto depNode : commonSchedInfo->GetCandidates()) {
590 Insn *insn = depNode->GetInsn();
591 ASSERT_NOT_NULL(insn);
592 uint32 predSize = depNode->GetValidPredsSize();
593 uint32 delay = depNode->GetDelay();
594 ASSERT_NOT_NULL(mad);
595 ASSERT_NOT_NULL(mad->FindReservation(*insn));
596 int latency = mad->FindReservation(*insn)->GetLatency();
597 LogInfo::MapleLogger() << " " << std::setiosflags(std::ios::left) << std::setw(kNumEight) << insn->GetId()
598 << std::resetiosflags(std::ios::left) << std::setiosflags(std::ios::right)
599 << std::setw(kNumFour) << curBB->GetId() << std::resetiosflags(std::ios::right)
600 << std::setiosflags(std::ios::right) << std::setw(kNumTen) << predSize
601 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
602 << std::setw(kNumTen) << delay << std::resetiosflags(std::ios::right)
603 << std::setiosflags(std::ios::right) << std::setw(kNumEight) << latency
604 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
605 << std::setw(kNumFifteen);
606 DumpReservation(*depNode);
607 LogInfo::MapleLogger() << std::resetiosflags(std::ios::right) << "\n";
608 }
609 LogInfo::MapleLogger() << " --------------------------------------------------------\n\n";
610 }
611
DumpEStartLStartOfAllNodes()612 void ListScheduler::DumpEStartLStartOfAllNodes()
613 {
614 BB *curBB = curCDGNode->GetBB();
615 DEBUG_ASSERT(curBB != nullptr, "get bb from cdgNode failed");
616 LogInfo::MapleLogger() << " >> max EStart: " << maxEStart << "\n\n";
617 LogInfo::MapleLogger() << " >> CP priority of readyList in bb_" << curBB->GetId() << "\n";
618 LogInfo::MapleLogger() << " --------------------------------------------------------------------------\n";
619 (void)LogInfo::MapleLogger().fill(' ');
620 LogInfo::MapleLogger() << " " << std::setiosflags(std::ios::left) << std::setw(kNumEight) << "insn"
621 << std::resetiosflags(std::ios::left) << std::setiosflags(std::ios::right)
622 << std::setw(kNumFour) << "bb" << std::resetiosflags(std::ios::right)
623 << std::setiosflags(std::ios::right) << std::setw(kNumEight) << "state"
624 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
625 << std::setw(kNumTwelve) << "predDepSize" << std::resetiosflags(std::ios::right)
626 << std::setiosflags(std::ios::right) << std::setw(kNumTen) << "EStart"
627 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
628 << std::setw(kNumTen) << "LStart" << std::resetiosflags(std::ios::right)
629 << std::setiosflags(std::ios::right) << std::setw(kNumEight) << "cost"
630 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
631 << std::setw(kNumFifteen) << "reservation" << std::resetiosflags(std::ios::right) << "\n";
632 LogInfo::MapleLogger() << " --------------------------------------------------------------------------\n";
633 DumpDepNodeInfo(*curBB, commonSchedInfo->GetCandidates(), "candi");
634 DumpDepNodeInfo(*curBB, waitingQueue, "wait");
635 DumpDepNodeInfo(*curBB, readyList, "ready");
636 LogInfo::MapleLogger() << " --------------------------------------------------------------------------\n\n";
637 }
638
DumpDepNodeInfo(const BB & curBB,MapleVector<DepNode * > & nodes,const std::string state) const639 void ListScheduler::DumpDepNodeInfo(const BB &curBB, MapleVector<DepNode *> &nodes, const std::string state) const
640 {
641 for (auto depNode : nodes) {
642 Insn *insn = depNode->GetInsn();
643 DEBUG_ASSERT(insn != nullptr, "get insn from depNode failed");
644 uint32 predSize = depNode->GetValidPredsSize();
645 uint32 eStart = depNode->GetEStart();
646 uint32 lStart = depNode->GetLStart();
647 ASSERT_NOT_NULL(mad->FindReservation(*insn));
648 int latency = mad->FindReservation(*insn)->GetLatency();
649 (void)LogInfo::MapleLogger().fill(' ');
650 LogInfo::MapleLogger() << " " << std::setiosflags(std::ios::left) << std::setw(kNumEight) << insn->GetId()
651 << std::resetiosflags(std::ios::left) << std::setiosflags(std::ios::right)
652 << std::setw(kNumFour) << curBB.GetId() << std::resetiosflags(std::ios::right)
653 << std::setiosflags(std::ios::right) << std::setw(kNumEight) << state
654 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
655 << std::setw(kNumTwelve) << predSize << std::resetiosflags(std::ios::right)
656 << std::setiosflags(std::ios::right) << std::setw(kNumTen) << eStart
657 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
658 << std::setw(kNumTen) << lStart << std::resetiosflags(std::ios::right)
659 << std::setiosflags(std::ios::right) << std::setw(kNumEight) << latency
660 << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::right)
661 << std::setw(kNumFour) << " ";
662 DumpReservation(*depNode);
663 LogInfo::MapleLogger() << std::resetiosflags(std::ios::right) << "\n";
664 }
665 }
666
DumpReservation(const DepNode & depNode) const667 void ListScheduler::DumpReservation(const DepNode &depNode) const
668 {
669 for (uint32 i = 0; i < depNode.GetUnitNum(); ++i) {
670 UnitId unitId = depNode.GetUnitByIndex(i)->GetUnitId();
671 switch (unitId) {
672 case kUnitIdSlot0:
673 LogInfo::MapleLogger() << "slot0";
674 break;
675 case kUnitIdSlot1:
676 LogInfo::MapleLogger() << "slot1";
677 break;
678 case kUnitIdAgen:
679 LogInfo::MapleLogger() << "agen";
680 break;
681 case kUnitIdHazard:
682 LogInfo::MapleLogger() << "hazard";
683 break;
684 case kUnitIdCrypto:
685 LogInfo::MapleLogger() << "crypto";
686 break;
687 case kUnitIdMul:
688 LogInfo::MapleLogger() << "mul";
689 break;
690 case kUnitIdDiv:
691 LogInfo::MapleLogger() << "div";
692 break;
693 case kUnitIdBranch:
694 LogInfo::MapleLogger() << "branch";
695 break;
696 case kUnitIdStAgu:
697 LogInfo::MapleLogger() << "stAgu";
698 break;
699 case kUnitIdLdAgu:
700 LogInfo::MapleLogger() << "ldAgu";
701 break;
702 case kUnitIdFpAluLo:
703 LogInfo::MapleLogger() << "fpAluLo";
704 break;
705 case kUnitIdFpAluHi:
706 LogInfo::MapleLogger() << "fpAluHi";
707 break;
708 case kUnitIdFpMulLo:
709 LogInfo::MapleLogger() << "fpMulLo";
710 break;
711 case kUnitIdFpMulHi:
712 LogInfo::MapleLogger() << "fpMulHi";
713 break;
714 case kUnitIdFpDivLo:
715 LogInfo::MapleLogger() << "fpDivLo";
716 break;
717 case kUnitIdFpDivHi:
718 LogInfo::MapleLogger() << "fpDivHi";
719 break;
720 case kUnitIdSlotS:
721 LogInfo::MapleLogger() << "slot0 | slot1";
722 break;
723 case kUnitIdFpAluS:
724 LogInfo::MapleLogger() << "fpAluLo | fpAluHi";
725 break;
726 case kUnitIdFpMulS:
727 LogInfo::MapleLogger() << "fpMulLo | fpMulHi";
728 break;
729 case kUnitIdFpDivS:
730 LogInfo::MapleLogger() << "fpDivLo | fpDivHi";
731 break;
732 case kUnitIdSlotD:
733 LogInfo::MapleLogger() << "slot0 & slot1";
734 break;
735 case kUnitIdFpAluD:
736 LogInfo::MapleLogger() << "fpAluLo & fpAluHi";
737 break;
738 case kUnitIdFpMulD:
739 LogInfo::MapleLogger() << "fpMulLo & fpMulHi";
740 break;
741 case kUnitIdFpDivD:
742 LogInfo::MapleLogger() << "fpMulLo & fpMulHi";
743 break;
744 case kUnitIdSlotSHazard:
745 LogInfo::MapleLogger() << "(slot0 | slot1) & hazard";
746 break;
747 case kUnitIdSlotSMul:
748 LogInfo::MapleLogger() << "(slot0 | slot1) & mul";
749 break;
750 case kUnitIdSlotSBranch:
751 LogInfo::MapleLogger() << "(slot0 | slot1) & branch";
752 break;
753 case kUnitIdSlotSAgen:
754 LogInfo::MapleLogger() << "(slot0 | slot1) & agen";
755 break;
756 case kUnitIdSlotDAgen:
757 LogInfo::MapleLogger() << "slot0 & slot1 & agen";
758 break;
759 case kUnitIdSlot0LdAgu:
760 LogInfo::MapleLogger() << "slot0 & ldAgu";
761 break;
762 case kUnitIdSlot0StAgu:
763 LogInfo::MapleLogger() << "slot0 & stAgu";
764 break;
765 default:
766 LogInfo::MapleLogger() << "unknown";
767 break;
768 }
769 if (i != depNode.GetUnitNum() - 1) {
770 LogInfo::MapleLogger() << ", ";
771 }
772 }
773 }
774 } // namespace maplebe
775