• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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