1 /**
2 * Copyright (c) 2021-2022 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 "basicblock.h"
17 #include "graph.h"
18 #include "inst.h"
19 #include "optimizer/analysis/loop_analyzer.h"
20 #include "optimizer/analysis/dominators_tree.h"
21
22 namespace panda::compiler {
23 class Inst;
BasicBlock(Graph * graph,uint32_t guest_pc)24 BasicBlock::BasicBlock(Graph *graph, uint32_t guest_pc)
25 : graph_(graph),
26 preds_(graph_->GetAllocator()->Adapter()),
27 succs_(graph_->GetAllocator()->Adapter()),
28 dom_blocks_(graph_->GetAllocator()->Adapter()),
29 guest_pc_(guest_pc)
30 {
31 }
32
IsStartBlock() const33 bool BasicBlock::IsStartBlock() const
34 {
35 return (graph_->GetStartBlock() == this);
36 }
IsEndBlock() const37 bool BasicBlock::IsEndBlock() const
38 {
39 return (graph_->GetEndBlock() == this);
40 }
IsPseudoControlFlowBlock() const41 bool BasicBlock::IsPseudoControlFlowBlock() const
42 {
43 return IsStartBlock() || IsEndBlock() || IsTryBegin() || IsTryEnd();
44 }
45
IsLoopHeader() const46 bool BasicBlock::IsLoopHeader() const
47 {
48 ASSERT(GetLoop() != nullptr);
49 return (GetLoop()->GetHeader() == this);
50 }
51
SplitBlockAfterInstruction(Inst * inst,bool make_edge)52 BasicBlock *BasicBlock::SplitBlockAfterInstruction(Inst *inst, bool make_edge)
53 {
54 ASSERT(inst != nullptr);
55 ASSERT(inst->GetBasicBlock() == this);
56 ASSERT(!IsStartBlock() && !IsEndBlock());
57
58 auto next_inst = inst->GetNext();
59 auto new_bb = GetGraph()->CreateEmptyBlock((next_inst != nullptr) ? next_inst->GetPc() : INVALID_PC);
60 new_bb->SetAllFields(this->GetAllFields());
61 GetLoop()->AppendBlock(new_bb);
62
63 for (; next_inst != nullptr; next_inst = next_inst->GetNext()) {
64 new_bb->AppendInst(next_inst);
65 }
66 inst->SetNext(nullptr);
67 last_inst_ = inst;
68 if (inst->IsPhi()) {
69 first_inst_ = nullptr;
70 }
71 for (auto succ : GetSuccsBlocks()) {
72 succ->ReplacePred(this, new_bb);
73 }
74 GetSuccsBlocks().clear();
75
76 ASSERT(GetSuccsBlocks().empty());
77 if (make_edge) {
78 AddSucc(new_bb);
79 }
80 return new_bb;
81 }
82
AddSucc(BasicBlock * succ,bool can_add_empty_block)83 void BasicBlock::AddSucc(BasicBlock *succ, bool can_add_empty_block)
84 {
85 auto it = std::find(succs_.begin(), succs_.end(), succ);
86 ASSERT_PRINT(it == succs_.end() || can_add_empty_block, "Uncovered case where empty block needed to fix CFG");
87 if (it != succs_.end() && can_add_empty_block) {
88 // If edge already exists we create empty block on it
89 auto empty_bb = GetGraph()->CreateEmptyBlock(GetGuestPc());
90 ReplaceSucc(succ, empty_bb);
91 succ->ReplacePred(this, empty_bb);
92 }
93 succs_.push_back(succ);
94 succ->GetPredsBlocks().push_back(this);
95 }
96
ReplaceSucc(const BasicBlock * prev_succ,BasicBlock * new_succ,bool can_add_empty_block)97 void BasicBlock::ReplaceSucc(const BasicBlock *prev_succ, BasicBlock *new_succ, bool can_add_empty_block)
98 {
99 auto it = std::find(succs_.begin(), succs_.end(), new_succ);
100 ASSERT_PRINT(it == succs_.end() || can_add_empty_block, "Uncovered case where empty block needed to fix CFG");
101 if (it != succs_.end() && can_add_empty_block) {
102 // If edge already exists we create empty block on it
103 auto empty_bb = GetGraph()->CreateEmptyBlock(GetGuestPc());
104 ReplaceSucc(new_succ, empty_bb);
105 new_succ->ReplacePred(this, empty_bb);
106 }
107 succs_[GetSuccBlockIndex(prev_succ)] = new_succ;
108 new_succ->preds_.push_back(this);
109 }
110
InsertNewBlockToSuccEdge(BasicBlock * succ)111 BasicBlock *BasicBlock::InsertNewBlockToSuccEdge(BasicBlock *succ)
112 {
113 auto block = GetGraph()->CreateEmptyBlock(succ->GetGuestPc());
114 this->ReplaceSucc(succ, block);
115 succ->ReplacePred(this, block);
116 return block;
117 }
118
InsertEmptyBlockBefore()119 BasicBlock *BasicBlock::InsertEmptyBlockBefore()
120 {
121 auto block = GetGraph()->CreateEmptyBlock(this->GetGuestPc());
122 for (auto pred : preds_) {
123 pred->ReplaceSucc(this, block);
124 this->RemovePred(pred);
125 }
126 block->AddSucc(this);
127 return block;
128 }
129
InsertBlockBeforeSucc(BasicBlock * block,BasicBlock * succ)130 void BasicBlock::InsertBlockBeforeSucc(BasicBlock *block, BasicBlock *succ)
131 {
132 this->ReplaceSucc(succ, block);
133 succ->ReplacePred(this, block);
134 }
135
RemovePhiProcessing(BasicBlock * bb,BasicBlock * succ)136 static void RemovePhiProcessing(BasicBlock *bb, BasicBlock *succ)
137 {
138 size_t num_preds = bb->GetPredsBlocks().size();
139
140 for (auto phi : succ->PhiInsts()) {
141 auto index = phi->CastToPhi()->GetPredBlockIndex(bb);
142 auto inst = phi->GetInput(index).GetInst();
143 if (inst->GetBasicBlock() == bb) { // When INST is from empty basic block ...
144 ASSERT(inst->IsPhi());
145 // ... we have to copy it's inputs into corresponding inputs of PHI
146 auto pred_bb = bb->GetPredBlockByIndex(0);
147 phi->SetInput(index, inst->CastToPhi()->GetPhiInput(pred_bb));
148 for (size_t i = 1; i < num_preds; i++) {
149 pred_bb = bb->GetPredBlockByIndex(i);
150 phi->AppendInput(inst->CastToPhi()->GetPhiInput(pred_bb));
151 }
152 } else { // otherwise, just copy inputs for new arrived predecessors
153 for (size_t i = 1; i < num_preds; i++) {
154 phi->AppendInput(inst);
155 }
156 }
157 }
158 // And now we should remove Phis from the empty block
159 for (auto phi : bb->PhiInstsSafe()) {
160 bb->RemoveInst(phi);
161 }
162 }
163
164 // Remove empty block with one successor, may have more than one predecessors and Phi(s)
RemoveEmptyBlock(bool irr_loop)165 void BasicBlock::RemoveEmptyBlock(bool irr_loop)
166 {
167 ASSERT(GetFirstInst() == nullptr);
168 ASSERT(!GetPredsBlocks().empty());
169 ASSERT(GetSuccsBlocks().size() == 1);
170 auto succ = succs_[0];
171
172 // Save old amount of predecessors in successor block
173 size_t succ_preds_num = succ->GetPredsBlocks().size();
174
175 size_t num_preds = preds_.size();
176 // If empty block had more than one predecessors
177 if (num_preds > 1) {
178 if (succ_preds_num > 1) {
179 // We have to process Phi instructions in successor block in a special way
180 RemovePhiProcessing(this, succ);
181 } else { // successor didn't have other predecessors, we are moving Phi(s) into successor
182 ASSERT(!succ->HasPhi());
183 for (auto phi : PhiInstsSafe()) {
184 succ->AppendPhi(phi);
185 }
186 first_phi_ = nullptr;
187 last_inst_ = nullptr;
188 }
189 }
190
191 // Set successor for all predecessor blocks, at the same time in successor we replace one predecessor
192 // and add others to the end (if there were many of them in empty block)
193 auto pred = preds_[0];
194 pred->succs_[pred->GetSuccBlockIndex(this)] = succ;
195 succ->preds_[succ->GetPredBlockIndex(this)] = pred;
196 for (size_t i = 1; i < num_preds; ++i) {
197 pred = preds_[i];
198 pred->succs_[pred->GetSuccBlockIndex(this)] = succ;
199 succ->preds_.push_back(pred);
200 }
201
202 ASSERT(GetLastInst() == nullptr);
203 ASSERT(GetLoop()->IsIrreducible() == irr_loop);
204 // N.B. info about Irreducible loop can not be fixed on the fly
205 if (!irr_loop) {
206 RemoveFixLoopInfo();
207 }
208 // Finally clean lists
209 preds_.clear();
210 succs_.clear();
211 }
212
FixLoopInfoHelper(BasicBlock * bb)213 static void FixLoopInfoHelper(BasicBlock *bb)
214 {
215 ASSERT(!bb->GetPredsBlocks().empty());
216 auto loop = bb->GetLoop();
217 auto first_pred = bb->GetPredBlockByIndex(0);
218 // Do not dup back-edge
219 if (loop->HasBackEdge(first_pred)) {
220 loop->RemoveBackEdge(bb);
221 } else {
222 loop->ReplaceBackEdge(bb, first_pred);
223 }
224 // If empty block has more than 1 predecessor, append others to the loop back-edges' list
225 for (size_t i = 1; i < bb->GetPredsBlocks().size(); ++i) {
226 auto pred = bb->GetPredBlockByIndex(i);
227 if (!loop->HasBackEdge(pred)) {
228 loop->AppendBackEdge(pred);
229 }
230 }
231 }
232
RemoveFixLoopInfo()233 void BasicBlock::RemoveFixLoopInfo()
234 {
235 auto loop = GetLoop();
236 ASSERT(loop != nullptr);
237 ASSERT(!loop->IsIrreducible());
238 while (!loop->IsRoot()) {
239 if (loop->HasBackEdge(this)) {
240 FixLoopInfoHelper(this);
241 }
242 loop = loop->GetOuterLoop();
243 }
244 if (this == GetLoop()->GetHeader()) {
245 GetLoop()->MoveHeaderToSucc();
246 }
247 GetLoop()->RemoveBlock(this);
248 }
249
250 /**
251 * Join single successor into single predecessor.
252 * Block must have one successor, and its successor must have one predecessor (this block).
253 * EXAMPLE:
254 * [1]
255 * |
256 * [2]
257 *
258 * turns into this:
259 * [1']
260 */
JoinSuccessorBlock()261 void BasicBlock::JoinSuccessorBlock()
262 {
263 ASSERT(!IsStartBlock());
264
265 ASSERT(GetSuccsBlocks().size() == 1);
266 auto succ = GetSuccessor(0);
267 ASSERT(!succ->IsEndBlock());
268
269 ASSERT(succ->GetPredsBlocks().size() == 1);
270 ASSERT(succ->GetPredBlockByIndex(0) == this);
271
272 // moving instructions from successor
273 ASSERT(!succ->HasPhi());
274 for (auto succ_inst : succ->Insts()) {
275 AppendInst(succ_inst);
276 }
277
278 // moving successor blocks from the successor
279 GetSuccsBlocks().clear();
280 for (auto succ_succ : succ->GetSuccsBlocks()) {
281 succ_succ->ReplacePred(succ, this);
282 }
283
284 // fixing loop information
285 // invariant: succ has one predecessor, so it cannot be a loop header
286 auto loop = succ->GetLoop();
287 ASSERT(loop != nullptr);
288 // Irreducible loop can not be fixed on the fly
289 if (loop->IsIrreducible()) {
290 GetGraph()->InvalidateAnalysis<LoopAnalyzer>();
291 } else {
292 // edge can have 2 successors, so it can be back-edge in 2 loops: own loop and outer loop
293 if (loop->HasBackEdge(succ)) {
294 loop->ReplaceBackEdge(succ, this);
295 }
296 if (auto outer_loop = loop->GetOuterLoop()) {
297 if (outer_loop->HasBackEdge(succ)) {
298 outer_loop->ReplaceBackEdge(succ, this);
299 }
300 }
301
302 for (auto inner_loop : loop->GetInnerLoops()) {
303 if (inner_loop->GetPreHeader() == succ) {
304 inner_loop->SetPreHeader(this);
305 }
306 }
307 loop->RemoveBlock(succ);
308 }
309
310 succ->first_inst_ = nullptr;
311 succ->last_inst_ = nullptr;
312 succ->GetPredsBlocks().clear();
313 succ->GetSuccsBlocks().clear();
314
315 this->bit_fields_ |= succ->bit_fields_;
316 // TODO (a.popov) replace by assert
317 if (succ->try_id_ != INVALID_ID) {
318 this->try_id_ = succ->try_id_;
319 }
320 GetGraph()->RemoveEmptyBlock(succ);
321 }
322
SelectsFixLoopInfo(BasicBlock * select_bb,BasicBlock * other)323 void BasicBlock::SelectsFixLoopInfo(BasicBlock *select_bb, BasicBlock *other)
324 {
325 // invariant: 'this' block has one predecessor, so it cannot be a loop header
326 auto loop = GetLoop();
327 ASSERT(loop != nullptr);
328 // Irreducible loop can not be fixed on the fly
329 if (loop->IsIrreducible()) {
330 GetGraph()->InvalidateAnalysis<LoopAnalyzer>();
331 } else {
332 if (loop->HasBackEdge(this)) {
333 loop->RemoveBackEdge(this);
334 }
335 for (auto inner_loop : loop->GetInnerLoops()) {
336 if (inner_loop->GetPreHeader() == this) {
337 inner_loop->SetPreHeader(select_bb);
338 break;
339 }
340 }
341 loop->RemoveBlock(this);
342 }
343
344 // Remove outgoing 'this->other' edge
345 RemoveSucc(other);
346 other->RemovePred(this);
347 // Disconnect
348 GetGraph()->RemoveEmptyBlock(this);
349 }
350
AppendPhi(Inst * inst)351 void BasicBlock::AppendPhi(Inst *inst)
352 {
353 ASSERT_PRINT(inst->IsPhi(), "Instruction must be phi");
354 inst->SetBasicBlock(this);
355 if (first_phi_ == nullptr) {
356 inst->SetNext(first_inst_);
357 if (first_inst_ != nullptr) {
358 first_inst_->SetPrev(inst);
359 }
360 first_phi_ = inst;
361 if (last_inst_ == nullptr) {
362 last_inst_ = inst;
363 }
364 } else {
365 if (first_inst_ != nullptr) {
366 Inst *prev = first_inst_->GetPrev();
367 ASSERT_PRINT(prev && prev->IsPhi(), "There is no phi in the block");
368 inst->SetPrev(prev);
369 prev->SetNext(inst);
370 inst->SetNext(first_inst_);
371 first_inst_->SetPrev(inst);
372 } else {
373 ASSERT_PRINT(last_inst_ && last_inst_->IsPhi(),
374 "If first_phi is defined and first_inst is undefined, last_inst must be phi");
375 last_inst_->SetNext(inst);
376 inst->SetPrev(last_inst_);
377 last_inst_ = inst;
378 }
379 }
380 }
381
382 template <bool to_end>
AddInst(Inst * inst)383 void BasicBlock::AddInst(Inst *inst)
384 {
385 ASSERT_PRINT(!inst->IsPhi(), "Instruction mustn't be phi");
386 inst->SetBasicBlock(this);
387 if (first_inst_ == nullptr) {
388 inst->SetPrev(last_inst_);
389 if (last_inst_ != nullptr) {
390 ASSERT(last_inst_->IsPhi());
391 last_inst_->SetNext(inst);
392 }
393 first_inst_ = inst;
394 last_inst_ = inst;
395 } else {
396 // NOLINTNEXTLINE(readability-braces-around-statements)
397 if constexpr (to_end) {
398 ASSERT_PRINT(last_inst_, "Last instruction is undefined");
399 inst->SetPrev(last_inst_);
400 last_inst_->SetNext(inst);
401 last_inst_ = inst;
402 // NOLINTNEXTLINE(readability-misleading-indentation)
403 } else {
404 auto first_prev = first_inst_->GetPrev();
405 if (first_prev != nullptr) {
406 first_prev->SetNext(inst);
407 }
408 inst->SetPrev(first_prev);
409 inst->SetNext(first_inst_);
410 first_inst_->SetPrev(inst);
411 first_inst_ = inst;
412 }
413 }
414 }
415
AppendRangeInst(Inst * range_first,Inst * range_last)416 void BasicBlock::AppendRangeInst(Inst *range_first, Inst *range_last)
417 {
418 #ifndef NDEBUG
419 ASSERT(range_first && range_last && range_first->IsDominate(range_last));
420 ASSERT(range_first->GetPrev() == nullptr);
421 ASSERT(range_last->GetNext() == nullptr);
422 auto inst_db = range_first;
423 while (inst_db != range_last) {
424 ASSERT_PRINT(!inst_db->IsPhi(), "Instruction mustn't be phi");
425 ASSERT_PRINT(inst_db->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
426 inst_db = inst_db->GetNext();
427 }
428 ASSERT_PRINT(!inst_db->IsPhi(), "Instruction mustn't be phi");
429 ASSERT_PRINT(inst_db->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
430 #endif
431
432 if (first_inst_ == nullptr) {
433 range_first->SetPrev(last_inst_);
434 if (last_inst_ != nullptr) {
435 ASSERT(last_inst_->IsPhi());
436 last_inst_->SetNext(range_first);
437 }
438 first_inst_ = range_first;
439 last_inst_ = range_last;
440 } else {
441 ASSERT_PRINT(last_inst_, "Last instruction is undefined");
442 range_first->SetPrev(last_inst_);
443 last_inst_->SetNext(range_first);
444 last_inst_ = range_last;
445 }
446 }
447
InsertAfter(Inst * inst,Inst * after)448 void BasicBlock::InsertAfter(Inst *inst, Inst *after)
449 {
450 ASSERT(inst && after);
451 ASSERT(inst->IsPhi() == after->IsPhi());
452 ASSERT(after->GetBasicBlock() == this);
453 ASSERT(inst->GetBasicBlock() == nullptr);
454 inst->SetBasicBlock(this);
455 Inst *next = after->GetNext();
456 inst->SetPrev(after);
457 inst->SetNext(next);
458 after->SetNext(inst);
459 if (next != nullptr) {
460 next->SetPrev(inst);
461 } else {
462 ASSERT(after == last_inst_);
463 last_inst_ = inst;
464 }
465 }
466
InsertBefore(Inst * inst,Inst * before)467 void BasicBlock::InsertBefore(Inst *inst, Inst *before)
468 {
469 ASSERT(inst && before);
470 ASSERT(inst->IsPhi() == before->IsPhi());
471 ASSERT(before->GetBasicBlock() == this);
472 ASSERT(inst->GetBasicBlock() == nullptr);
473 inst->SetBasicBlock(this);
474 Inst *prev = before->GetPrev();
475 inst->SetPrev(prev);
476 inst->SetNext(before);
477 before->SetPrev(inst);
478 if (prev != nullptr) {
479 prev->SetNext(inst);
480 }
481 if (before == first_phi_) {
482 first_phi_ = inst;
483 }
484 if (before == first_inst_) {
485 first_inst_ = inst;
486 }
487 }
488
InsertRangeBefore(Inst * range_first,Inst * range_last,Inst * before)489 void BasicBlock::InsertRangeBefore(Inst *range_first, Inst *range_last, Inst *before)
490 {
491 #ifndef NDEBUG
492 ASSERT(range_first && range_last && range_first->IsDominate(range_last));
493 ASSERT(before && !before->IsPhi());
494 ASSERT(range_first->GetPrev() == nullptr);
495 ASSERT(range_last->GetNext() == nullptr);
496 ASSERT(before->GetBasicBlock() == this);
497 auto inst_db = range_first;
498 while (inst_db != range_last) {
499 ASSERT_PRINT(!inst_db->IsPhi(), "Instruction mustn't be phi");
500 ASSERT_PRINT(inst_db->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
501 inst_db = inst_db->GetNext();
502 }
503 ASSERT_PRINT(!inst_db->IsPhi(), "Instruction mustn't be phi");
504 ASSERT_PRINT(inst_db->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
505 #endif
506
507 Inst *prev = before->GetPrev();
508 range_first->SetPrev(prev);
509 range_last->SetNext(before);
510 before->SetPrev(range_last);
511 if (prev != nullptr) {
512 prev->SetNext(range_first);
513 }
514 if (before == first_inst_) {
515 first_inst_ = range_first;
516 }
517 }
518
ReplaceInst(Inst * old_inst,Inst * new_inst)519 void BasicBlock::ReplaceInst(Inst *old_inst, Inst *new_inst)
520 {
521 ASSERT(old_inst && new_inst);
522 ASSERT(old_inst->IsPhi() == new_inst->IsPhi());
523 ASSERT(old_inst->GetBasicBlock() == this);
524 ASSERT(new_inst->GetBasicBlock() == nullptr);
525 new_inst->SetBasicBlock(this);
526 Inst *prev = old_inst->GetPrev();
527 Inst *next = old_inst->GetNext();
528
529 old_inst->SetBasicBlock(nullptr);
530 if (prev != nullptr) {
531 prev->SetNext(new_inst);
532 }
533 if (next != nullptr) {
534 next->SetPrev(new_inst);
535 }
536 new_inst->SetPrev(prev);
537 new_inst->SetNext(next);
538 if (first_phi_ == old_inst) {
539 first_phi_ = new_inst;
540 }
541 if (first_inst_ == old_inst) {
542 first_inst_ = new_inst;
543 }
544 if (last_inst_ == old_inst) {
545 last_inst_ = new_inst;
546 }
547
548 if (graph_->IsInstThrowable(old_inst)) {
549 graph_->ReplaceThrowableInst(old_inst, new_inst);
550 }
551 }
552
EraseInst(Inst * inst,bool will_be_moved)553 void BasicBlock::EraseInst(Inst *inst, [[maybe_unused]] bool will_be_moved)
554 {
555 ASSERT(will_be_moved || !GetGraph()->IsInstThrowable(inst));
556 Inst *prev = inst->GetPrev();
557 Inst *next = inst->GetNext();
558
559 ASSERT(inst->GetBasicBlock() == this);
560 inst->SetBasicBlock(nullptr);
561 if (prev != nullptr) {
562 prev->SetNext(next);
563 }
564 if (next != nullptr) {
565 next->SetPrev(prev);
566 }
567 inst->SetPrev(nullptr);
568 inst->SetNext(nullptr);
569 if (inst == first_phi_) {
570 first_phi_ = (next != nullptr && next->IsPhi()) ? next : nullptr;
571 }
572 if (inst == first_inst_) {
573 first_inst_ = next;
574 }
575 if (inst == last_inst_) {
576 last_inst_ = prev;
577 }
578 }
579
RemoveInst(Inst * inst)580 void BasicBlock::RemoveInst(Inst *inst)
581 {
582 inst->RemoveUsers();
583 ASSERT(!inst->HasUsers());
584 inst->RemoveInputs();
585 if (inst->GetOpcode() == Opcode::Constant) {
586 graph_->RemoveConstFromList(static_cast<ConstantInst *>(inst));
587 }
588
589 if (graph_->IsInstThrowable(inst)) {
590 graph_->RemoveThrowableInst(inst);
591 }
592 EraseInst(inst);
593 }
594
Clear()595 void BasicBlock::Clear()
596 {
597 for (auto inst : AllInstsSafeReverse()) {
598 RemoveInst(inst);
599 }
600 }
601
602 /*
603 * Check if this block is dominate other
604 */
IsDominate(const BasicBlock * other) const605 bool BasicBlock::IsDominate(const BasicBlock *other) const
606 {
607 if (other == this) {
608 return true;
609 }
610 ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
611 BasicBlock *dom_block = other->GetDominator();
612 while (dom_block != nullptr) {
613 if (dom_block == this) {
614 return true;
615 }
616 // Otherwise we are in infinite loop!?
617 ASSERT(dom_block != dom_block->GetDominator());
618 dom_block = dom_block->GetDominator();
619 }
620 return false;
621 }
622
CreateImmediateDominator()623 BasicBlock *BasicBlock::CreateImmediateDominator()
624 {
625 ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
626 auto dominator = GetGraph()->CreateEmptyBlock();
627 GetGraph()->GetAnalysis<DominatorsTree>().SetValid(true);
628 if (GetDominator() != nullptr) {
629 GetDominator()->RemoveDominatedBlock(this);
630 GetDominator()->AddDominatedBlock(dominator);
631 dominator->SetDominator(GetDominator());
632 }
633 dominator->AddDominatedBlock(this);
634 SetDominator(dominator);
635 return dominator;
636 }
637
GetDominator() const638 BasicBlock *BasicBlock::GetDominator() const
639 {
640 ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
641 return dominator_;
642 }
643
GetDominatedBlocks() const644 const ArenaVector<BasicBlock *> &BasicBlock::GetDominatedBlocks() const
645 {
646 ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
647 return dom_blocks_;
648 }
649
PhiInsts() const650 PhiInstIter BasicBlock::PhiInsts() const
651 {
652 return PhiInstIter(*this);
653 }
Insts() const654 InstIter BasicBlock::Insts() const
655 {
656 return InstIter(*this);
657 }
AllInsts() const658 AllInstIter BasicBlock::AllInsts() const
659 {
660 return AllInstIter(*this);
661 }
662
InstsReverse() const663 InstReverseIter BasicBlock::InstsReverse() const
664 {
665 return InstReverseIter(*this);
666 }
667
PhiInstsSafe() const668 PhiInstSafeIter BasicBlock::PhiInstsSafe() const
669 {
670 return PhiInstSafeIter(*this);
671 }
InstsSafe() const672 InstSafeIter BasicBlock::InstsSafe() const
673 {
674 return InstSafeIter(*this);
675 }
AllInstsSafe() const676 AllInstSafeIter BasicBlock::AllInstsSafe() const
677 {
678 return AllInstSafeIter(*this);
679 }
680
PhiInstsSafeReverse() const681 PhiInstSafeReverseIter BasicBlock::PhiInstsSafeReverse() const
682 {
683 return PhiInstSafeReverseIter(*this);
684 }
InstsSafeReverse() const685 InstSafeReverseIter BasicBlock::InstsSafeReverse() const
686 {
687 return InstSafeReverseIter(*this);
688 }
AllInstsSafeReverse() const689 AllInstSafeReverseIter BasicBlock::AllInstsSafeReverse() const
690 {
691 return AllInstSafeReverseIter(*this);
692 }
693
694 template void BasicBlock::AddInst<false>(Inst *inst);
695 template void BasicBlock::AddInst<true>(Inst *inst);
696
InsertBlockBefore(BasicBlock * block)697 void BasicBlock::InsertBlockBefore(BasicBlock *block)
698 {
699 for (auto pred : GetPredsBlocks()) {
700 pred->ReplaceSucc(this, block);
701 }
702 GetPredsBlocks().clear();
703 block->AddSucc(this);
704 }
705
Clone(Graph * target_graph) const706 BasicBlock *BasicBlock::Clone(Graph *target_graph) const
707 {
708 BasicBlock *clone = nullptr;
709 #ifndef NDEBUG
710 if (GetGraph() == target_graph) {
711 clone = target_graph->CreateEmptyBlock();
712 } else {
713 clone = target_graph->CreateEmptyBlock(GetId(), GetGuestPc());
714 }
715 #else
716 clone = target_graph->CreateEmptyBlock();
717 #endif
718 clone->SetAllFields(this->GetAllFields());
719 clone->try_id_ = GetTryId();
720 if (this->IsStartBlock()) {
721 target_graph->SetStartBlock(clone);
722 } else if (this->IsEndBlock()) {
723 target_graph->SetEndBlock(clone);
724 }
725 return clone;
726 }
727
GetFistThrowableInst() const728 Inst *BasicBlock::GetFistThrowableInst() const
729 {
730 if (!IsTry()) {
731 return nullptr;
732 }
733 for (auto inst : AllInsts()) {
734 if (GetGraph()->IsInstThrowable(inst)) {
735 return inst;
736 }
737 }
738 return nullptr;
739 }
740
InvalidateLoopIfIrreducible()741 void BasicBlock::InvalidateLoopIfIrreducible()
742 {
743 auto loop = GetLoop();
744 ASSERT(loop != nullptr);
745 if (IsLoopHeader() && loop->IsIrreducible()) {
746 GetGraph()->InvalidateAnalysis<LoopAnalyzer>();
747 }
748 }
749
BlocksPathDfsSearch(Marker marker,BasicBlock * block,const BasicBlock * target_block,const BasicBlock * exclude_block)750 bool BlocksPathDfsSearch(Marker marker, BasicBlock *block, const BasicBlock *target_block,
751 const BasicBlock *exclude_block)
752 {
753 ASSERT(marker != UNDEF_MARKER);
754 if (block == target_block) {
755 return true;
756 }
757 block->SetMarker(marker);
758
759 for (auto succ_block : block->GetSuccsBlocks()) {
760 if (!succ_block->IsMarked(marker) && succ_block != exclude_block) {
761 if (BlocksPathDfsSearch(marker, succ_block, target_block, exclude_block)) {
762 return true;
763 }
764 }
765 }
766 return false;
767 }
768 } // namespace panda::compiler
769