• 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 MAPLE_ME_INCLUDE_BB_H
17 #define MAPLE_ME_INCLUDE_BB_H
18 #include "utils.h"
19 #include "mpl_number.h"
20 #include "ptr_list_ref.h"
21 #include "orig_symbol.h"
22 #include "ver_symbol.h"
23 #include "ssa.h"
24 #include "scc.h"
25 #include "base_graph_node.h"
26 
27 namespace maple {
28 class MeStmt;          // circular dependency exists, no other choice
29 class MePhiNode;       // circular dependency exists, no other choice
30 class PiassignMeStmt;  // circular dependency exists, no other choice
31 class IRMap;           // circular dependency exists, no other choice
32 enum BBKind {
33     kBBUnknown,  // uninitialized
34     kBBCondGoto,
35     kBBGoto,  // unconditional branch
36     kBBFallthru,
37     kBBReturn,
38     kBBAfterGosub,  // the BB that follows a gosub, as it is an entry point
39     kBBSwitch,
40     kBBIgoto,
41     kBBInvalid
42 };
43 
44 enum BBAttr : uint32 {
45     kBBAttrIsEntry = utils::bit_field_v<1>,
46     kBBAttrIsExit = utils::bit_field_v<2>,
47     kBBAttrWontExit = utils::bit_field_v<3>,
48     kBBAttrIsTry = utils::bit_field_v<4>,
49     kBBAttrIsTryEnd = utils::bit_field_v<5>,
50     kBBAttrIsJSCatch = utils::bit_field_v<6>,
51     kBBAttrIsJSFinally = utils::bit_field_v<7>,
52     kBBAttrIsCatch = utils::bit_field_v<8>,
53     kBBAttrArtificial = utils::bit_field_v<10>,
54     kBBAttrIsInLoop = utils::bit_field_v<11>,
55     kBBAttrIsInLoopForEA = utils::bit_field_v<12>,
56     kBBAttrIsInstrument = utils::bit_field_v<13>
57 };
58 
59 constexpr uint32 kBBVectorInitialSize = 2;
60 using StmtNodes = PtrListRef<StmtNode>;
61 using MeStmts = PtrListRef<MeStmt>;
62 
63 class BB : public BaseGraphNode {
64 public:
65     using BBId = utils::Index<BB>;
66 
BB(MapleAllocator * alloc,MapleAllocator * versAlloc,BBId id)67     BB(MapleAllocator *alloc, MapleAllocator *versAlloc, BBId id)
68         : id(id),
69           pred(kBBVectorInitialSize, nullptr, alloc->Adapter()),
70           succ(kBBVectorInitialSize, nullptr, alloc->Adapter()),
71           succFreq(alloc->Adapter()),
72           phiList(versAlloc->Adapter()),
73           mePhiList(alloc->Adapter()),
74           meVarPiList(alloc->Adapter()),
75           group(this)
76     {
77         pred.pop_back();
78         pred.pop_back();
79         succ.pop_back();
80         succ.pop_back();
81     }
82 
BB(MapleAllocator * alloc,MapleAllocator * versAlloc,BBId id,StmtNode * firstStmt,StmtNode * lastStmt)83     BB(MapleAllocator *alloc, MapleAllocator *versAlloc, BBId id, StmtNode *firstStmt, StmtNode *lastStmt)
84         : id(id),
85           pred(kBBVectorInitialSize, nullptr, alloc->Adapter()),
86           succ(kBBVectorInitialSize, nullptr, alloc->Adapter()),
87           succFreq(alloc->Adapter()),
88           phiList(versAlloc->Adapter()),
89           mePhiList(alloc->Adapter()),
90           meVarPiList(alloc->Adapter()),
91           stmtNodeList(firstStmt, lastStmt),
92           group(this)
93     {
94         pred.pop_back();
95         pred.pop_back();
96         succ.pop_back();
97         succ.pop_back();
98     }
99 
100     virtual ~BB() = default;
GetSCCNode()101     SCCNode<BB> *GetSCCNode()
102     {
103         return sccNode;
104     }
SetSCCNode(SCCNode<BB> * scc)105     void SetSCCNode(SCCNode<BB> *scc)
106     {
107         sccNode = scc;
108     }
109 
GetIdentity()110     const std::string GetIdentity()
111     {
112         return "BBId: " + std::to_string(GetID());
113     }
114 
GetOutNodes(std::vector<BaseGraphNode * > & outNodes)115     void GetOutNodes(std::vector<BaseGraphNode *> &outNodes) const final
116     {
117         outNodes.resize(succ.size(), nullptr);
118         std::copy(succ.begin(), succ.end(), outNodes.begin());
119     }
120 
GetOutNodes(std::vector<BaseGraphNode * > & outNodes)121     void GetOutNodes(std::vector<BaseGraphNode *> &outNodes) final
122     {
123         static_cast<const BB *>(this)->GetOutNodes(outNodes);
124     }
125 
GetInNodes(std::vector<BaseGraphNode * > & inNodes)126     void GetInNodes(std::vector<BaseGraphNode *> &inNodes) const final
127     {
128         inNodes.resize(pred.size(), nullptr);
129         std::copy(pred.begin(), pred.end(), inNodes.begin());
130     }
131 
GetInNodes(std::vector<BaseGraphNode * > & inNodes)132     void GetInNodes(std::vector<BaseGraphNode *> &inNodes) final
133     {
134         static_cast<const BB *>(this)->GetInNodes(inNodes);
135     }
136 
GetAttributes(uint32 attrKind)137     bool GetAttributes(uint32 attrKind) const
138     {
139         return (attributes & attrKind) != 0;
140     }
141 
GetAttributes()142     uint32 GetAttributes() const
143     {
144         return attributes;
145     }
146 
SetAttributes(uint32 attrKind)147     void SetAttributes(uint32 attrKind)
148     {
149         attributes |= attrKind;
150     }
151 
ClearAttributes(uint32 attrKind)152     void ClearAttributes(uint32 attrKind)
153     {
154         attributes &= (~attrKind);
155     }
156 
IsGoto()157     virtual bool IsGoto() const
158     {
159         return kind == kBBGoto;
160     }
161 
AddBackEndTry()162     virtual bool AddBackEndTry() const
163     {
164         return GetAttributes(kBBAttrIsTryEnd);
165     }
166 
167     void Dump(const MIRModule *mod);
168     void DumpHeader(const MIRModule *mod) const;
169     void DumpPhi();
170     void DumpBBAttribute(const MIRModule *mod) const;
171     std::string StrAttribute() const;
172 
173     // Only use for common entry bb
AddEntry(BB & bb)174     void AddEntry(BB &bb)
175     {
176         succ.push_back(&bb);
177     }
178 
179     // Only use for common exit bb
AddExit(BB & bb)180     void AddExit(BB &bb)
181     {
182         pred.push_back(&bb);
183     }
184 
185     // This is to help new bb to keep some flags from original bb after logically splitting.
CopyFlagsAfterSplit(const BB & bb)186     void CopyFlagsAfterSplit(const BB &bb)
187     {
188         bb.GetAttributes(kBBAttrIsTry) ? SetAttributes(kBBAttrIsTry) : ClearAttributes(kBBAttrIsTry);
189         bb.GetAttributes(kBBAttrIsTryEnd) ? SetAttributes(kBBAttrIsTryEnd) : ClearAttributes(kBBAttrIsTryEnd);
190         bb.GetAttributes(kBBAttrIsExit) ? SetAttributes(kBBAttrIsExit) : ClearAttributes(kBBAttrIsExit);
191         bb.GetAttributes(kBBAttrWontExit) ? SetAttributes(kBBAttrWontExit) : ClearAttributes(kBBAttrWontExit);
192     }
193 
GetBBId()194     BBId GetBBId() const
195     {
196         return id;
197     }
198 
SetBBId(BBId idx)199     void SetBBId(BBId idx)
200     {
201         id = idx;
202     }
203 
UintID()204     uint32 UintID() const
205     {
206         return static_cast<uint32>(id);
207     }
208 
GetID()209     uint32 GetID() const
210     {
211         return static_cast<uint32>(id);
212     }
213 
IsEmpty()214     bool IsEmpty() const
215     {
216         return stmtNodeList.empty();
217     }
218 
SetFirst(StmtNode * stmt)219     void SetFirst(StmtNode *stmt)
220     {
221         stmtNodeList.update_front(stmt);
222     }
223 
SetLast(StmtNode * stmt)224     void SetLast(StmtNode *stmt)
225     {
226         stmtNodeList.update_back(stmt);
227     }
228 
229     // should test IsEmpty first
GetFirst()230     StmtNode &GetFirst()
231     {
232         return stmtNodeList.front();
233     }
234     // should test IsEmpty first
GetFirst()235     const StmtNode &GetFirst() const
236     {
237         return stmtNodeList.front();
238     }
239 
240     // should test IsEmpty first
GetLast()241     StmtNode &GetLast()
242     {
243         return stmtNodeList.back();
244     }
245     // should test IsEmpty first
GetLast()246     const StmtNode &GetLast() const
247     {
248         return stmtNodeList.back();
249     }
250 
251     void SetFirstMe(MeStmt *stmt);
252     void SetLastMe(MeStmt *stmt);
253     MeStmt *GetFirstMe();
254     const MeStmt *GetFirstMe() const;
255 
256     void DumpMeBB(const IRMap &irMap);
257     void MoveAllPredToSucc(BB *newSucc, BB *commonEntry);
258     void MoveAllSuccToPred(BB *newPred, BB *commonExit);
259     void RemoveStmtNode(StmtNode *stmt);
260 
InsertPi(BB & bb,PiassignMeStmt & s)261     void InsertPi(BB &bb, PiassignMeStmt &s)
262     {
263         if (meVarPiList.find(&bb) == meVarPiList.end()) {
264             std::vector<PiassignMeStmt *> tmp;
265             meVarPiList[&bb] = tmp;
266         }
267         meVarPiList[&bb].push_back(&s);
268     }
269 
GetPiList()270     MapleMap<BB *, std::vector<PiassignMeStmt *>> &GetPiList()
271     {
272         return meVarPiList;
273     }
274 
IsMeStmtEmpty()275     bool IsMeStmtEmpty() const
276     {
277         return meStmtList.empty();
278     }
279 
IsReturnBB()280     bool IsReturnBB() const
281     {
282         return kind == kBBReturn && !stmtNodeList.empty() && stmtNodeList.back().GetOpCode() == OP_return;
283     }
284 
285     void FindWillExitBBs(std::vector<bool> &visitedBBs) const;
286     const PhiNode *PhiofVerStInserted(const VersionSt &versionSt) const;
287     bool InsertPhi(MapleAllocator *alloc, VersionSt *versionSt);
288     void PrependMeStmt(MeStmt *meStmt);
289     void RemoveMeStmt(MeStmt *meStmt);
290     void AddMeStmtFirst(MeStmt *meStmt);
291     void AddMeStmtLast(MeStmt *meStmt);
292     void InsertMeStmtBefore(const MeStmt *meStmt, MeStmt *inStmt);
293     void InsertMeStmtAfter(const MeStmt *meStmt, MeStmt *inStmt);
294     void InsertMeStmtLastBr(MeStmt *inStmt);
295     void ReplaceMeStmt(MeStmt *stmt, MeStmt *newStmt);
296     void RemoveLastMeStmt();
297     void DumpMePhiList(const IRMap *irMap);
298     void DumpMeVarPiList(const IRMap *irMap);
299     void EmitBB(SSATab &ssaTab, BlockNode &curblk, bool needAnotherPass);
GetStmtNodes()300     StmtNodes &GetStmtNodes()
301     {
302         return stmtNodeList;
303     }
304 
GetStmtNodes()305     const StmtNodes &GetStmtNodes() const
306     {
307         return stmtNodeList;
308     }
309 
GetMeStmts()310     MeStmts &GetMeStmts()
311     {
312         return meStmtList;
313     }
314 
GetMeStmts()315     const MeStmts &GetMeStmts() const
316     {
317         return meStmtList;
318     }
319 
GetBBLabel()320     LabelIdx GetBBLabel() const
321     {
322         return bbLabel;
323     }
324 
SetBBLabel(LabelIdx idx)325     void SetBBLabel(LabelIdx idx)
326     {
327         bbLabel = idx;
328     }
329 
GetFrequency()330     uint32 GetFrequency() const
331     {
332         return frequency;
333     }
334 
SetFrequency(uint32 f)335     void SetFrequency(uint32 f)
336     {
337         frequency = f;
338     }
339 
GetKind()340     BBKind GetKind() const
341     {
342         return kind;
343     }
344 
SetKind(BBKind bbKind)345     void SetKind(BBKind bbKind)
346     {
347         kind = bbKind;
348     }
349 
SetKindReturn()350     void SetKindReturn()
351     {
352         SetKind(kBBReturn);
353         SetAttributes(kBBAttrIsExit);
354     }
355 
GetPred()356     const MapleVector<BB *> &GetPred() const
357     {
358         return pred;
359     }
360 
GetPred()361     MapleVector<BB *> &GetPred()
362     {
363         return pred;
364     }
365 
GetUniquePred()366     BB *GetUniquePred() const
367     {
368         if (pred.empty()) {
369             return nullptr;
370         }
371         if (pred.size() == 1) {
372             return pred.front();
373         }
374         for (size_t i = 0; i < pred.size(); ++i) {
375             if (pred.at(i) != pred.at(0)) {
376                 return nullptr;
377             }
378         }
379         return pred.front();
380     }
381 
GetPred(size_t cnt)382     const BB *GetPred(size_t cnt) const
383     {
384         DEBUG_ASSERT(cnt < pred.size(), "out of range in BB::GetPred");
385         return pred.at(cnt);
386     }
387 
GetPred(size_t cnt)388     BB *GetPred(size_t cnt)
389     {
390         DEBUG_ASSERT(cnt < pred.size(), "out of range in BB::GetPred");
391         return pred.at(cnt);
392     }
393 
SetPred(size_t cnt,BB * pp)394     void SetPred(size_t cnt, BB *pp)
395     {
396         CHECK_FATAL(cnt < pred.size(), "out of range in BB::SetPred");
397         pred[cnt] = pp;
398     }
399 
PushBackSuccFreq(uint64 freq)400     void PushBackSuccFreq(uint64 freq)
401     {
402         return succFreq.push_back(freq);
403     }
404 
GetSuccFreq()405     MapleVector<uint64> &GetSuccFreq()
406     {
407         return succFreq;
408     }
SetSuccFreq(int idx,uint64 freq)409     void SetSuccFreq(int idx, uint64 freq)
410     {
411         DEBUG_ASSERT(idx >= 0 && static_cast<size_t>(idx) <= succFreq.size(), "sanity check");
412         succFreq[static_cast<size_t>(idx)] = freq;
413     }
414 
GetSucc()415     const MapleVector<BB *> &GetSucc() const
416     {
417         return succ;
418     }
419 
GetSucc()420     MapleVector<BB *> &GetSucc()
421     {
422         return succ;
423     }
424 
GetUniqueSucc()425     BB *GetUniqueSucc()
426     {
427         if (succ.empty()) {
428             return nullptr;
429         }
430         if (succ.size() == 1) {
431             return succ.front();
432         }
433         for (size_t i = 0; i < succ.size(); ++i) {
434             if (succ.at(i) != succ.at(0)) {
435                 return nullptr;
436             }
437         }
438         return succ.front();
439     }
440 
GetSucc(size_t cnt)441     const BB *GetSucc(size_t cnt) const
442     {
443         DEBUG_ASSERT(cnt < succ.size(), "out of range in BB::GetSucc");
444         return succ.at(cnt);
445     }
446 
GetSucc(size_t cnt)447     BB *GetSucc(size_t cnt)
448     {
449         DEBUG_ASSERT(cnt < succ.size(), "out of range in BB::GetSucc");
450         return succ.at(cnt);
451     }
452 
SetSucc(size_t cnt,BB * ss)453     void SetSucc(size_t cnt, BB *ss)
454     {
455         CHECK_FATAL(cnt < succ.size(), "out of range in BB::SetSucc");
456         succ[cnt] = ss;
457     }
458 
GetPhiList()459     const MapleMap<OStIdx, PhiNode> &GetPhiList() const
460     {
461         return phiList;
462     }
GetPhiList()463     MapleMap<OStIdx, PhiNode> &GetPhiList()
464     {
465         return phiList;
466     }
ClearPhiList()467     void ClearPhiList()
468     {
469         phiList.clear();
470     }
471 
GetMePhiList()472     MapleMap<OStIdx, MePhiNode *> &GetMePhiList()
473     {
474         return mePhiList;
475     }
476 
GetMePhiList()477     const MapleMap<OStIdx, MePhiNode *> &GetMePhiList() const
478     {
479         return mePhiList;
480     }
481 
ClearMePhiList()482     void ClearMePhiList()
483     {
484         mePhiList.clear();
485     }
486 
GetEdgeFreq(const BB * bb)487     uint64 GetEdgeFreq(const BB *bb) const
488     {
489         auto iter = std::find(succ.begin(), succ.end(), bb);
490         CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID());
491         CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size doesn't match succ size");
492         const size_t idx = static_cast<size_t>(std::distance(succ.begin(), iter));
493         return succFreq[idx];
494     }
495 
GetEdgeFreq(size_t idx)496     uint64 GetEdgeFreq(size_t idx) const
497     {
498         CHECK_FATAL(idx < succFreq.size(), "out of range in BB::GetEdgeFreq");
499         CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size doesn't match succ size");
500         return succFreq[idx];
501     }
502 
SetEdgeFreq(const BB * bb,uint64 freq)503     void SetEdgeFreq(const BB *bb, uint64 freq)
504     {
505         auto iter = std::find(succ.begin(), succ.end(), bb);
506         CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID());
507         CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size %d doesn't match succ size %d", succFreq.size(),
508                     succ.size());
509         const size_t idx = static_cast<size_t>(std::distance(succ.begin(), iter));
510         succFreq[idx] = freq;
511     }
512 
InitEdgeFreq()513     void InitEdgeFreq()
514     {
515         succFreq.resize(succ.size());
516     }
517 
GetGroup()518     BB *GetGroup() const
519     {
520         return group;
521     }
522 
SetGroup(BB * g)523     void SetGroup(BB *g)
524     {
525         group = g;
526     }
527 
ClearGroup()528     void ClearGroup()
529     {
530         group = this;
531     }
532 
533     void RemoveBBFromSucc(const BB &bb);
534     int GetPredIndex(const BB &predBB) const;
535     int GetSuccIndex(const BB &succBB) const;
536     void RemovePhiOpnd(int index);
537 
538 private:
539     BBId id;
540     LabelIdx bbLabel = 0;    // the BB's label
541     MapleVector<BB *> pred;  // predecessor list
542     MapleVector<BB *> succ;  // successor list
543     // record the edge freq from curBB to succ BB
544     MapleVector<uint64> succFreq;
545     MapleMap<OStIdx, PhiNode> phiList;
546     MapleMap<OStIdx, MePhiNode *> mePhiList;
547     MapleMap<BB *, std::vector<PiassignMeStmt *>> meVarPiList;
548     uint32 frequency = 0;
549     BBKind kind = kBBUnknown;
550     uint32 attributes = 0;
551 
552 public:
553     StmtNodes stmtNodeList;
554 
555 private:
556     MeStmts meStmtList;
557     BB *group;
558     SCCNode<BB> *sccNode = nullptr;
559 };
560 
561 using BBId = BB::BBId;
562 
563 class SCCOfBBs {
564 public:
SCCOfBBs(uint32 index,BB * bb,MapleAllocator * alloc)565     SCCOfBBs(uint32 index, BB *bb, MapleAllocator *alloc)
566         : id(index),
567           entry(bb),
568           bbs(alloc->Adapter()),
569           predSCC(std::less<SCCOfBBs *>(), alloc->Adapter()),
570           succSCC(std::less<SCCOfBBs *>(), alloc->Adapter())
571     {
572     }
573     ~SCCOfBBs() = default;
574     void Dump();
575     void Verify(MapleVector<SCCOfBBs *> &sccOfBB);
576     void SetUp(MapleVector<SCCOfBBs *> &sccOfBB);
577     bool HasCycle() const;
AddBBNode(BB * bb)578     void AddBBNode(BB *bb)
579     {
580         bbs.push_back(bb);
581     }
Clear()582     void Clear()
583     {
584         bbs.clear();
585     }
GetID()586     uint32 GetID() const
587     {
588         return id;
589     }
GetBBs()590     const MapleVector<BB *> &GetBBs() const
591     {
592         return bbs;
593     }
GetSucc()594     const MapleSet<SCCOfBBs *> &GetSucc() const
595     {
596         return succSCC;
597     }
GetPred()598     const MapleSet<SCCOfBBs *> &GetPred() const
599     {
600         return predSCC;
601     }
HasPred()602     bool HasPred() const
603     {
604         return !predSCC.empty();
605     }
GetEntry()606     BB *GetEntry()
607     {
608         return entry;
609     }
610 
611 private:
612     uint32 id;
613     BB *entry;
614     MapleVector<BB *> bbs;
615     MapleSet<SCCOfBBs *> predSCC;
616     MapleSet<SCCOfBBs *> succSCC;
617 };
618 
619 bool ControlFlowInInfiniteLoop(const BB &bb, Opcode opcode);
620 }  // namespace maple
621 
622 namespace std {
623 template <>
624 struct hash<maple::BBId> {
625     size_t operator()(const maple::BBId &x) const
626     {
627         return x;
628     }
629 };
630 }  // namespace std
631 #endif  // MAPLE_ME_INCLUDE_BB_H
632