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