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