• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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