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