• 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 #include "cg_cfg.h"
17 #if TARGAARCH64
18 #include "aarch64_insn.h"
19 #endif
20 #if TARGX86_64
21 #include "x64_cgfunc.h"
22 #include "cg.h"
23 #endif
24 
25 namespace maplebe {
BuildCFG()26 void CGCFG::BuildCFG()
27 {
28     if (cgFunc->HasBuiltCfg()) {
29         return;
30     }
31     /*
32      * Second Pass:
33      * Link preds/succs in the BBs
34      */
35     BB *firstBB = cgFunc->GetFirstBB();
36     for (BB *curBB = firstBB; curBB != nullptr; curBB = curBB->GetNext()) {
37         BB::BBKind kind = curBB->GetKind();
38         switch (kind) {
39             case BB::kBBIf: {
40                 BB *fallthruBB = curBB->GetNext();
41                 curBB->PushBackSuccs(*fallthruBB);
42                 fallthruBB->PushBackPreds(*curBB);
43                 Insn *branchInsn = curBB->GetLastMachineInsn();
44                 CHECK_FATAL(branchInsn != nullptr, "machine instruction must be exist in ifBB");
45                 DEBUG_ASSERT(branchInsn->IsCondBranch(), "must be a conditional branch generated from an intrinsic");
46                 /* Assume the last non-null operand is the branch target */
47                 uint32 opSz = branchInsn->GetOperandSize();
48                 DEBUG_ASSERT(opSz >= 1, "lastOpndIndex's opnd is greater than 1");
49                 Operand &lastOpnd = branchInsn->GetOperand(opSz - 1u);
50                 DEBUG_ASSERT(lastOpnd.IsLabelOpnd(), "label Operand must be exist in branch insn");
51                 auto &labelOpnd = static_cast<LabelOperand &>(lastOpnd);
52                 BB *brToBB = cgFunc->GetBBFromLab2BBMap(labelOpnd.GetLabelIndex());
53                 if (fallthruBB->GetId() != brToBB->GetId()) {
54                     curBB->PushBackSuccs(*brToBB);
55                     brToBB->PushBackPreds(*curBB);
56                 }
57                 break;
58             }
59             case BB::kBBGoto: {
60                 Insn *insn = curBB->GetLastMachineInsn();
61                 if (insn == nullptr) {
62                     curBB->SetKind(BB::kBBFallthru);
63                     continue;
64                 }
65                 CHECK_FATAL(insn != nullptr, "machine insn must be exist in gotoBB");
66                 DEBUG_ASSERT(insn->IsUnCondBranch(), "insn must be a unconditional branch insn");
67                 LabelIdx labelIdx = static_cast<LabelOperand &>(insn->GetOperand(0)).GetLabelIndex();
68                 BB *gotoBB = cgFunc->GetBBFromLab2BBMap(labelIdx);
69                 CHECK_FATAL(gotoBB != nullptr, "gotoBB is null");
70                 curBB->PushBackSuccs(*gotoBB);
71                 gotoBB->PushBackPreds(*curBB);
72                 break;
73             }
74             case BB::kBBRangeGoto: {
75                 std::set<BB *, BBIdCmp> bbs;
76                 for (auto labelIdx : curBB->GetRangeGotoLabelVec()) {
77                     BB *gotoBB = cgFunc->GetBBFromLab2BBMap(labelIdx);
78                     bbs.insert(gotoBB);
79                 }
80                 for (auto gotoBB : bbs) {
81                     curBB->PushBackSuccs(*gotoBB);
82                     gotoBB->PushBackPreds(*curBB);
83                 }
84                 break;
85             }
86             case BB::kBBFallthru: {
87                 BB *fallthruBB = curBB->GetNext();
88                 if (fallthruBB != nullptr) {
89                     curBB->PushBackSuccs(*fallthruBB);
90                     fallthruBB->PushBackPreds(*curBB);
91                 }
92                 break;
93             }
94             default:
95                 break;
96         } /* end switch */
97     }
98     FindAndMarkUnreachable(*cgFunc);
99     cgFunc->SetHasBuiltCfg(true);
100 }
101 
CheckCFG()102 void CGCFG::CheckCFG()
103 {
104     FOR_ALL_BB(bb, cgFunc)
105     {
106         for (BB *sucBB : bb->GetSuccs()) {
107             bool found = false;
108             for (BB *sucPred : sucBB->GetPreds()) {
109                 if (sucPred == bb) {
110                     if (!found) {
111                         found = true;
112                     } else {
113                         LogInfo::MapleLogger()
114                             << "dup pred " << sucPred->GetId() << " for sucBB " << sucBB->GetId() << "\n";
115                         CHECK_FATAL_FALSE("CG_CFG check failed !");
116                     }
117                 }
118             }
119             if (!found) {
120                 LogInfo::MapleLogger() << "non pred for sucBB " << sucBB->GetId() << " for BB " << bb->GetId() << "\n";
121                 CHECK_FATAL_FALSE("CG_CFG check failed !");
122             }
123         }
124     }
125     FOR_ALL_BB(bb, cgFunc)
126     {
127         for (BB *predBB : bb->GetPreds()) {
128             bool found = false;
129             for (BB *predSucc : predBB->GetSuccs()) {
130                 if (predSucc == bb) {
131                     if (!found) {
132                         found = true;
133                     } else {
134                         LogInfo::MapleLogger()
135                             << "dup succ " << predSucc->GetId() << " for predBB " << predBB->GetId() << "\n";
136                         CHECK_FATAL_FALSE("CG_CFG check failed !");
137                     }
138                 }
139             }
140             if (!found) {
141                 LogInfo::MapleLogger() << "non succ for predBB " << predBB->GetId() << " for BB " << bb->GetId()
142                                        << "\n";
143                 CHECK_FATAL_FALSE("CG_CFG check failed !");
144             }
145         }
146     }
147 }
148 
149 InsnVisitor *CGCFG::insnVisitor;
150 
InitInsnVisitor(CGFunc & func) const151 void CGCFG::InitInsnVisitor(CGFunc &func) const
152 {
153     insnVisitor = func.NewInsnModifier();
154 }
155 
156 /*
157  * return true if:
158  * mergee has only one predecessor which is merger,
159  * or mergee has other comments only predecessors & merger is soloGoto
160  * mergee can't have cfi instruction when postcfgo.
161  */
BBJudge(const BB & first,const BB & second) const162 bool CGCFG::BBJudge(const BB &first, const BB &second) const
163 {
164     if (first.GetKind() == BB::kBBReturn || second.GetKind() == BB::kBBReturn) {
165         return false;
166     }
167     if (&first == &second) {
168         return false;
169     }
170     if (second.GetPreds().size() == 1 && second.GetPreds().front() == &first) {
171         return true;
172     }
173     for (BB *bb : second.GetPreds()) {
174         if (bb != &first && !AreCommentAllPreds(*bb)) {
175             return false;
176         }
177     }
178     return first.IsSoloGoto();
179 }
180 
181 /*
182  * Check if a given BB mergee can be merged into BB merger.
183  * Returns true if:
184  * 1. mergee has only one predecessor which is merger, or mergee has
185  *   other comments only predecessors.
186  * 2. merge has only one successor which is mergee.
187  * 3. mergee can't have cfi instruction when postcfgo.
188  */
CanMerge(const BB & merger,const BB & mergee) const189 bool CGCFG::CanMerge(const BB &merger, const BB &mergee) const
190 {
191     if (!BBJudge(merger, mergee)) {
192         return false;
193     }
194     if (mergee.GetFirstInsn() != nullptr && mergee.GetFirstInsn()->IsCfiInsn()) {
195         return false;
196     }
197     return (merger.GetSuccs().size() == 1) && (merger.GetSuccs().front() == &mergee);
198 }
199 
200 /* Check if the given BB contains only comments and all its predecessors are comments */
AreCommentAllPreds(const BB & bb)201 bool CGCFG::AreCommentAllPreds(const BB &bb)
202 {
203     if (!bb.IsCommentBB()) {
204         return false;
205     }
206     for (BB *pred : bb.GetPreds()) {
207         if (!AreCommentAllPreds(*pred)) {
208             return false;
209         }
210     }
211     return true;
212 }
213 
214 /* Merge sucBB into curBB. */
MergeBB(BB & merger,BB & mergee,CGFunc & func)215 void CGCFG::MergeBB(BB &merger, BB &mergee, CGFunc &func)
216 {
217     BB *prevLast = mergee.GetPrev();
218     MergeBB(merger, mergee);
219     if (func.GetLastBB()->GetId() == mergee.GetId()) {
220         func.SetLastBB(*prevLast);
221     }
222     if (mergee.GetKind() == BB::kBBReturn) {
223         auto retIt = func.GetExitBBsVec().begin();
224         while (retIt != func.GetExitBBsVec().end()) {
225             if (*retIt == &mergee) {
226                 (void)func.EraseExitBBsVec(retIt);
227                 break;
228             } else {
229                 ++retIt;
230             }
231         }
232         func.PushBackExitBBsVec(merger);
233     }
234     if (mergee.GetKind() == BB::kBBNoReturn) {
235         auto noRetIt = func.GetNoRetCallBBVec().begin();
236         while (noRetIt != func.GetNoRetCallBBVec().end()) {
237             if (*noRetIt == &mergee) {
238                 (void)func.EraseNoReturnCallBB(noRetIt);
239                 break;
240             } else {
241                 ++noRetIt;
242             }
243         }
244         func.PushBackNoReturnCallBBsVec(merger);
245     }
246     if (mergee.GetKind() == BB::kBBRangeGoto) {
247         func.AddEmitSt(merger.GetId(), *func.GetEmitSt(mergee.GetId()));
248         func.DeleteEmitSt(mergee.GetId());
249     }
250 }
251 
MergeBB(BB & merger,BB & mergee)252 void CGCFG::MergeBB(BB &merger, BB &mergee)
253 {
254     if (merger.GetKind() == BB::kBBGoto && merger.GetLastMachineInsn() != nullptr) {
255         if (!merger.GetLastMachineInsn()->IsBranch()) {
256             CHECK_FATAL(false, "unexpected insn kind");
257         }
258         merger.RemoveInsn(*merger.GetLastMachineInsn());
259     }
260     merger.AppendBBInsns(mergee);
261     if (mergee.GetPrev() != nullptr) {
262         mergee.GetPrev()->SetNext(mergee.GetNext());
263     }
264     if (mergee.GetNext() != nullptr) {
265         mergee.GetNext()->SetPrev(mergee.GetPrev());
266     }
267     merger.RemoveSuccs(mergee);
268     for (BB *bb : mergee.GetSuccs()) {
269         bb->RemovePreds(mergee);
270         bb->PushBackPreds(merger);
271         merger.PushBackSuccs(*bb);
272     }
273     merger.SetKind(mergee.GetKind());
274     mergee.SetNext(nullptr);
275     mergee.SetPrev(nullptr);
276     mergee.ClearPreds();
277     mergee.ClearSuccs();
278     mergee.SetFirstInsn(nullptr);
279     mergee.SetLastInsn(nullptr);
280 }
281 
282 /*
283  * Find all reachable BBs by dfs in cgfunc and mark their field<unreachable> false, then all other bbs should be
284  * unreachable.
285  */
FindAndMarkUnreachable(CGFunc & func)286 void CGCFG::FindAndMarkUnreachable(CGFunc &func)
287 {
288     BB *firstBB = func.GetFirstBB();
289     std::stack<BB *> toBeAnalyzedBBs;
290     toBeAnalyzedBBs.push(firstBB);
291     std::unordered_set<uint32> instackBBs;
292 
293     BB *bb = firstBB;
294     /* set all bb's unreacable to true */
295     while (bb != nullptr) {
296         /* Check if bb is the first or the last BB of the function */
297         if (InSwitchTable(bb->GetLabIdx(), func) || bb == func.GetFirstBB() || bb == func.GetLastBB()) {
298             toBeAnalyzedBBs.push(bb);
299         } else if (bb->IsLabelTaken() == false) {
300             bb->SetUnreachable(true);
301         }
302         bb = bb->GetNext();
303     }
304 
305     /* do a dfs to see which bbs are reachable */
306     while (!toBeAnalyzedBBs.empty()) {
307         bb = toBeAnalyzedBBs.top();
308         toBeAnalyzedBBs.pop();
309         (void)instackBBs.insert(bb->GetId());
310 
311         bb->SetUnreachable(false);
312 
313         for (BB *succBB : bb->GetSuccs()) {
314             if (instackBBs.count(succBB->GetId()) == 0) {
315                 toBeAnalyzedBBs.push(succBB);
316                 (void)instackBBs.insert(succBB->GetId());
317             }
318         }
319     }
320     FOR_ALL_BB(tmpBB, &func)
321     {
322         for (MapleList<BB *>::iterator predIt = tmpBB->GetPredsBegin(); predIt != tmpBB->GetPredsEnd(); ++predIt) {
323             if ((*predIt)->IsUnreachable()) {
324                 tmpBB->ErasePreds(predIt);
325             }
326         }
327     }
328 }
329 
330 /*
331  * Theoretically, every time you remove from a bb's preds, you should consider invoking this method.
332  *
333  * @param bb
334  * @param func
335  */
FlushUnReachableStatusAndRemoveRelations(BB & bb,const CGFunc & func) const336 void CGCFG::FlushUnReachableStatusAndRemoveRelations(BB &bb, const CGFunc &func) const
337 {
338     /* Check if bb is the first or the last BB of the function */
339     bool isFirstBBInfunc = (&bb == func.GetFirstBB());
340     bool isLastBBInfunc = (&bb == func.GetLastBB());
341     if (InSwitchTable(bb.GetLabIdx(), func) || isFirstBBInfunc || isLastBBInfunc) {
342         return;
343     }
344     std::stack<BB *> toBeAnalyzedBBs;
345     toBeAnalyzedBBs.push(&bb);
346     std::set<uint32> instackBBs;
347     BB *it = nullptr;
348     while (!toBeAnalyzedBBs.empty()) {
349         it = toBeAnalyzedBBs.top();
350         (void)instackBBs.insert(it->GetId());
351         toBeAnalyzedBBs.pop();
352         /* Check if bb is the first or the last BB of the function */
353         isFirstBBInfunc = (it == func.GetFirstBB());
354         isLastBBInfunc = (it == func.GetLastBB());
355         bool needFlush = !isFirstBBInfunc && !isLastBBInfunc && it->GetPreds().empty() &&
356                          !InSwitchTable(it->GetLabIdx(), *cgFunc) && !cgFunc->IsExitBB(*it) &&
357                          (it->IsLabelTaken() == false);
358         if (!needFlush) {
359             continue;
360         }
361         it->SetUnreachable(true);
362         it->SetFirstInsn(nullptr);
363         it->SetLastInsn(nullptr);
364         for (BB *succ : it->GetSuccs()) {
365             if (instackBBs.count(succ->GetId()) == 0) {
366                 toBeAnalyzedBBs.push(succ);
367                 (void)instackBBs.insert(succ->GetId());
368             }
369             succ->RemovePreds(*it);
370         }
371         it->ClearSuccs();
372     }
373 }
374 
RemoveBB(BB & curBB,bool isGotoIf) const375 void CGCFG::RemoveBB(BB &curBB, bool isGotoIf) const
376 {
377     if (!curBB.IsUnreachable()) {
378         BB *sucBB = CGCFG::GetTargetSuc(curBB, false, isGotoIf);
379         if (sucBB != nullptr) {
380             sucBB->RemovePreds(curBB);
381         }
382         BB *fallthruSuc = nullptr;
383         if (isGotoIf) {
384             for (BB *succ : curBB.GetSuccs()) {
385                 if (succ == sucBB) {
386                     continue;
387                 }
388                 fallthruSuc = succ;
389                 break;
390             }
391             DEBUG_ASSERT(fallthruSuc == curBB.GetNext(), "fallthru succ should be its next bb.");
392             if (fallthruSuc != nullptr) {
393                 fallthruSuc->RemovePreds(curBB);
394             }
395         }
396 
397         for (BB *preBB : curBB.GetPreds()) {
398             /*
399              * If curBB is the target of its predecessor, change
400              * the jump target.
401              */
402             if (&curBB == GetTargetSuc(*preBB, true, isGotoIf)) {
403                 LabelIdx targetLabel;
404                 if (curBB.GetNext()->GetLabIdx() == 0) {
405                     targetLabel = insnVisitor->GetCGFunc()->CreateLabel();
406                     curBB.GetNext()->SetLabIdx(targetLabel);
407                     cgFunc->SetLab2BBMap(targetLabel, *curBB.GetNext());
408                 } else {
409                     targetLabel = curBB.GetNext()->GetLabIdx();
410                 }
411                 insnVisitor->ModifyJumpTarget(targetLabel, *preBB);
412             }
413             if (fallthruSuc != nullptr && !fallthruSuc->IsPredecessor(*preBB)) {
414                 preBB->PushBackSuccs(*fallthruSuc);
415                 fallthruSuc->PushBackPreds(*preBB);
416             }
417             if (sucBB != nullptr && !sucBB->IsPredecessor(*preBB)) {
418                 preBB->PushBackSuccs(*sucBB);
419                 sucBB->PushBackPreds(*preBB);
420             }
421             preBB->RemoveSuccs(curBB);
422         }
423     }
424 
425     if (curBB.GetNext() != nullptr) {
426         cgFunc->GetCommonExitBB()->RemovePreds(curBB);
427         curBB.GetNext()->RemovePreds(curBB);
428         curBB.GetNext()->SetPrev(curBB.GetPrev());
429     } else {
430         cgFunc->SetLastBB(*curBB.GetPrev());
431     }
432     if (curBB.GetPrev() != nullptr) {
433         curBB.GetPrev()->SetNext(curBB.GetNext());
434     } else {
435         cgFunc->SetFirstBB(*curBB.GetNext());
436     }
437     cgFunc->ClearBBInVec(curBB.GetId());
438 }
439 
UpdateCommonExitBBInfo()440 void CGCFG::UpdateCommonExitBBInfo()
441 {
442     BB *commonExitBB = cgFunc->GetCommonExitBB();
443     ASSERT_NOT_NULL(commonExitBB);
444     commonExitBB->ClearPreds();
445     for (BB *exitBB : cgFunc->GetExitBBsVec()) {
446         if (!exitBB->IsUnreachable()) {
447             commonExitBB->PushBackPreds(*exitBB);
448         }
449     }
450     for (BB *noRetBB : cgFunc->GetNoRetCallBBVec()) {
451         if (!noRetBB->IsUnreachable()) {
452             commonExitBB->PushBackPreds(*noRetBB);
453         }
454     }
455     WontExitAnalysis();
456 }
457 
GetTargetSuc(BB & curBB,bool branchOnly,bool isGotoIf)458 BB *CGCFG::GetTargetSuc(BB &curBB, bool branchOnly, bool isGotoIf)
459 {
460     switch (curBB.GetKind()) {
461         case BB::kBBGoto:
462         case BB::kBBIf: {
463             const Insn *origLastInsn = curBB.GetLastMachineInsn();
464             ASSERT_NOT_NULL(origLastInsn);
465             if (isGotoIf && (curBB.GetPrev() != nullptr) &&
466                 (curBB.GetKind() == BB::kBBGoto || curBB.GetKind() == BB::kBBIf) &&
467                 (curBB.GetPrev()->GetKind() == BB::kBBGoto || curBB.GetPrev()->GetKind() == BB::kBBIf)) {
468                 origLastInsn = curBB.GetPrev()->GetLastMachineInsn();
469             }
470             ASSERT_NOT_NULL(origLastInsn);
471             LabelIdx label = insnVisitor->GetJumpLabel(*origLastInsn);
472             for (BB *bb : curBB.GetSuccs()) {
473                 if (bb->GetLabIdx() == label) {
474                     return bb;
475                 }
476             }
477             break;
478         }
479         case BB::kBBFallthru: {
480             return (branchOnly ? nullptr : curBB.GetNext());
481         }
482         default:
483             return nullptr;
484     }
485     return nullptr;
486 }
487 
InSwitchTable(LabelIdx label,const CGFunc & func)488 bool CGCFG::InSwitchTable(LabelIdx label, const CGFunc &func)
489 {
490     if (label == 0) {
491         return false;
492     }
493     return func.InSwitchTable(label);
494 }
495 
496 /*
497  * analyse the CFG to find the BBs that are not reachable from function entries
498  * and delete them
499  */
UnreachCodeAnalysis() const500 void CGCFG::UnreachCodeAnalysis() const
501 {
502     BB *firstBB = cgFunc->GetFirstBB();
503     std::forward_list<BB *> toBeAnalyzedBBs;
504     toBeAnalyzedBBs.push_front(firstBB);
505     std::set<BB *, BBIdCmp> unreachBBs;
506 
507     BB *bb = firstBB;
508     /* set all bb's unreacable to true */
509     while (bb != nullptr) {
510         /* Check if bb is the firstBB/cleanupBB/returnBB/lastBB of the function */
511         if (InSwitchTable(bb->GetLabIdx(), *cgFunc) || bb == cgFunc->GetFirstBB() ||
512             bb == cgFunc->GetLastBB() || bb->GetKind() == BB::kBBReturn) {
513             toBeAnalyzedBBs.push_front(bb);
514         } else {
515             (void)unreachBBs.insert(bb);
516         }
517         if (bb->IsLabelTaken() == false) {
518             bb->SetUnreachable(true);
519         }
520         bb = bb->GetNext();
521     }
522 
523     /* do a dfs to see which bbs are reachable */
524     while (!toBeAnalyzedBBs.empty()) {
525         bb = toBeAnalyzedBBs.front();
526         toBeAnalyzedBBs.pop_front();
527         if (!bb->IsUnreachable()) {
528             continue;
529         }
530         bb->SetUnreachable(false);
531         for (BB *succBB : bb->GetSuccs()) {
532             toBeAnalyzedBBs.push_front(succBB);
533             unreachBBs.erase(succBB);
534         }
535     }
536 
537     /* remove unreachable bb */
538     std::set<BB *, BBIdCmp>::iterator it;
539     for (it = unreachBBs.begin(); it != unreachBBs.end(); it++) {
540         BB *unreachBB = *it;
541         DEBUG_ASSERT(unreachBB != nullptr, "unreachBB must not be nullptr");
542         for (auto exitBB = cgFunc->GetExitBBsVec().begin(); exitBB != cgFunc->GetExitBBsVec().end(); ++exitBB) {
543             if (*exitBB == unreachBB) {
544                 cgFunc->GetExitBBsVec().erase(exitBB);
545                 break;
546             }
547         }
548         unreachBB->GetPrev()->SetNext(unreachBB->GetNext());
549         cgFunc->GetCommonExitBB()->RemovePreds(*unreachBB);
550         if (unreachBB->GetNext()) {
551             unreachBB->GetNext()->SetPrev(unreachBB->GetPrev());
552         }
553 
554         for (BB *sucBB : unreachBB->GetSuccs()) {
555             sucBB->RemovePreds(*unreachBB);
556         }
557 
558         unreachBB->ClearSuccs();
559 
560         cgFunc->ClearBBInVec(unreachBB->GetId());
561     }
562 }
563 
FindWillExitBBs(BB * bb,std::set<BB *,BBIdCmp> * visitedBBs)564 void CGCFG::FindWillExitBBs(BB *bb, std::set<BB *, BBIdCmp> *visitedBBs)
565 {
566     std::queue<BB *> allBBs;
567     allBBs.push(bb);
568     while (!allBBs.empty()) {
569         BB *curBB = allBBs.front();
570         allBBs.pop();
571         if (visitedBBs->count(curBB) != 0) {
572             continue;
573         }
574         visitedBBs->insert(curBB);
575         for (auto *predBB : curBB->GetPreds()) {
576             allBBs.push(predBB);
577         }
578     }
579 }
580 
581 /*
582  * analyse the CFG to find the BBs that will not reach any function exit; these
583  * are BBs inside infinite loops; mark their wontExit flag and create
584  * artificial edges from them to commonExitBB
585  */
WontExitAnalysis()586 void CGCFG::WontExitAnalysis()
587 {
588     std::set<BB *, BBIdCmp> visitedBBs;
589     FindWillExitBBs(cgFunc->GetCommonExitBB(), &visitedBBs);
590     BB *bb = cgFunc->GetFirstBB();
591     while (bb != nullptr) {
592         if (visitedBBs.count(bb) == 0) {
593             bb->SetWontExit(true);
594             if (bb->GetKind() == BB::kBBGoto) {
595                 // make this bb a predecessor of commonExitBB
596                 cgFunc->GetCommonExitBB()->PushBackPreds(*bb);
597             }
598         }
599         bb = bb->GetNext();
600     }
601 }
602 
GetAnalysisDependence(AnalysisDep & aDep) const603 void CgHandleCFG::GetAnalysisDependence(AnalysisDep &aDep) const
604 {
605     aDep.SetPreservedAll();
606 }
607 
PhaseRun(maplebe::CGFunc & f)608 bool CgHandleCFG::PhaseRun(maplebe::CGFunc &f)
609 {
610     CGCFG *cfg = f.GetMemoryPool()->New<CGCFG>(f);
611     f.SetTheCFG(cfg);
612     /* build control flow graph */
613     f.GetTheCFG()->BuildCFG();
614     f.HandleFuncCfg(cfg);
615 
616     /* analysis unreachable code */
617     f.GetTheCFG()->UnreachCodeAnalysis();
618     f.EraseUnreachableStackMapInsns();
619     return false;
620 }
621 MAPLE_ANALYSIS_PHASE_REGISTER(CgHandleCFG, handlecfg)
622 
623 } /* namespace maplebe */
624