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 "cfgo.h"
17 #include "cgbb.h"
18 #include "cg.h"
19 #include "loop.h"
20 #include "mpl_logging.h"
21 
22 /*
23  * This phase traverses all basic block of cgFunc and finds special
24  * basic block patterns, like continuous fallthrough basic block, continuous
25  * uncondition jump basic block, unreachable basic block and empty basic block,
26  * then do basic mergering, basic block placement transformations,
27  * unnecessary jumps elimination, and remove unreachable or empty basic block.
28  * This optimization is done on control flow graph basis.
29  */
30 namespace maplebe {
31 using namespace maple;
32 
33 #define CFGO_DUMP_NEWPM CG_DEBUG_FUNC(f)
34 
35 /* return true if to is put after from and there is no real insns between from and to, */
NoInsnBetween(const BB &from, const BB &to) const36 bool ChainingPattern::NoInsnBetween(const BB &from, const BB &to) const
37 {
38     const BB *bb = nullptr;
39     for (bb = from.GetNext(); bb != nullptr && bb != &to && bb != cgFunc->GetLastBB(); bb = bb->GetNext()) {
40         if (!bb->IsEmptyOrCommentOnly() || bb->IsUnreachable() || bb->GetKind() != BB::kBBFallthru) {
41             return false;
42         }
43     }
44     return (bb == &to);
45 }
46 
47 /* return true if insns in bb1 and bb2 are the same except the last goto insn. */
DoSameThing(const BB &bb1, const Insn &last1, const BB &bb2, const Insn &last2) const48 bool ChainingPattern::DoSameThing(const BB &bb1, const Insn &last1, const BB &bb2, const Insn &last2) const
49 {
50     const Insn *insn1 = bb1.GetFirstMachineInsn();
51     const Insn *insn2 = bb2.GetFirstMachineInsn();
52     while (insn1 != nullptr && insn1 != last1.GetNextMachineInsn() && insn2 != nullptr &&
53            insn2 != last2.GetNextMachineInsn()) {
54         if (!insn1->IsMachineInstruction()) {
55             insn1 = insn1->GetNext();
56             continue;
57         }
58         if (!insn2->IsMachineInstruction()) {
59             insn2 = insn2->GetNext();
60             continue;
61         }
62         if (insn1->GetMachineOpcode() != insn2->GetMachineOpcode()) {
63             return false;
64         }
65         uint32 opndNum = insn1->GetOperandSize();
66         for (uint32 i = 0; i < opndNum; ++i) {
67             Operand &op1 = insn1->GetOperand(i);
68             Operand &op2 = insn2->GetOperand(i);
69             if (&op1 == &op2) {
70                 continue;
71             }
72             if (!op1.Equals(op2)) {
73                 return false;
74             }
75         }
76         insn1 = insn1->GetNextMachineInsn();
77         insn2 = insn2->GetNextMachineInsn();
78     }
79     return (insn1 == last1.GetNextMachineInsn() && insn2 == last2.GetNextMachineInsn());
80 }
81 
82 /*
83  * BB2 can be merged into BB1, if
84  *   1. BB1's kind is fallthrough;
85  *   2. BB2 has only one predecessor which is BB1 and BB2 is not the lastbb
86  *   3. BB2 is neither catch BB nor switch case BB
87  */
MergeFallthuBB(BB &curBB)88 bool ChainingPattern::MergeFallthuBB(BB &curBB)
89 {
90     BB *sucBB = curBB.GetNext();
91     if (sucBB == nullptr || IsLabelInSwitchTable(sucBB->GetLabIdx()) ||
92         !cgFunc->GetTheCFG()->CanMerge(curBB, *sucBB)) {
93         return false;
94     }
95     if (curBB.IsAtomicBuiltInBB() || sucBB->IsAtomicBuiltInBB()) {
96         return false;
97     }
98     Log(curBB.GetId());
99     if (checkOnly) {
100         return false;
101     }
102     if (sucBB == cgFunc->GetLastBB()) {
103         cgFunc->SetLastBB(curBB);
104     }
105     cgFunc->GetTheCFG()->MergeBB(curBB, *sucBB, *cgFunc);
106     keepPosition = true;
107     return true;
108 }
109 
MergeGotoBB(BB &curBB, BB &sucBB)110 bool ChainingPattern::MergeGotoBB(BB &curBB, BB &sucBB)
111 {
112     Log(curBB.GetId());
113     if (checkOnly) {
114         return false;
115     }
116     cgFunc->GetTheCFG()->MergeBB(curBB, sucBB, *cgFunc);
117     keepPosition = true;
118     return true;
119 }
120 
MoveSuccBBAsCurBBNext(BB &curBB, BB &sucBB)121 bool ChainingPattern::MoveSuccBBAsCurBBNext(BB &curBB, BB &sucBB)
122 {
123     /*
124      * without the judge below, there is
125      * Assembler Error: CFI state restore without previous remember
126      */
127     if (sucBB.GetHasCfi() || (sucBB.GetFirstInsn() != nullptr && sucBB.GetFirstInsn()->IsCfiInsn())) {
128         return false;
129     }
130     Log(curBB.GetId());
131     if (checkOnly) {
132         return false;
133     }
134     /* put sucBB as curBB's next. */
135     DEBUG_ASSERT(sucBB.GetPrev() != nullptr, "the target of current goto BB will not be the first bb");
136     sucBB.GetPrev()->SetNext(sucBB.GetNext());
137     if (sucBB.GetNext() != nullptr) {
138         sucBB.GetNext()->SetPrev(sucBB.GetPrev());
139     }
140     sucBB.SetNext(curBB.GetNext());
141     DEBUG_ASSERT(curBB.GetNext() != nullptr, "current goto BB will not be the last bb");
142     curBB.GetNext()->SetPrev(&sucBB);
143     if (sucBB.GetId() == cgFunc->GetLastBB()->GetId()) {
144         cgFunc->SetLastBB(*(sucBB.GetPrev()));
145     } else if (curBB.GetId() == cgFunc->GetLastBB()->GetId()) {
146         cgFunc->SetLastBB(sucBB);
147     }
148     sucBB.SetPrev(&curBB);
149     curBB.SetNext(&sucBB);
150     if (curBB.GetLastMachineInsn() != nullptr) {
151         curBB.RemoveInsn(*curBB.GetLastMachineInsn());
152     }
153     curBB.SetKind(BB::kBBFallthru);
154     return true;
155 }
156 
RemoveGotoInsn(BB &curBB, BB &sucBB)157 bool ChainingPattern::RemoveGotoInsn(BB &curBB, BB &sucBB)
158 {
159     Log(curBB.GetId());
160     if (checkOnly) {
161         return false;
162     }
163     if (&sucBB != curBB.GetNext()) {
164         DEBUG_ASSERT(curBB.GetNext() != nullptr, "nullptr check");
165         curBB.ReplaceSucc(sucBB, *curBB.GetNext());
166         curBB.GetNext()->PushBackPreds(curBB);
167         sucBB.RemovePreds(curBB);
168     }
169     if (curBB.GetLastMachineInsn() != nullptr) {
170         curBB.RemoveInsn(*curBB.GetLastMachineInsn());
171     }
172     curBB.SetKind(BB::kBBFallthru);
173     return true;
174 }
175 
ClearCurBBAndResetTargetBB(BB &curBB, BB &sucBB)176 bool ChainingPattern::ClearCurBBAndResetTargetBB(BB &curBB, BB &sucBB)
177 {
178     if (curBB.GetHasCfi() || (curBB.GetFirstInsn() != nullptr && curBB.GetFirstInsn()->IsCfiInsn())) {
179         return false;
180     }
181     Insn *brInsn = nullptr;
182     for (brInsn = curBB.GetLastMachineInsn(); brInsn != nullptr; brInsn = brInsn->GetPrev()) {
183         if (brInsn->IsUnCondBranch()) {
184             break;
185         }
186     }
187     DEBUG_ASSERT(brInsn != nullptr, "goto BB has no branch");
188     BB *newTarget = sucBB.GetPrev();
189     DEBUG_ASSERT(newTarget != nullptr, "get prev bb failed in ChainingPattern::ClearCurBBAndResetTargetBB");
190     Insn *last1 = newTarget->GetLastMachineInsn();
191     if (newTarget->GetKind() == BB::kBBGoto) {
192         Insn *br = nullptr;
193         for (br = newTarget->GetLastMachineInsn();
194              newTarget->GetFirstInsn() != nullptr && br != newTarget->GetFirstInsn()->GetPrev(); br = br->GetPrev()) {
195             DEBUG_ASSERT(br != nullptr, "br should not be nullptr");
196             if (br->IsUnCondBranch()) {
197                 break;
198             }
199         }
200         DEBUG_ASSERT(br != nullptr, "goto BB has no branch");
201         last1 = br->GetPreviousMachineInsn();
202     }
203     if (last1 == nullptr) {
204         return false;
205     }
206     ASSERT_NOT_NULL(brInsn);
207     if (brInsn->GetPreviousMachineInsn()) {
208         if (!DoSameThing(*newTarget, *last1, curBB, *brInsn->GetPreviousMachineInsn())) {
209             return false;
210         }
211     }
212 
213     Log(curBB.GetId());
214     if (checkOnly) {
215         return false;
216     }
217 
218     LabelIdx tgtLabIdx = newTarget->GetLabIdx();
219     if (newTarget->GetLabIdx() == MIRLabelTable::GetDummyLabel()) {
220         tgtLabIdx = cgFunc->CreateLabel();
221         newTarget->AddLabel(tgtLabIdx);
222         cgFunc->SetLab2BBMap(tgtLabIdx, *newTarget);
223     }
224     LabelOperand &brTarget = cgFunc->GetOrCreateLabelOperand(tgtLabIdx);
225     brInsn->SetOperand(0, brTarget);
226     curBB.RemoveInsnSequence(*curBB.GetFirstInsn(), *brInsn->GetPrev());
227 
228     curBB.RemoveFromSuccessorList(sucBB);
229     curBB.PushBackSuccs(*newTarget);
230     sucBB.RemoveFromPredecessorList(curBB);
231     newTarget->PushBackPreds(curBB);
232 
233     sucBB.GetPrev()->SetUnreachable(false);
234     keepPosition = true;
235     return true;
236 }
237 
238 /*
239  * Following optimizations are performed:
240  * 1. Basic block merging
241  * 2. unnecessary jumps elimination
242  * 3. Remove duplicates Basic block.
243  */
Optimize(BB &curBB)244 bool ChainingPattern::Optimize(BB &curBB)
245 {
246     if (curBB.IsUnreachable()) {
247         return false;
248     }
249 
250     if (curBB.GetKind() == BB::kBBFallthru) {
251         return MergeFallthuBB(curBB);
252     }
253 
254     if (curBB.GetKind() == BB::kBBGoto && !curBB.IsEmpty()) {
255         Insn *last = curBB.GetLastMachineInsn();
256         if (last->IsTailCall()) {
257             return false;
258         }
259 
260         BB *sucBB = CGCFG::GetTargetSuc(curBB);
261         /*
262          * BB2 can be merged into BB1, if
263          *   1. BB1 ends with a goto;
264          *   2. BB2 has only one predecessor which is BB1
265          *   3. BB2 is of goto kind. Otherwise, the original fall through will be broken
266          *   4. BB2 is neither catch BB nor switch case BB
267          */
268         if (sucBB == nullptr) {
269             return false;
270         }
271         if (sucBB->GetKind() == BB::kBBGoto && !IsLabelInSwitchTable(sucBB->GetLabIdx()) &&
272             cgFunc->GetTheCFG()->CanMerge(curBB, *sucBB)) {
273             // BB9(curBB)   BB1
274             //  \           /
275             //   BB5(sucBB, gotoBB)
276             // for this case, should not merge BB5, BB9
277             if (sucBB->GetPreds().size() > 1) {
278                 return false;
279             }
280             return MergeGotoBB(curBB, *sucBB);
281         } else if (sucBB != &curBB && curBB.GetNext() != sucBB && sucBB != cgFunc->GetLastBB() &&
282                    !sucBB->IsPredecessor(*sucBB->GetPrev()) &&
283                    !(sucBB->GetNext() != nullptr && sucBB->GetNext()->IsPredecessor(*sucBB)) &&
284                    !IsLabelInSwitchTable(sucBB->GetLabIdx()) && curBB.GetNext() != nullptr) {
285             return MoveSuccBBAsCurBBNext(curBB, *sucBB);
286         }
287         /*
288          * Last goto instruction can be removed, if:
289          *  1. The goto target is physically the next one to current BB.
290          */
291         else if (sucBB == curBB.GetNext() ||
292                  (NoInsnBetween(curBB, *sucBB) && !IsLabelInSwitchTable(curBB.GetNext()->GetLabIdx()))) {
293             return RemoveGotoInsn(curBB, *sucBB);
294         }
295         /*
296          * Clear curBB and target it to sucBB->GetPrev()
297          *  if sucBB->GetPrev() and curBB's insns are the same.
298          *
299          * curBB:           curBB:
300          *   insn_x0          b prevbb
301          *   b sucBB        ...
302          * ...         ==>  prevbb:
303          * prevbb:            insn_x0
304          *   insn_x0        sucBB:
305          * sucBB:
306          */
307         else if (sucBB != curBB.GetNext() && !curBB.IsSoloGoto() && !IsLabelInSwitchTable(curBB.GetLabIdx()) &&
308                  sucBB->GetKind() == BB::kBBReturn && sucBB->GetPreds().size() > 1 && sucBB->GetPrev() != nullptr &&
309                  sucBB->IsPredecessor(*sucBB->GetPrev()) &&
310                  (sucBB->GetPrev()->GetKind() == BB::kBBFallthru || sucBB->GetPrev()->GetKind() == BB::kBBGoto)) {
311             return ClearCurBBAndResetTargetBB(curBB, *sucBB);
312         }
313     }
314     return false;
315 }
316 
317 /*
318  * 1. relocate goto BB
319  * Found pattern             (1) ftBB->GetPreds().size() == 1
320  * curBB:                      curBB: cond1_br target
321  *       ...            ==>    brBB:
322  *       cond_br brBB           ...
323  * ftBB:                       targetBB: (ftBB,targetBB)
324  *       goto target         (2) ftBB->GetPreds().size() > 1
325  * brBB:                       curBB : cond1_br ftBB
326  *       ...                   brBB:
327  * targetBB                      ...
328  *                            ftBB
329  *                            targetBB
330  *
331  * 2. loopHeaderBB:              loopHeaderBB:
332  *      ...                        ...
333  *      cond_br loopExit:          cond_br loopHeaderBB
334  *    ftBB:                      ftBB:
335  *      goto loopHeaderBB:         goto loopExit
336  */
Optimize(BB &curBB)337 bool FlipBRPattern::Optimize(BB &curBB)
338 {
339     if (curBB.IsUnreachable()) {
340         return false;
341     }
342     if (curBB.GetKind() == BB::kBBIf && !curBB.IsEmpty()) {
343         BB *ftBB = curBB.GetNext();
344         DEBUG_ASSERT(ftBB != nullptr, "ftBB is null in  FlipBRPattern::Optimize");
345         BB *brBB = CGCFG::GetTargetSuc(curBB);
346         DEBUG_ASSERT(brBB != nullptr, "brBB is null in  FlipBRPattern::Optimize");
347         /* Check if it can be optimized */
348         if (ftBB->GetKind() == BB::kBBGoto && ftBB->GetNext() == brBB) {
349             Insn *curBBBranchInsn = nullptr;
350             for (curBBBranchInsn = curBB.GetLastMachineInsn(); curBBBranchInsn != nullptr;
351                  curBBBranchInsn = curBBBranchInsn->GetPrev()) {
352                 if (curBBBranchInsn->IsBranch()) {
353                     break;
354                 }
355             }
356             DEBUG_ASSERT(curBBBranchInsn != nullptr, "FlipBRPattern: curBB has no branch");
357             Insn *brInsn = nullptr;
358             for (brInsn = ftBB->GetLastMachineInsn(); brInsn != nullptr; brInsn = brInsn->GetPrev()) {
359                 if (brInsn->IsUnCondBranch()) {
360                     break;
361                 }
362             }
363             DEBUG_ASSERT(brInsn != nullptr, "FlipBRPattern: ftBB has no branch");
364 
365             /* Reverse the branch */
366             ASSERT_NOT_NULL(curBBBranchInsn);
367             uint32 targetIdx = GetJumpTargetIdx(*curBBBranchInsn);
368             MOperator mOp = FlipConditionOp(curBBBranchInsn->GetMachineOpcode());
369             if (mOp == 0) {
370                 return false;
371             }
372             auto it = ftBB->GetSuccsBegin();
373             BB *tgtBB = *it;
374             if (ftBB->GetPreds().size() == 1 &&
375                 (ftBB->IsSoloGoto() ||
376                  (!IsLabelInSwitchTable(tgtBB->GetLabIdx()) && cgFunc->GetTheCFG()->CanMerge(*ftBB, *tgtBB)))) {
377                 curBBBranchInsn->SetMOP(cgFunc->GetCG()->GetTargetMd(mOp));
378                 ASSERT_NOT_NULL(brInsn);
379                 Operand &brTarget = brInsn->GetOperand(GetJumpTargetIdx(*brInsn));
380                 curBBBranchInsn->SetOperand(targetIdx, brTarget);
381                 /* Insert ftBB's insn at the beginning of tgtBB. */
382                 if (!ftBB->IsSoloGoto()) {
383                     ftBB->RemoveInsn(*brInsn);
384                     tgtBB->InsertAtBeginning(*ftBB);
385                 }
386                 /* Patch pred and succ lists */
387                 ftBB->EraseSuccs(it);
388                 ftBB->PushBackSuccs(*brBB);
389                 it = curBB.GetSuccsBegin();
390                 CHECK_FATAL(*it != nullptr, "nullptr check");
391                 if (*it == brBB) {
392                     curBB.ReplaceSucc(it, *tgtBB);
393                 } else {
394                     ++it;
395                     curBB.ReplaceSucc(it, *tgtBB);
396                 }
397                 for (it = tgtBB->GetPredsBegin(); it != tgtBB->GetPredsEnd(); ++it) {
398                     if (*it == ftBB) {
399                         tgtBB->ErasePreds(it);
400                         break;
401                     }
402                 }
403                 tgtBB->PushBackPreds(curBB);
404                 for (it = brBB->GetPredsBegin(); it != brBB->GetPredsEnd(); ++it) {
405                     if (*it == &curBB) {
406                         brBB->ErasePreds(it);
407                         break;
408                     }
409                 }
410                 brBB->PushFrontPreds(*ftBB);
411                 /* Remove instructions from ftBB so curBB falls thru to brBB */
412                 ftBB->SetFirstInsn(nullptr);
413                 ftBB->SetLastInsn(nullptr);
414                 ftBB->SetKind(BB::kBBFallthru);
415             } else if (!IsLabelInSwitchTable(ftBB->GetLabIdx()) && !tgtBB->IsPredecessor(*tgtBB->GetPrev())) {
416                 curBBBranchInsn->SetMOP(cgFunc->GetCG()->GetTargetMd(mOp));
417                 LabelIdx tgtLabIdx = ftBB->GetLabIdx();
418                 if (ftBB->GetLabIdx() == MIRLabelTable::GetDummyLabel()) {
419                     tgtLabIdx = cgFunc->CreateLabel();
420                     ftBB->AddLabel(tgtLabIdx);
421                     cgFunc->SetLab2BBMap(tgtLabIdx, *ftBB);
422                 }
423                 LabelOperand &brTarget = cgFunc->GetOrCreateLabelOperand(tgtLabIdx);
424                 curBBBranchInsn->SetOperand(targetIdx, brTarget);
425                 curBB.SetNext(brBB);
426                 brBB->SetPrev(&curBB);
427                 ftBB->SetPrev(tgtBB->GetPrev());
428                 tgtBB->GetPrev()->SetNext(ftBB);
429                 ftBB->SetNext(tgtBB);
430                 tgtBB->SetPrev(ftBB);
431 
432                 ftBB->RemoveInsn(*brInsn);
433                 ftBB->SetKind(BB::kBBFallthru);
434             }
435         } else if (GetPhase() == kCfgoPostRegAlloc && ftBB->GetKind() == BB::kBBGoto &&
436                    loopInfo.GetBBLoopParent(curBB.GetId()) != nullptr &&
437                    loopInfo.GetBBLoopParent(curBB.GetId()) == loopInfo.GetBBLoopParent(ftBB->GetId()) &&
438                    ftBB->IsSoloGoto() &&
439                    &(loopInfo.GetBBLoopParent(ftBB->GetId())->GetHeader()) == *(ftBB->GetSuccsBegin()) &&
440                    !loopInfo.GetBBLoopParent(curBB.GetId())->Has(
441                        (curBB.GetSuccs().front() == ftBB) ? *curBB.GetSuccs().back() : *curBB.GetSuccs().front())) {
442             Insn *curBBBranchInsn = nullptr;
443             for (curBBBranchInsn = curBB.GetLastMachineInsn(); curBBBranchInsn != nullptr;
444                  curBBBranchInsn = curBBBranchInsn->GetPrev()) {
445                 if (curBBBranchInsn->IsBranch()) {
446                     break;
447                 }
448             }
449             DEBUG_ASSERT(curBBBranchInsn != nullptr, "FlipBRPattern: curBB has no branch");
450             Insn *brInsn = nullptr;
451             for (brInsn = ftBB->GetLastMachineInsn(); brInsn != nullptr; brInsn = brInsn->GetPrev()) {
452                 if (brInsn->IsUnCondBranch()) {
453                     break;
454                 }
455             }
456             DEBUG_ASSERT(brInsn != nullptr, "FlipBRPattern: ftBB has no branch");
457             uint32 condTargetIdx = GetJumpTargetIdx(*curBBBranchInsn);
458             LabelOperand &condTarget = static_cast<LabelOperand &>(curBBBranchInsn->GetOperand(condTargetIdx));
459             MOperator mOp = FlipConditionOp(curBBBranchInsn->GetMachineOpcode());
460             if (mOp == 0) {
461                 return false;
462             }
463             uint32 gotoTargetIdx = GetJumpTargetIdx(*brInsn);
464             LabelOperand &gotoTarget = static_cast<LabelOperand &>(brInsn->GetOperand(gotoTargetIdx));
465             curBBBranchInsn->SetMOP(cgFunc->GetCG()->GetTargetMd(mOp));
466             curBBBranchInsn->SetOperand(condTargetIdx, gotoTarget);
467             brInsn->SetOperand(gotoTargetIdx, condTarget);
468             auto it = ftBB->GetSuccsBegin();
469             BB *loopHeadBB = *it;
470             curBB.ReplaceSucc(*brBB, *loopHeadBB);
471             brBB->RemovePreds(curBB);
472             ftBB->ReplaceSucc(*loopHeadBB, *brBB);
473             loopHeadBB->RemovePreds(*ftBB);
474 
475             loopHeadBB->PushBackPreds(curBB);
476             brBB->PushBackPreds(*ftBB);
477         }
478     }
479     return false;
480 }
481 
482 /* remove a basic block that contains nothing */
Optimize(BB &curBB)483 bool EmptyBBPattern::Optimize(BB &curBB)
484 {
485     // Can not remove the BB whose address is referenced by adrp_label insn
486     if (curBB.IsUnreachable()) {
487         return false;
488     }
489     /* Empty bb and it's not a cleanupBB/returnBB/lastBB/catchBB. */
490     if (curBB.GetPrev() == nullptr || curBB.IsCleanup() || &curBB == cgFunc->GetLastBB() ||
491         curBB.GetKind() == BB::kBBReturn || IsLabelInSwitchTable(curBB.GetLabIdx())) {
492         return false;
493     }
494     if (curBB.GetFirstInsn() == nullptr && curBB.GetLastInsn() == nullptr) {
495         // empty BB
496         Log(curBB.GetId());
497         if (checkOnly) {
498             return false;
499         }
500 
501         BB *sucBB = CGCFG::GetTargetSuc(curBB);
502         if (sucBB == nullptr || sucBB->IsCleanup()) {
503             return false;
504         }
505         cgFunc->GetTheCFG()->RemoveBB(curBB);
506         /* removeBB may do nothing. since no need to repeat, always ret false here. */
507         return false;
508     } else if (!curBB.HasMachineInsn()) {
509         // BB only has dbg insn
510         Log(curBB.GetId());
511         if (checkOnly) {
512             return false;
513         }
514         BB *sucBB = CGCFG::GetTargetSuc(curBB);
515         if (sucBB == nullptr || sucBB->IsCleanup()) {
516             return false;
517         }
518         // For Now We try to sink first conservatively.
519         // All dbg insns should not be dropped. Later hoist or copy case should be considered.
520         if (curBB.NumSuccs() == 1) {
521             BB *succBB = curBB.GetSuccs().front();
522             succBB->InsertAtBeginning(curBB);
523             cgFunc->GetTheCFG()->RemoveBB(curBB);
524         }
525         return false;
526     }
527     return false;
528 }
529 
530 /*
531  * remove unreachable BB
532  * condition:
533  *   1. unreachable BB can't have cfi instruction when postcfgo.
534  */
Optimize(BB &curBB)535 bool UnreachBBPattern::Optimize(BB &curBB)
536 {
537     if (curBB.IsUnreachable()) {
538         Log(curBB.GetId());
539         if (checkOnly) {
540             return false;
541         }
542         /* if curBB in exitbbsvec,return false. */
543         if (cgFunc->IsExitBB(curBB)) {
544             // In C some bb follow noreturn calls should remain unreachable
545             curBB.SetUnreachable(cgFunc->GetMirModule().GetSrcLang() == kSrcLangC);
546             return false;
547         }
548 
549         if (curBB.GetHasCfi() || (curBB.GetFirstInsn() != nullptr && curBB.GetFirstInsn()->IsCfiInsn())) {
550             return false;
551         }
552 
553         // Indicates whether the curBB is removed
554         bool isRemoved = true;
555         if (curBB.GetPrev() != nullptr) {
556             curBB.GetPrev()->SetNext(curBB.GetNext());
557         }
558         if (curBB.GetNext() != nullptr) {
559             curBB.GetNext()->SetPrev(curBB.GetPrev());
560         } else {
561             cgFunc->SetLastBB(*(curBB.GetPrev()));
562         }
563         if (cgFunc->GetFirstBB() == cgFunc->GetLastBB() && cgFunc->GetFirstBB() != nullptr) {
564             isRemoved = false;
565         }
566 
567         /* flush after remove; */
568         for (BB *bb : curBB.GetSuccs()) {
569             bb->RemovePreds(curBB);
570             cgFunc->GetTheCFG()->FlushUnReachableStatusAndRemoveRelations(*bb, *cgFunc);
571         }
572         curBB.ClearSuccs();
573         // return always be false
574         if (!isRemoved) {
575             return false;
576         }
577     }
578     return false;
579 }
580 
GetAnalysisDependence(AnalysisDep &aDep) const581 void CgCfgo::GetAnalysisDependence(AnalysisDep &aDep) const
582 {
583     aDep.AddRequired<CgLoopAnalysis>();
584 }
585 
PhaseRun(maplebe::CGFunc &f)586 bool CgCfgo::PhaseRun(maplebe::CGFunc &f)
587 {
588     auto *loopInfo = GET_ANALYSIS(CgLoopAnalysis, f);
589     CFGOptimizer *cfgOptimizer = f.GetCG()->CreateCFGOptimizer(*GetPhaseMemPool(), f, *loopInfo);
590     DEBUG_ASSERT(cfgOptimizer != nullptr, "nullptr check");
591     if (f.IsAfterRegAlloc()) {
592         cfgOptimizer->SetPhase(kCfgoPostRegAlloc);
593     }
594     const std::string &funcClass = f.GetFunction().GetBaseClassName();
595     const std::string &funcName = f.GetFunction().GetBaseFuncName();
596     const std::string &name = funcClass + funcName;
597     if (CFGO_DUMP_NEWPM) {
598         DotGenerator::GenerateDot("before-cfgo", f, f.GetMirModule());
599     }
600     cfgOptimizer->Run(name);
601     if (CFGO_DUMP_NEWPM) {
602         f.GetTheCFG()->CheckCFG();
603         DotGenerator::GenerateDot("after-cfgo", f, f.GetMirModule());
604     }
605     return false;
606 }
607 MAPLE_TRANSFORM_PHASE_REGISTER_CANSKIP(CgCfgo, cfgo)
608 } /* namespace maplebe */
609