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 #ifndef MAPLEBE_INCLUDE_CG_CGBB_H
17 #define MAPLEBE_INCLUDE_CG_CGBB_H
18
19 #include "isa.h"
20 #include "insn.h"
21 #include "sparse_datainfo.h"
22
23 /* Maple IR headers */
24 #include "mir_nodes.h"
25 #include "mir_symbol.h"
26
27 /* Maple MP header */
28 #include "mempool_allocator.h"
29 #include "maple_phase_manager.h"
30 #include "base_graph_node.h"
31
32 namespace maplebe {
33 /* For get bb */
34 #define FIRST_BB_OF_FUNC(FUNC) ((FUNC)->GetFirstBB())
35 #define LAST_BB_OF_FUNC(FUNC) ((FUNC)->GetLastBB())
36
37 /* For iterating over basic blocks. */
38 #define FOR_BB_BETWEEN(BASE, FROM, TO, DIR) for (BB * (BASE) = (FROM); (BASE) != (TO); (BASE) = (BASE)->DIR())
39 #define FOR_BB_BETWEEN_CONST(BASE, FROM, TO, DIR) \
40 for (const BB *(BASE) = (FROM); (BASE) != (TO); (BASE) = (BASE)->DIR())
41
42 #define FOR_ALL_BB_CONST(BASE, FUNC) FOR_BB_BETWEEN_CONST(BASE, FIRST_BB_OF_FUNC(FUNC), nullptr, GetNext)
43 #define FOR_ALL_BB(BASE, FUNC) FOR_BB_BETWEEN(BASE, FIRST_BB_OF_FUNC(FUNC), nullptr, GetNext)
44 #define FOR_ALL_BB_REV(BASE, FUNC) FOR_BB_BETWEEN(BASE, LAST_BB_OF_FUNC(FUNC), nullptr, GetPrev)
45
46 /* For get insn */
47 #define FIRST_INSN(BLOCK) (BLOCK)->GetFirstInsn()
48 #define LAST_INSN(BLOCK) (BLOCK)->GetLastInsn()
49 #define NEXT_INSN(INSN) (INSN)->GetNext()
50 #define PREV_INSN(INSN) (INSN)->GetPrev()
51
52 /* For iterating over insns in basic block. */
53 #define FOR_INSN_BETWEEN(INSN, FROM, TO, DIR) \
54 for (Insn * (INSN) = (FROM); (INSN) != nullptr && (INSN) != (TO); (INSN) = (INSN)->DIR)
55
56 #define FOR_BB_INSNS(INSN, BLOCK) for (Insn * (INSN) = FIRST_INSN(BLOCK); (INSN) != nullptr; (INSN) = (INSN)->GetNext())
57 #define FOR_BB_INSNS_CONST(INSN, BLOCK) \
58 for (const Insn *(INSN) = FIRST_INSN(BLOCK); (INSN) != nullptr; (INSN) = (INSN)->GetNext())
59
60 #define FOR_BB_INSNS_REV(INSN, BLOCK) \
61 for (Insn * (INSN) = LAST_INSN(BLOCK); (INSN) != nullptr; (INSN) = (INSN)->GetPrev())
62 #define FOR_BB_INSNS_REV_CONST(INSN, BLOCK) \
63 for (const Insn *(INSN) = LAST_INSN(BLOCK); (INSN) != nullptr; (INSN) = (INSN)->GetPrev())
64
65 /* For iterating over insns in basic block when we might remove the current insn. */
66 #define FOR_BB_INSNS_SAFE(INSN, BLOCK, NEXT) \
67 for (Insn * (INSN) = FIRST_INSN(BLOCK), *(NEXT) = (INSN) ? NEXT_INSN(INSN) : nullptr; (INSN) != nullptr; \
68 (INSN) = (NEXT), (NEXT) = (INSN) ? NEXT_INSN(INSN) : nullptr)
69
70 #define FOR_BB_INSNS_REV_SAFE(INSN, BLOCK, NEXT) \
71 for (Insn * (INSN) = LAST_INSN(BLOCK), *(NEXT) = (INSN) ? PREV_INSN(INSN) : nullptr; (INSN) != nullptr; \
72 (INSN) = (NEXT), (NEXT) = (INSN) ? PREV_INSN(INSN) : nullptr)
73
74 class CGFunc;
75 class CDGNode;
76
77 using BBID = uint32;
78
79 class BB : public maple::BaseGraphNode {
80 public:
81 static constexpr int32 kUnknownProb = -1;
82 static constexpr uint32 kBBIfSuccsSize = 2;
83 enum BBKind : uint8 {
84 kBBFallthru, /* default */
85 kBBIf, /* conditional branch */
86 kBBGoto, /* unconditional branch */
87 kBBReturn,
88 kBBNoReturn,
89 kBBRangeGoto,
90 kBBLast
91 };
92
BB(BBID bbID,MapleAllocator & mallocator)93 BB(BBID bbID, MapleAllocator &mallocator)
94 : id(bbID),
95 kind(kBBFallthru), /* kBBFallthru default kind */
96 labIdx(MIRLabelTable::GetDummyLabel()),
97 preds(mallocator.Adapter()),
98 succs(mallocator.Adapter()),
99 succsProb(mallocator.Adapter()),
100 liveInRegNO(mallocator.Adapter()),
101 liveOutRegNO(mallocator.Adapter()),
102 callInsns(mallocator.Adapter()),
103 rangeGotoLabelVec(mallocator.Adapter()),
104 phiInsnList(mallocator.Adapter())
105 {
106 }
107
108 virtual ~BB() = default;
109
Clone(MemPool & memPool)110 virtual BB *Clone(MemPool &memPool) const
111 {
112 BB *bb = memPool.Clone<BB>(*this);
113 return bb;
114 }
115
116 void Dump() const;
117 bool IsCommentBB() const;
118 bool IsEmptyOrCommentOnly() const;
119 bool IsSoloGoto() const;
120
IsEmpty()121 bool IsEmpty() const
122 {
123 if (lastInsn == nullptr) {
124 CHECK_FATAL(firstInsn == nullptr, "firstInsn must be nullptr");
125 return true;
126 } else {
127 CHECK_FATAL(firstInsn != nullptr, "firstInsn must not be nullptr");
128 return false;
129 }
130 }
131
GetKindName()132 const std::string &GetKindName() const
133 {
134 DEBUG_ASSERT(kind < kBBLast, "out of range in GetKindName");
135 return bbNames[kind];
136 }
137
SetKind(BBKind bbKind)138 void SetKind(BBKind bbKind)
139 {
140 kind = bbKind;
141 }
142
GetKind()143 BBKind GetKind() const
144 {
145 return kind;
146 }
147
AddLabel(LabelIdx idx)148 void AddLabel(LabelIdx idx)
149 {
150 labIdx = idx;
151 }
152
AppendBB(BB & bb)153 void AppendBB(BB &bb)
154 {
155 bb.prev = this;
156 bb.next = next;
157 if (next != nullptr) {
158 next->prev = &bb;
159 }
160 succsProb[&bb] = kUnknownProb;
161 next = &bb;
162 }
163
PrependBB(BB & bb)164 void PrependBB(BB &bb)
165 {
166 bb.next = this;
167 bb.prev = this->prev;
168 if (this->prev != nullptr) {
169 this->prev->next = &bb;
170 }
171 this->prev = &bb;
172 succsProb[&bb] = kUnknownProb;
173 }
174
175 Insn *InsertInsnBefore(Insn &existing, Insn &newInsn);
176
177 /* returns newly inserted instruction */
178 Insn *InsertInsnAfter(Insn &existing, Insn &newInsn);
179
InsertInsnBegin(Insn & insn)180 void InsertInsnBegin(Insn &insn)
181 {
182 if (lastInsn == nullptr) {
183 firstInsn = lastInsn = &insn;
184 insn.SetNext(nullptr);
185 insn.SetPrev(nullptr);
186 insn.SetBB(this);
187 } else {
188 InsertInsnBefore(*firstInsn, insn);
189 }
190 }
191
AppendInsn(Insn & insn)192 void AppendInsn(Insn &insn)
193 {
194 if (firstInsn != nullptr && lastInsn != nullptr) {
195 InsertInsnAfter(*lastInsn, insn);
196 } else {
197 firstInsn = lastInsn = &insn;
198 insn.SetNext(nullptr);
199 insn.SetPrev(nullptr);
200 insn.SetBB(this);
201 }
202 internalFlag1++;
203 }
204
205 void ReplaceInsn(Insn &insn, Insn &newInsn);
206
207 void RemoveInsn(Insn &insn);
208
209 void RemoveInsnSequence(Insn &insn, const Insn &nextInsn);
210
211 /* append all insns from bb into this bb */
212 void AppendBBInsns(BB &bb);
213
214 /* append all insns from bb into this bb */
215 void InsertAtBeginning(BB &bb);
216 void InsertAtEnd(BB &bb);
217
218 /* clear BB but don't remove insns of this */
ClearInsns()219 void ClearInsns()
220 {
221 firstInsn = lastInsn = nullptr;
222 }
223
NumPreds()224 uint32 NumPreds() const
225 {
226 return static_cast<uint32>(preds.size());
227 }
228
IsPredecessor(const BB & predBB)229 bool IsPredecessor(const BB &predBB)
230 {
231 for (const BB *bb : preds) {
232 if (bb == &predBB) {
233 return true;
234 }
235 }
236 return false;
237 }
238
RemoveFromPredecessorList(const BB & bb)239 void RemoveFromPredecessorList(const BB &bb)
240 {
241 for (auto i = preds.begin(); i != preds.end(); ++i) {
242 if (*i == &bb) {
243 preds.erase(i);
244 return;
245 }
246 }
247 CHECK_FATAL(false, "request to remove a non-existent element?");
248 }
249
RemoveFromSuccessorList(const BB & bb)250 void RemoveFromSuccessorList(const BB &bb)
251 {
252 for (auto i = succs.begin(); i != succs.end(); ++i) {
253 if (*i == &bb) {
254 succs.erase(i);
255 succsProb.erase(&bb);
256 return;
257 }
258 }
259 CHECK_FATAL(false, "request to remove a non-existent element?");
260 }
261
NumSuccs()262 uint32 NumSuccs() const
263 {
264 return static_cast<uint32>(succs.size());
265 }
266
HasCall()267 bool HasCall() const
268 {
269 return hasCall;
270 }
271
SetHasCall()272 void SetHasCall()
273 {
274 hasCall = true;
275 }
276
277 /* Number of instructions excluding DbgInsn and comments */
278 int32 NumInsn() const;
GetId()279 uint32 GetId() const
280 {
281 return id;
282 }
GetID()283 uint32 GetID() const
284 {
285 return id;
286 }
GetLevel()287 uint32 GetLevel() const
288 {
289 return level;
290 }
SetLevel(uint32 arg)291 void SetLevel(uint32 arg)
292 {
293 level = arg;
294 }
GetFrequency()295 uint32 GetFrequency() const
296 {
297 return frequency;
298 }
SetFrequency(uint32 arg)299 void SetFrequency(uint32 arg)
300 {
301 frequency = arg;
302 }
IsInColdSection()303 bool IsInColdSection() const
304 {
305 return inColdSection;
306 }
SetColdSection()307 void SetColdSection()
308 {
309 inColdSection = true;
310 }
GetNext()311 BB *GetNext()
312 {
313 return next;
314 }
GetNext()315 const BB *GetNext() const
316 {
317 return next;
318 }
GetPrev()319 BB *GetPrev()
320 {
321 return prev;
322 }
GetPrev()323 const BB *GetPrev() const
324 {
325 return prev;
326 }
SetNext(BB * arg)327 void SetNext(BB *arg)
328 {
329 next = arg;
330 }
SetPrev(BB * arg)331 void SetPrev(BB *arg)
332 {
333 prev = arg;
334 }
GetLabIdx()335 LabelIdx GetLabIdx() const
336 {
337 return labIdx;
338 }
SetLabIdx(LabelIdx arg)339 void SetLabIdx(LabelIdx arg)
340 {
341 labIdx = arg;
342 }
GetFirstStmt()343 StmtNode *GetFirstStmt()
344 {
345 return firstStmt;
346 }
GetFirstStmt()347 const StmtNode *GetFirstStmt() const
348 {
349 return firstStmt;
350 }
SetFirstStmt(StmtNode & arg)351 void SetFirstStmt(StmtNode &arg)
352 {
353 firstStmt = &arg;
354 }
GetLastStmt()355 StmtNode *GetLastStmt()
356 {
357 return lastStmt;
358 }
GetLastStmt()359 const StmtNode *GetLastStmt() const
360 {
361 return lastStmt;
362 }
SetLastStmt(StmtNode & arg)363 void SetLastStmt(StmtNode &arg)
364 {
365 lastStmt = &arg;
366 }
GetFirstInsn()367 Insn *GetFirstInsn()
368 {
369 return firstInsn;
370 }
GetFirstInsn()371 const Insn *GetFirstInsn() const
372 {
373 return firstInsn;
374 }
375
SetFirstInsn(Insn * arg)376 void SetFirstInsn(Insn *arg)
377 {
378 firstInsn = arg;
379 }
GetFirstMachineInsn()380 Insn *GetFirstMachineInsn()
381 {
382 FOR_BB_INSNS(insn, this) {
383 if (insn->IsMachineInstruction()) {
384 return insn;
385 }
386 }
387 return nullptr;
388 }
389
GetFirstMachineInsn()390 const Insn *GetFirstMachineInsn() const
391 {
392 FOR_BB_INSNS_CONST(insn, this) {
393 if (insn->IsMachineInstruction()) {
394 return insn;
395 }
396 }
397 return nullptr;
398 }
399
GetLastMachineInsn()400 Insn *GetLastMachineInsn()
401 {
402 FOR_BB_INSNS_REV(insn, this) {
403 if (insn->IsMachineInstruction() && !insn->IsPseudo()) {
404 return insn;
405 }
406 }
407 return nullptr;
408 }
409
GetLastMachineInsn()410 const Insn *GetLastMachineInsn() const
411 {
412 FOR_BB_INSNS_REV_CONST(insn, this) {
413 if (insn->IsMachineInstruction() && !insn->IsPseudo()) {
414 return insn;
415 }
416 }
417 return nullptr;
418 }
419
GetLastInsn()420 Insn *GetLastInsn()
421 {
422 return lastInsn;
423 }
GetLastInsn()424 const Insn *GetLastInsn() const
425 {
426 return lastInsn;
427 }
SetLastInsn(Insn * arg)428 void SetLastInsn(Insn *arg)
429 {
430 lastInsn = arg;
431 }
IsLastInsn(const Insn * insn)432 bool IsLastInsn(const Insn *insn) const
433 {
434 return (lastInsn == insn);
435 }
InsertPred(const MapleList<BB * >::iterator & it,BB & bb)436 void InsertPred(const MapleList<BB *>::iterator &it, BB &bb)
437 {
438 preds.insert(it, &bb);
439 }
440 void InsertSucc(const MapleList<BB *>::iterator &it, BB &bb, int32 prob = kUnknownProb)
441 {
442 succs.insert(it, &bb);
443 succsProb[&bb] = prob;
444 }
GetPreds()445 const MapleList<BB *> &GetPreds() const
446 {
447 return preds;
448 }
GetPredsSize()449 std::size_t GetPredsSize() const
450 {
451 return preds.size();
452 }
GetSuccs()453 const MapleList<BB *> &GetSuccs() const
454 {
455 return succs;
456 }
GetSuccsSize()457 std::size_t GetSuccsSize() const
458 {
459 return succs.size();
460 }
461
462 // override interface of BaseGraphNode
GetIdentity()463 const std::string GetIdentity() final
464 {
465 return "BBId: " + std::to_string(GetID());
466 }
GetOutNodes(std::vector<BaseGraphNode * > & outNodes)467 void GetOutNodes(std::vector<BaseGraphNode *> &outNodes) const final
468 {
469 outNodes.resize(succs.size(), nullptr);
470 std::copy(succs.begin(), succs.end(), outNodes.begin());
471 }
472
GetOutNodes(std::vector<BaseGraphNode * > & outNodes)473 void GetOutNodes(std::vector<BaseGraphNode *> &outNodes) final
474 {
475 static_cast<const BB *>(this)->GetOutNodes(outNodes);
476 }
477
GetInNodes(std::vector<BaseGraphNode * > & inNodes)478 void GetInNodes(std::vector<BaseGraphNode *> &inNodes) const final
479 {
480 inNodes.resize(preds.size(), nullptr);
481 std::copy(preds.begin(), preds.end(), inNodes.begin());
482 }
483
GetInNodes(std::vector<BaseGraphNode * > & inNodes)484 void GetInNodes(std::vector<BaseGraphNode *> &inNodes) final
485 {
486 static_cast<const BB *>(this)->GetInNodes(inNodes);
487 }
GetPredsBegin()488 MapleList<BB *>::iterator GetPredsBegin()
489 {
490 return preds.begin();
491 }
GetSuccsBegin()492 MapleList<BB *>::iterator GetSuccsBegin()
493 {
494 return succs.begin();
495 }
GetPredsEnd()496 MapleList<BB *>::iterator GetPredsEnd()
497 {
498 return preds.end();
499 }
GetSuccsEnd()500 MapleList<BB *>::iterator GetSuccsEnd()
501 {
502 return succs.end();
503 }
PushBackPreds(BB & bb)504 void PushBackPreds(BB &bb)
505 {
506 preds.push_back(&bb);
507 }
508 void PushBackSuccs(BB &bb, int32 prob = kUnknownProb)
509 {
510 succs.push_back(&bb);
511 succsProb[&bb] = prob;
512 }
PushFrontPreds(BB & bb)513 void PushFrontPreds(BB &bb)
514 {
515 preds.push_front(&bb);
516 }
517 void PushFrontSuccs(BB &bb, int32 prob = kUnknownProb)
518 {
519 succs.push_front(&bb);
520 succsProb[&bb] = prob;
521 }
ErasePreds(MapleList<BB * >::iterator it)522 void ErasePreds(MapleList<BB *>::iterator it)
523 {
524 preds.erase(it);
525 }
EraseSuccs(MapleList<BB * >::const_iterator it)526 void EraseSuccs(MapleList<BB *>::const_iterator it)
527 {
528 succs.erase(it);
529 }
RemovePreds(BB & bb)530 void RemovePreds(BB &bb)
531 {
532 preds.remove(&bb);
533 }
RemoveSuccs(BB & bb)534 void RemoveSuccs(BB &bb)
535 {
536 succs.remove(&bb);
537 succsProb.erase(&bb);
538 }
ReplaceSucc(const MapleList<BB * >::const_iterator it,BB & newBB)539 void ReplaceSucc(const MapleList<BB *>::const_iterator it, BB &newBB)
540 {
541 int prob = succsProb[*it];
542 EraseSuccs(it);
543 PushBackSuccs(newBB, prob);
544 }
545
ReplaceSucc(BB & oldBB,BB & newBB)546 void ReplaceSucc(BB &oldBB, BB &newBB)
547 {
548 int prob = succsProb[&oldBB];
549 RemoveSuccs(oldBB);
550 PushBackSuccs(newBB, prob);
551 }
ClearPreds()552 void ClearPreds()
553 {
554 preds.clear();
555 }
ClearSuccs()556 void ClearSuccs()
557 {
558 succs.clear();
559 succsProb.clear();
560 }
GetLiveInRegNO()561 const MapleSet<regno_t> &GetLiveInRegNO() const
562 {
563 return liveInRegNO;
564 }
GetLiveInRegNO()565 MapleSet<regno_t> &GetLiveInRegNO()
566 {
567 return liveInRegNO;
568 }
InsertLiveInRegNO(regno_t arg)569 void InsertLiveInRegNO(regno_t arg)
570 {
571 (void)liveInRegNO.insert(arg);
572 }
EraseLiveInRegNO(MapleSet<regno_t>::iterator it)573 void EraseLiveInRegNO(MapleSet<regno_t>::iterator it)
574 {
575 liveInRegNO.erase(it);
576 }
EraseLiveInRegNO(regno_t arg)577 void EraseLiveInRegNO(regno_t arg)
578 {
579 liveInRegNO.erase(arg);
580 }
ClearLiveInRegNO()581 void ClearLiveInRegNO()
582 {
583 liveInRegNO.clear();
584 }
GetLiveOutRegNO()585 const MapleSet<regno_t> &GetLiveOutRegNO() const
586 {
587 return liveOutRegNO;
588 }
GetLiveOutRegNO()589 MapleSet<regno_t> &GetLiveOutRegNO()
590 {
591 return liveOutRegNO;
592 }
InsertLiveOutRegNO(regno_t arg)593 void InsertLiveOutRegNO(regno_t arg)
594 {
595 (void)liveOutRegNO.insert(arg);
596 }
EraseLiveOutRegNO(MapleSet<regno_t>::iterator it)597 void EraseLiveOutRegNO(MapleSet<regno_t>::iterator it)
598 {
599 liveOutRegNO.erase(it);
600 }
ClearLiveOutRegNO()601 void ClearLiveOutRegNO()
602 {
603 liveOutRegNO.clear();
604 }
GetLiveInChange()605 bool GetLiveInChange() const
606 {
607 return liveInChange;
608 }
SetLiveInChange(bool arg)609 void SetLiveInChange(bool arg)
610 {
611 liveInChange = arg;
612 }
GetCritical()613 bool GetCritical() const
614 {
615 return isCritical;
616 }
SetCritical(bool arg)617 void SetCritical(bool arg)
618 {
619 isCritical = arg;
620 }
GetInsertUse()621 bool GetInsertUse() const
622 {
623 return insertUse;
624 }
SetInsertUse(bool arg)625 void SetInsertUse(bool arg)
626 {
627 insertUse = arg;
628 }
IsUnreachable()629 bool IsUnreachable() const
630 {
631 return unreachable;
632 }
SetUnreachable(bool arg)633 void SetUnreachable(bool arg)
634 {
635 unreachable = arg;
636 }
IsWontExit()637 bool IsWontExit() const
638 {
639 return wontExit;
640 }
SetWontExit(bool arg)641 void SetWontExit(bool arg)
642 {
643 wontExit = arg;
644 }
SetFastPath(bool arg)645 void SetFastPath(bool arg)
646 {
647 fastPath = arg;
648 }
IsCatch()649 bool IsCatch() const
650 {
651 return isCatch;
652 }
SetIsCatch(bool arg)653 void SetIsCatch(bool arg)
654 {
655 isCatch = arg;
656 }
IsCleanup()657 bool IsCleanup() const
658 {
659 return isCleanup;
660 }
SetIsCleanup(bool arg)661 void SetIsCleanup(bool arg)
662 {
663 isCleanup = arg;
664 }
IsProEpilog()665 bool IsProEpilog() const
666 {
667 return isProEpilog;
668 }
SetIsProEpilog(bool arg)669 void SetIsProEpilog(bool arg)
670 {
671 isProEpilog = arg;
672 }
IsLabelTaken()673 bool IsLabelTaken() const
674 {
675 return labelTaken;
676 }
SetLabelTaken()677 void SetLabelTaken()
678 {
679 labelTaken = true;
680 }
GetHasCfi()681 bool GetHasCfi() const
682 {
683 return hasCfi;
684 }
SetHasCfi()685 void SetHasCfi()
686 {
687 hasCfi = true;
688 }
GetInternalFlag1()689 long GetInternalFlag1() const
690 {
691 return internalFlag1;
692 }
SetInternalFlag1(long arg)693 void SetInternalFlag1(long arg)
694 {
695 internalFlag1 = arg;
696 }
GetInternalFlag2()697 long GetInternalFlag2() const
698 {
699 return internalFlag2;
700 }
SetInternalFlag2(long arg)701 void SetInternalFlag2(long arg)
702 {
703 internalFlag2 = arg;
704 }
GetInternalFlag3()705 long GetInternalFlag3() const
706 {
707 return internalFlag3;
708 }
SetInternalFlag3(long arg)709 void SetInternalFlag3(long arg)
710 {
711 internalFlag3 = arg;
712 }
IsAtomicBuiltInBB()713 bool IsAtomicBuiltInBB() const
714 {
715 return isAtomicBuiltIn;
716 }
SetAtomicBuiltIn()717 void SetAtomicBuiltIn()
718 {
719 isAtomicBuiltIn = true;
720 }
GetCallInsns()721 const MapleList<Insn *> &GetCallInsns() const
722 {
723 return callInsns;
724 }
PushBackCallInsns(Insn & insn)725 void PushBackCallInsns(Insn &insn)
726 {
727 callInsns.push_back(&insn);
728 }
ClearCallInsns()729 void ClearCallInsns()
730 {
731 callInsns.clear();
732 }
GetRangeGotoLabelVec()733 const MapleVector<LabelIdx> &GetRangeGotoLabelVec() const
734 {
735 return rangeGotoLabelVec;
736 }
SetRangeGotoLabel(uint32 index,LabelIdx labelIdx)737 void SetRangeGotoLabel(uint32 index, LabelIdx labelIdx)
738 {
739 rangeGotoLabelVec[index] = labelIdx;
740 }
PushBackRangeGotoLabel(LabelIdx labelIdx)741 void PushBackRangeGotoLabel(LabelIdx labelIdx)
742 {
743 rangeGotoLabelVec.emplace_back(labelIdx);
744 }
AddPhiInsn(regno_t regNO,Insn & insn)745 void AddPhiInsn(regno_t regNO, Insn &insn)
746 {
747 DEBUG_ASSERT(!phiInsnList.count(regNO), "repeat phiInsn");
748 phiInsnList.emplace(std::pair<regno_t, Insn *>(regNO, &insn));
749 }
RemovePhiInsn(regno_t regNO)750 void RemovePhiInsn(regno_t regNO)
751 {
752 DEBUG_ASSERT(phiInsnList.count(regNO), "no such insn");
753 phiInsnList.erase(regNO);
754 }
HasPhiInsn(regno_t regNO)755 bool HasPhiInsn(regno_t regNO)
756 {
757 return phiInsnList.find(regNO) != phiInsnList.end();
758 }
GetPhiInsns()759 MapleMap<regno_t, Insn *> &GetPhiInsns()
760 {
761 return phiInsnList;
762 }
GetFirstLoc()763 const Insn *GetFirstLoc() const
764 {
765 return firstLoc;
766 }
SetFirstLoc(const Insn & arg)767 void SetFirstLoc(const Insn &arg)
768 {
769 firstLoc = &arg;
770 }
GetLastLoc()771 const Insn *GetLastLoc() const
772 {
773 return lastLoc;
774 }
SetLastLoc(const Insn * arg)775 void SetLastLoc(const Insn *arg)
776 {
777 lastLoc = arg;
778 }
GetLiveIn()779 SparseDataInfo *GetLiveIn()
780 {
781 return liveIn;
782 }
GetLiveIn()783 const SparseDataInfo *GetLiveIn() const
784 {
785 return liveIn;
786 }
SetLiveIn(SparseDataInfo & arg)787 void SetLiveIn(SparseDataInfo &arg)
788 {
789 liveIn = &arg;
790 }
SetLiveInBit(uint32 arg)791 void SetLiveInBit(uint32 arg) const
792 {
793 liveIn->SetBit(arg);
794 }
SetLiveInInfo(const SparseDataInfo & arg)795 void SetLiveInInfo(const SparseDataInfo &arg) const
796 {
797 *liveIn = arg;
798 }
LiveInOrBits(const SparseDataInfo & arg)799 bool LiveInOrBits(const SparseDataInfo &arg) const
800 {
801 return liveIn->OrBits(arg);
802 }
LiveInEnlargeCapacity(uint32 arg)803 void LiveInEnlargeCapacity(uint32 arg) const
804 {
805 liveIn->EnlargeCapacityToAdaptSize(arg);
806 }
LiveInClearDataInfo()807 void LiveInClearDataInfo()
808 {
809 liveIn->ClearDataInfo();
810 liveIn = nullptr;
811 }
GetLiveOut()812 SparseDataInfo *GetLiveOut()
813 {
814 return liveOut;
815 }
GetLiveOut()816 const SparseDataInfo *GetLiveOut() const
817 {
818 return liveOut;
819 }
SetLiveOut(SparseDataInfo & arg)820 void SetLiveOut(SparseDataInfo &arg)
821 {
822 liveOut = &arg;
823 }
SetLiveOutBit(uint32 arg)824 void SetLiveOutBit(uint32 arg) const
825 {
826 liveOut->SetBit(arg);
827 }
LiveOutOrBits(const SparseDataInfo & arg)828 bool LiveOutOrBits(const SparseDataInfo &arg) const
829 {
830 return liveOut->OrBits(arg);
831 }
LiveOutEnlargeCapacity(uint32 arg)832 void LiveOutEnlargeCapacity(uint32 arg) const
833 {
834 liveOut->EnlargeCapacityToAdaptSize(arg);
835 }
LiveOutClearDataInfo()836 void LiveOutClearDataInfo()
837 {
838 liveOut->ClearDataInfo();
839 liveOut = nullptr;
840 }
GetDef()841 const SparseDataInfo *GetDef() const
842 {
843 return def;
844 }
SetDef(SparseDataInfo & arg)845 void SetDef(SparseDataInfo &arg)
846 {
847 def = &arg;
848 }
SetDefBit(uint32 arg)849 void SetDefBit(uint32 arg) const
850 {
851 def->SetBit(arg);
852 }
DefResetAllBit()853 void DefResetAllBit() const
854 {
855 def->ResetAllBit();
856 }
DefResetBit(uint32 arg)857 void DefResetBit(uint32 arg) const
858 {
859 def->ResetBit(arg);
860 }
DefClearDataInfo()861 void DefClearDataInfo()
862 {
863 def->ClearDataInfo();
864 def = nullptr;
865 }
GetUse()866 const SparseDataInfo *GetUse() const
867 {
868 return use;
869 }
SetUse(SparseDataInfo & arg)870 void SetUse(SparseDataInfo &arg)
871 {
872 use = &arg;
873 }
SetUseBit(uint32 arg)874 void SetUseBit(uint32 arg) const
875 {
876 use->SetBit(arg);
877 }
UseResetAllBit()878 void UseResetAllBit() const
879 {
880 use->ResetAllBit();
881 }
UseResetBit(uint32 arg)882 void UseResetBit(uint32 arg) const
883 {
884 use->ResetBit(arg);
885 }
UseClearDataInfo()886 void UseClearDataInfo()
887 {
888 use->ClearDataInfo();
889 use = nullptr;
890 }
SetNeedAlign(bool flag)891 void SetNeedAlign(bool flag)
892 {
893 needAlign = flag;
894 }
IsBBNeedAlign()895 bool IsBBNeedAlign() const
896 {
897 return needAlign;
898 }
SetAlignPower(uint32 power)899 void SetAlignPower(uint32 power)
900 {
901 alignPower = power;
902 }
GetAlignPower()903 uint32 GetAlignPower() const
904 {
905 return alignPower;
906 }
SetAlignNopNum(uint32 num)907 void SetAlignNopNum(uint32 num)
908 {
909 alignNopNum = num;
910 }
GetAlignNopNum()911 uint32 GetAlignNopNum() const
912 {
913 return alignNopNum;
914 }
915
GetCDGNode()916 CDGNode *GetCDGNode()
917 {
918 return cdgNode;
919 }
SetCDGNode(CDGNode * node)920 void SetCDGNode(CDGNode *node)
921 {
922 cdgNode = node;
923 }
924
925 // Check if a given BB mergee can be merged into this BB in the sense of control flow
926 // The condition is looser than CanMerge, since we only need this for debug info.
MayFoldInCfg(const BB & mergee)927 bool MayFoldInCfg(const BB &mergee) const
928 {
929 bool onePred = (mergee.GetPreds().size() == 1) && (mergee.GetPreds().front() == this);
930 bool oneSucc = (GetSuccs().size() == 1) && (GetSuccs().front() == &mergee);
931 return oneSucc && onePred;
932 }
933
934 // This means two bb are close to each other in cfg. Only for debug info.
935 // May add more conditions in the future.
IsCloseTo(const BB & tar)936 bool IsCloseTo(const BB &tar) const
937 {
938 return MayFoldInCfg(tar);
939 }
940
GetEdgeProb(const BB & bb)941 int32 GetEdgeProb(const BB &bb) const
942 {
943 return succsProb.find(&bb)->second;
944 }
945
HasMachineInsn()946 bool HasMachineInsn()
947 {
948 FOR_BB_INSNS(insn, this) {
949 if (insn->IsMachineInstruction()) {
950 return true;
951 }
952 }
953 return false;
954 }
955
GetSCCNode()956 SCCNode<BB> *GetSCCNode()
957 {
958 return sccNode;
959 }
SetSCCNode(SCCNode<BB> * scc)960 void SetSCCNode(SCCNode<BB> *scc)
961 {
962 sccNode = scc;
963 }
964
965 private:
966 static const std::string bbNames[kBBLast];
967 uint32 id;
968 uint32 level = 0;
969 uint32 frequency = 0;
970 BB *prev = nullptr; /* Doubly linked list of BBs; */
971 BB *next = nullptr;
972 /* They represent the order in which blocks are to be emitted. */
973 BBKind kind = kBBFallthru; /* The BB's last statement (i.e. lastStmt) determines */
974 /* what type this BB has. By default, kBbFallthru */
975 LabelIdx labIdx;
976 StmtNode *firstStmt = nullptr;
977 StmtNode *lastStmt = nullptr;
978 Insn *firstInsn = nullptr; /* the first instruction */
979 Insn *lastInsn = nullptr; /* the last instruction */
980 MapleList<BB *> preds; /* preds, succs represent CFG */
981 MapleList<BB *> succs;
982 MapleMap<const BB *, int32> succsProb;
983 bool inColdSection = false; /* for bb splitting */
984
985 /* this is for live in out analysis */
986 MapleSet<regno_t> liveInRegNO;
987 MapleSet<regno_t> liveOutRegNO;
988 bool liveInChange = false;
989 bool isCritical = false;
990 bool insertUse = false;
991 bool hasCall = false;
992 bool unreachable = false;
993 bool wontExit = false;
994 bool fastPath = false;
995 bool isCatch = false; /* part of the catch bb, true does might also mean it is unreachable */
996 /*
997 * Since isCatch is set early and unreachable detected later, there
998 * are some overlap here.
999 */
1000 bool isCleanup = false; /* true if the bb is cleanup bb. otherwise, false. */
1001 bool isProEpilog = false; /* Temporary tag for modifying prolog/epilog bb. */
1002 bool labelTaken = false; /* Block label is taken indirectly and can be used to jump to it. */
1003 bool hasCfi = false; /* bb contain cfi directive. */
1004 /*
1005 * Different meaning for each data flow analysis.
1006 * For HandleFunction(), rough estimate of num of insn created.
1007 * For cgbb.cpp, track insn count during code selection.
1008 * For cgbb.cpp, bb is traversed during BFS ordering.
1009 * For aarchregalloc.cpp, the bb is part of cleanup at end of function.
1010 * For aarchcolorra.cpp, the bb is part of cleanup at end of function.
1011 * also used for live range splitting.
1012 * For live analysis, it indicates if bb is cleanupbb.
1013 */
1014 long internalFlag1 = 0;
1015
1016 /*
1017 * Different meaning for each data flow analysis.
1018 * For cgbb.cpp, bb is levelized to be 1 more than largest predecessor.
1019 * For aarchcolorra.cpp, used for live range splitting pruning of bb.
1020 */
1021 long internalFlag2 = 0;
1022
1023 /*
1024 * Different meaning for each data flow analysis.
1025 * For cgfunc.cpp, it temporarily marks for catch bb discovery.
1026 * For live analysis, it indicates if bb is visited.
1027 * For peephole, used for live-out checking of bb.
1028 */
1029 long internalFlag3 = 0;
1030 MapleList<Insn *> callInsns;
1031 MapleVector<LabelIdx> rangeGotoLabelVec;
1032
1033 /* bb support for SSA analysis */
1034 MapleMap<regno_t, Insn *> phiInsnList;
1035
1036 /* includes Built-in functions for atomic memory access */
1037 bool isAtomicBuiltIn = false;
1038
1039 const Insn *firstLoc = nullptr;
1040 const Insn *lastLoc = nullptr;
1041 SparseDataInfo *liveIn = nullptr;
1042 SparseDataInfo *liveOut = nullptr;
1043 SparseDataInfo *def = nullptr;
1044 SparseDataInfo *use = nullptr;
1045
1046 bool needAlign = false;
1047 uint32 alignPower = 0;
1048 uint32 alignNopNum = 0;
1049
1050 CDGNode *cdgNode = nullptr;
1051 SCCNode<BB> *sccNode = nullptr;
1052 }; /* class BB */
1053
1054 struct BBIdCmp {
operatorBBIdCmp1055 bool operator()(const BB *lhs, const BB *rhs) const
1056 {
1057 CHECK_FATAL(lhs != nullptr, "null ptr check");
1058 CHECK_FATAL(rhs != nullptr, "null ptr check");
1059 return (lhs->GetId() < rhs->GetId());
1060 }
1061 };
1062
1063 class Bfs {
1064 public:
Bfs(CGFunc & cgFunc,MemPool & memPool)1065 Bfs(CGFunc &cgFunc, MemPool &memPool)
1066 : cgfunc(&cgFunc),
1067 memPool(&memPool),
1068 alloc(&memPool),
1069 cycleSuccs(alloc.Adapter()),
1070 visitedBBs(alloc.Adapter()),
1071 sortedBBs(alloc.Adapter())
1072 {
1073 }
1074 ~Bfs() = default;
1075
1076 void SeekCycles();
1077 bool AllPredBBVisited(const BB &bb, long &level) const;
1078 BB *MarkStraightLineBBInBFS(BB *bb);
1079 BB *SearchForStraightLineBBs(BB &bb);
1080 void BFS(BB &curBB);
1081 void ComputeBlockOrder();
1082
1083 CGFunc *cgfunc;
1084 MemPool *memPool;
1085 MapleAllocator alloc;
1086 MapleVector<MapleSet<BBID>> cycleSuccs; // bb's succs in cycle
1087 MapleVector<bool> visitedBBs;
1088 MapleVector<BB *> sortedBBs;
1089 };
1090
MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgBBSort,CGFunc)1091 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgBBSort, CGFunc)
1092 Bfs *GetResult()
1093 {
1094 return bfs;
1095 }
1096 Bfs *bfs = nullptr;
1097 OVERRIDE_DEPENDENCE
1098 MAPLE_MODULE_PHASE_DECLARE_END
1099 } /* namespace maplebe */
1100
1101 #endif /* MAPLEBE_INCLUDE_CG_CGBB_H */
1102