• 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         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