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