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