• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 ark::compiler {
23 class Inst;
BasicBlock(Graph * graph,uint32_t guestPc)24 BasicBlock::BasicBlock(Graph *graph, uint32_t guestPc)
25     : graph_(graph),
26       preds_(graph_->GetAllocator()->Adapter()),
27       succs_(graph_->GetAllocator()),
28       domBlocks_(graph_->GetAllocator()->Adapter()),
29       guestPc_(guestPc)
30 {
31 }
32 
SetId(uint32_t id)33 void BasicBlock::SetId(uint32_t id)
34 {
35     bbId_ = id;
36 }
GetId() const37 uint32_t BasicBlock::GetId() const
38 {
39     return bbId_;
40 }
41 
GetPredsBlocks()42 ArenaVector<BasicBlock *> &BasicBlock::GetPredsBlocks()
43 {
44     return preds_;
45 }
GetPredsBlocks() const46 const ArenaVector<BasicBlock *> &BasicBlock::GetPredsBlocks() const
47 {
48     return preds_;
49 }
50 
GetSuccsBlocks()51 BasicBlock::SuccsVector &BasicBlock::GetSuccsBlocks()
52 {
53     return succs_;
54 }
GetSuccsBlocks() const55 const BasicBlock::SuccsVector &BasicBlock::GetSuccsBlocks() const
56 {
57     return succs_;
58 }
59 
GetSuccessor(size_t index) const60 BasicBlock *BasicBlock::GetSuccessor(size_t index) const
61 {
62     ASSERT(index < succs_.size());
63     return succs_[index];
64 }
65 
GetPredecessor(size_t index) const66 BasicBlock *BasicBlock::GetPredecessor(size_t index) const
67 {
68     ASSERT(index < preds_.size());
69     return preds_[index];
70 }
71 
IsInverted() const72 bool BasicBlock::IsInverted() const
73 {
74     return inverted_;
75 }
76 
SetHotness(int64_t hotness)77 void BasicBlock::SetHotness(int64_t hotness)
78 {
79     hotness_ = hotness;
80 }
81 
GetHotness() const82 int64_t BasicBlock::GetHotness() const
83 {
84     return hotness_;
85 }
86 
GetTrueSuccessor() const87 BasicBlock *BasicBlock::GetTrueSuccessor() const
88 {
89     ASSERT(!succs_.empty());
90     return succs_[TRUE_SUCC_IDX];
91 }
92 
GetFalseSuccessor() const93 BasicBlock *BasicBlock::GetFalseSuccessor() const
94 {
95     ASSERT(succs_.size() > 1);
96     return succs_[FALSE_SUCC_IDX];
97 }
98 
GetPredBlockIndex(const BasicBlock * block) const99 size_t BasicBlock::GetPredBlockIndex(const BasicBlock *block) const
100 {
101     auto it = std::find(preds_.begin(), preds_.end(), block);
102     ASSERT(it != preds_.end());
103     ASSERT(std::find(it + 1, preds_.end(), block) == preds_.end());
104     return std::distance(preds_.begin(), it);
105 }
106 
GetSuccBlockIndex(const BasicBlock * block) const107 size_t BasicBlock::GetSuccBlockIndex(const BasicBlock *block) const
108 {
109     auto it = std::find(succs_.begin(), succs_.end(), block);
110     ASSERT(it != succs_.end());
111     ASSERT(std::find(it + 1, succs_.end(), block) == succs_.end());
112     return std::distance(succs_.begin(), it);
113 }
114 
GetPredBlockByIndex(size_t index) const115 BasicBlock *BasicBlock::GetPredBlockByIndex(size_t index) const
116 {
117     ASSERT(index < preds_.size());
118     return preds_[index];
119 }
120 
GetGraph()121 Graph *BasicBlock::GetGraph()
122 {
123     return graph_;
124 }
125 
GetGraph() const126 const Graph *BasicBlock::GetGraph() const
127 {
128     return graph_;
129 }
130 
SetGraph(Graph * graph)131 void BasicBlock::SetGraph(Graph *graph)
132 {
133     graph_ = graph;
134 }
135 
SetGuestPc(uint32_t guestPc)136 void BasicBlock::SetGuestPc(uint32_t guestPc)
137 {
138     guestPc_ = guestPc;
139 }
140 
GetGuestPc() const141 uint32_t BasicBlock::GetGuestPc() const
142 {
143     return guestPc_;
144 }
145 
HasSucc(BasicBlock * succ)146 bool BasicBlock::HasSucc(BasicBlock *succ)
147 {
148     return std::find(succs_.begin(), succs_.end(), succ) != succs_.end();
149 }
150 
ReplacePred(BasicBlock * prevPred,BasicBlock * newPred)151 void BasicBlock::ReplacePred(BasicBlock *prevPred, BasicBlock *newPred)
152 {
153     preds_[GetPredBlockIndex(prevPred)] = newPred;
154     newPred->succs_.push_back(this);
155 }
156 
ReplaceTrueSuccessor(BasicBlock * newSucc)157 void BasicBlock::ReplaceTrueSuccessor(BasicBlock *newSucc)
158 {
159     ASSERT(!succs_.empty());
160     succs_[TRUE_SUCC_IDX] = newSucc;
161     newSucc->preds_.push_back(this);
162 }
163 
ReplaceFalseSuccessor(BasicBlock * newSucc)164 void BasicBlock::ReplaceFalseSuccessor(BasicBlock *newSucc)
165 {
166     ASSERT(succs_.size() > 1);
167     succs_[FALSE_SUCC_IDX] = newSucc;
168     newSucc->preds_.push_back(this);
169 }
170 
PrependInst(Inst * inst)171 void BasicBlock::PrependInst(Inst *inst)
172 {
173     AddInst<false>(inst);
174 }
175 // Insert new instruction(NOT PHI) in BasicBlock at the end of instructions
AppendInst(Inst * inst)176 void BasicBlock::AppendInst(Inst *inst)
177 {
178     AddInst<true>(inst);
179 }
AppendInsts(std::initializer_list<Inst * > && insts)180 void BasicBlock::AppendInsts(std::initializer_list<Inst *> &&insts)
181 {
182     for (auto inst : insts) {
183         AddInst<true>(inst);
184     }
185 }
186 
GetLastInst() const187 Inst *BasicBlock::GetLastInst() const
188 {
189     return lastInst_;
190 }
191 
IsEndWithThrowOrDeoptimize() const192 bool BasicBlock::IsEndWithThrowOrDeoptimize() const
193 {
194     if (lastInst_ == nullptr) {
195         return false;
196     }
197     return lastInst_->IsControlFlow() && lastInst_->CanThrow() && lastInst_->IsTerminator();
198 }
199 
IsEndWithThrow() const200 bool BasicBlock::IsEndWithThrow() const
201 {
202     if (lastInst_ == nullptr) {
203         return false;
204     }
205     return lastInst_->GetOpcode() == Opcode::Throw;
206 }
207 
GetFirstInst() const208 Inst *BasicBlock::GetFirstInst() const
209 {
210     return firstInst_;
211 }
212 
GetFirstPhi() const213 Inst *BasicBlock::GetFirstPhi() const
214 {
215     return firstPhi_;
216 }
217 
IsEmpty() const218 bool BasicBlock::IsEmpty() const
219 {
220     return firstInst_ == nullptr;
221 }
222 
HasPhi() const223 bool BasicBlock::HasPhi() const
224 {
225     return firstPhi_ != nullptr;
226 }
227 
SetDominator(BasicBlock * dominator)228 void BasicBlock::SetDominator(BasicBlock *dominator)
229 {
230     dominator_ = dominator;
231 }
ClearDominator()232 void BasicBlock::ClearDominator()
233 {
234     dominator_ = nullptr;
235 }
236 
AddDominatedBlock(BasicBlock * block)237 void BasicBlock::AddDominatedBlock(BasicBlock *block)
238 {
239     domBlocks_.push_back(block);
240 }
241 
RemoveDominatedBlock(BasicBlock * block)242 void BasicBlock::RemoveDominatedBlock(BasicBlock *block)
243 {
244     domBlocks_.erase(std::find(domBlocks_.begin(), domBlocks_.end(), block));
245 }
246 
ClearDominatedBlocks()247 void BasicBlock::ClearDominatedBlocks()
248 {
249     domBlocks_.clear();
250 }
251 
RemovePred(const BasicBlock * pred)252 void BasicBlock::RemovePred(const BasicBlock *pred)
253 {
254     ASSERT(GetPredBlockIndex(pred) < preds_.size());
255     preds_[GetPredBlockIndex(pred)] = preds_.back();
256     preds_.pop_back();
257 }
258 
RemovePred(size_t index)259 void BasicBlock::RemovePred(size_t index)
260 {
261     ASSERT(index < preds_.size());
262     preds_[index] = preds_.back();
263     preds_.pop_back();
264 }
265 
RemoveSucc(BasicBlock * succ)266 void BasicBlock::RemoveSucc(BasicBlock *succ)
267 {
268     auto it = std::find(succs_.begin(), succs_.end(), succ);
269     ASSERT(it != succs_.end());
270     succs_.erase(it);
271 }
272 
GetLoop() const273 Loop *BasicBlock::GetLoop() const
274 {
275     return loop_;
276 }
SetLoop(Loop * loop)277 void BasicBlock::SetLoop(Loop *loop)
278 {
279     loop_ = loop;
280 }
IsLoopValid() const281 bool BasicBlock::IsLoopValid() const
282 {
283     return GetLoop() != nullptr;
284 }
285 
SetNextLoop(Loop * loop)286 void BasicBlock::SetNextLoop(Loop *loop)
287 {
288     nextLoop_ = loop;
289 }
290 
GetNextLoop() const291 Loop *BasicBlock::GetNextLoop() const
292 {
293     return nextLoop_;
294 }
295 
IsLoopPreHeader() const296 bool BasicBlock::IsLoopPreHeader() const
297 {
298     return (nextLoop_ != nullptr);
299 }
300 
SetAllFields(uint32_t bitFields)301 void BasicBlock::SetAllFields(uint32_t bitFields)
302 {
303     bitFields_ = bitFields;
304 }
305 
GetAllFields() const306 uint32_t BasicBlock::GetAllFields() const
307 {
308     return bitFields_;
309 }
310 
SetMonitorEntryBlock(bool v)311 void BasicBlock::SetMonitorEntryBlock(bool v)
312 {
313     SetField<MonitorEntryBlock>(v);
314 }
315 
GetMonitorEntryBlock()316 bool BasicBlock::GetMonitorEntryBlock()
317 {
318     return GetField<MonitorEntryBlock>();
319 }
320 
SetMonitorExitBlock(bool v)321 void BasicBlock::SetMonitorExitBlock(bool v)
322 {
323     SetField<MonitorExitBlock>(v);
324 }
325 
GetMonitorExitBlock() const326 bool BasicBlock::GetMonitorExitBlock() const
327 {
328     return GetField<MonitorExitBlock>();
329 }
330 
SetMonitorBlock(bool v)331 void BasicBlock::SetMonitorBlock(bool v)
332 {
333     SetField<MonitorBlock>(v);
334 }
335 
GetMonitorBlock() const336 bool BasicBlock::GetMonitorBlock() const
337 {
338     return GetField<MonitorBlock>();
339 }
340 
SetCatch(bool v)341 void BasicBlock::SetCatch(bool v)
342 {
343     SetField<CatchBlock>(v);
344 }
345 
IsCatch() const346 bool BasicBlock::IsCatch() const
347 {
348     return GetField<CatchBlock>();
349 }
350 
SetCatchBegin(bool v)351 void BasicBlock::SetCatchBegin(bool v)
352 {
353     SetField<CatchBeginBlock>(v);
354 }
355 
IsCatchBegin() const356 bool BasicBlock::IsCatchBegin() const
357 {
358     return GetField<CatchBeginBlock>();
359 }
360 
SetTry(bool v)361 void BasicBlock::SetTry(bool v)
362 {
363     SetField<TryBlock>(v);
364 }
365 
IsTry() const366 bool BasicBlock::IsTry() const
367 {
368     return GetField<TryBlock>();
369 }
370 
SetTryBegin(bool v)371 void BasicBlock::SetTryBegin(bool v)
372 {
373     SetField<TryBeginBlock>(v);
374 }
375 
IsTryBegin() const376 bool BasicBlock::IsTryBegin() const
377 {
378     return GetField<TryBeginBlock>();
379 }
380 
SetTryEnd(bool v)381 void BasicBlock::SetTryEnd(bool v)
382 {
383     SetField<TryEndBlock>(v);
384 }
385 
IsTryEnd() const386 bool BasicBlock::IsTryEnd() const
387 {
388     return GetField<TryEndBlock>();
389 }
390 
SetOsrEntry(bool v)391 void BasicBlock::SetOsrEntry(bool v)
392 {
393     SetField<OsrEntry>(v);
394 }
395 
IsOsrEntry() const396 bool BasicBlock::IsOsrEntry() const
397 {
398     return GetField<OsrEntry>();
399 }
400 
CopyTryCatchProps(BasicBlock * block)401 void BasicBlock::CopyTryCatchProps(BasicBlock *block)
402 {
403     if (block->IsTry()) {
404         SetTry(true);
405         SetTryId(block->GetTryId());
406     }
407     if (block->IsCatch()) {
408         SetCatch(true);
409     }
410 }
411 
GetTryId() const412 uint32_t BasicBlock::GetTryId() const
413 {
414     return tryId_;
415 }
416 
SetTryId(uint32_t tryId)417 void BasicBlock::SetTryId(uint32_t tryId)
418 {
419     tryId_ = tryId;
420 }
421 
SetNeedsJump(bool v)422 void BasicBlock::SetNeedsJump(bool v)
423 {
424     SetField<JumpFlag>(v);
425 }
426 
NeedsJump() const427 bool BasicBlock::NeedsJump() const
428 {
429     return GetField<JumpFlag>();
430 }
431 
IsIfBlock() const432 bool BasicBlock::IsIfBlock() const
433 {
434     if (lastInst_ != nullptr) {
435         if (lastInst_->GetOpcode() == Opcode::If || lastInst_->GetOpcode() == Opcode::IfImm) {
436             return true;
437         }
438     }
439     return false;
440 }
441 
IsStartBlock() const442 bool BasicBlock::IsStartBlock() const
443 {
444     return (graph_->GetStartBlock() == this);
445 }
IsEndBlock() const446 bool BasicBlock::IsEndBlock() const
447 {
448     return (graph_->GetEndBlock() == this);
449 }
IsPseudoControlFlowBlock() const450 bool BasicBlock::IsPseudoControlFlowBlock() const
451 {
452     return IsStartBlock() || IsEndBlock() || IsTryBegin() || IsTryEnd();
453 }
454 
IsLoopHeader() const455 bool BasicBlock::IsLoopHeader() const
456 {
457     ASSERT(GetLoop() != nullptr);
458     return (GetLoop()->GetHeader() == this);
459 }
460 
IsLoopPostExit() const461 bool BasicBlock::IsLoopPostExit() const
462 {
463     for (auto innerLoop : GetLoop()->GetInnerLoops()) {
464         if (innerLoop->IsPostExitBlock(this)) {
465             return true;
466         }
467     }
468 
469     return false;
470 }
471 
IsTryCatch() const472 bool BasicBlock::IsTryCatch() const
473 {
474     return IsTry() || IsTryBegin() || IsTryEnd() || IsCatch() || IsCatchBegin();
475 }
476 
SplitBlockAfterInstruction(Inst * inst,bool makeEdge)477 BasicBlock *BasicBlock::SplitBlockAfterInstruction(Inst *inst, bool makeEdge)
478 {
479     ASSERT(inst != nullptr);
480     ASSERT(inst->GetBasicBlock() == this);
481     ASSERT(!IsStartBlock() && !IsEndBlock());
482 
483     auto nextInst = inst->GetNext();
484     auto newBb = GetGraph()->CreateEmptyBlock((nextInst != nullptr) ? nextInst->GetPc() : INVALID_PC);
485     newBb->SetAllFields(this->GetAllFields());
486     newBb->SetOsrEntry(false);
487     GetLoop()->AppendBlock(newBb);
488 
489     for (; nextInst != nullptr; nextInst = nextInst->GetNext()) {
490         newBb->AppendInst(nextInst);
491     }
492     inst->SetNext(nullptr);
493     lastInst_ = inst;
494     if (inst->IsPhi()) {
495         firstInst_ = nullptr;
496     }
497     for (auto succ : GetSuccsBlocks()) {
498         succ->ReplacePred(this, newBb);
499     }
500     GetSuccsBlocks().clear();
501 
502     ASSERT(GetSuccsBlocks().empty());
503     if (makeEdge) {
504         AddSucc(newBb);
505     }
506     return newBb;
507 }
508 
AddSucc(BasicBlock * succ,bool canAddEmptyBlock)509 void BasicBlock::AddSucc(BasicBlock *succ, bool canAddEmptyBlock)
510 {
511     auto it = std::find(succs_.begin(), succs_.end(), succ);
512     ASSERT_PRINT(it == succs_.end() || canAddEmptyBlock, "Uncovered case where empty block needed to fix CFG");
513     if (it != succs_.end() && canAddEmptyBlock) {
514         // If edge already exists we create empty block on it
515         auto emptyBb = GetGraph()->CreateEmptyBlock(GetGuestPc());
516         ReplaceSucc(succ, emptyBb);
517         succ->ReplacePred(this, emptyBb);
518     }
519     succs_.push_back(succ);
520     succ->GetPredsBlocks().push_back(this);
521 }
522 
ReplaceSucc(const BasicBlock * prevSucc,BasicBlock * newSucc,bool canAddEmptyBlock)523 void BasicBlock::ReplaceSucc(const BasicBlock *prevSucc, BasicBlock *newSucc, bool canAddEmptyBlock)
524 {
525     auto it = std::find(succs_.begin(), succs_.end(), newSucc);
526     ASSERT_PRINT(it == succs_.end() || canAddEmptyBlock, "Uncovered case where empty block needed to fix CFG");
527     if (it != succs_.end() && canAddEmptyBlock) {
528         // If edge already exists we create empty block on it
529         auto emptyBb = GetGraph()->CreateEmptyBlock(GetGuestPc());
530         ReplaceSucc(newSucc, emptyBb);
531         newSucc->ReplacePred(this, emptyBb);
532     }
533     succs_[GetSuccBlockIndex(prevSucc)] = newSucc;
534     newSucc->preds_.push_back(this);
535 }
536 
InsertNewBlockToSuccEdge(BasicBlock * succ)537 BasicBlock *BasicBlock::InsertNewBlockToSuccEdge(BasicBlock *succ)
538 {
539     auto block = GetGraph()->CreateEmptyBlock(succ->GetGuestPc());
540     this->ReplaceSucc(succ, block);
541     succ->ReplacePred(this, block);
542     return block;
543 }
544 
InsertEmptyBlockBefore()545 BasicBlock *BasicBlock::InsertEmptyBlockBefore()
546 {
547     auto block = GetGraph()->CreateEmptyBlock(this->GetGuestPc());
548     for (auto pred : preds_) {
549         pred->ReplaceSucc(this, block);
550         this->RemovePred(pred);
551     }
552     block->AddSucc(this);
553     return block;
554 }
555 
InsertBlockBeforeSucc(BasicBlock * block,BasicBlock * succ)556 void BasicBlock::InsertBlockBeforeSucc(BasicBlock *block, BasicBlock *succ)
557 {
558     this->ReplaceSucc(succ, block);
559     succ->ReplacePred(this, block);
560 }
561 
RemovePhiProcessing(BasicBlock * bb,BasicBlock * succ)562 static void RemovePhiProcessing(BasicBlock *bb, BasicBlock *succ)
563 {
564     size_t numPreds = bb->GetPredsBlocks().size();
565 
566     for (auto phi : succ->PhiInsts()) {
567         auto index = phi->CastToPhi()->GetPredBlockIndex(bb);
568         auto inst = phi->GetInput(index).GetInst();
569         if (inst->GetBasicBlock() == bb) {  // When INST is from empty basic block ...
570             ASSERT(inst->IsPhi());
571             // ... we have to copy it's inputs into corresponding inputs of PHI
572             auto predBb = bb->GetPredBlockByIndex(0);
573             phi->SetInput(index, inst->CastToPhi()->GetPhiInput(predBb));
574             for (size_t i = 1; i < numPreds; i++) {
575                 predBb = bb->GetPredBlockByIndex(i);
576                 phi->AppendInput(inst->CastToPhi()->GetPhiInput(predBb));
577             }
578         } else {  // otherwise, just copy inputs for new arrived predecessors
579             for (size_t i = 1; i < numPreds; i++) {
580                 phi->AppendInput(inst);
581             }
582         }
583     }
584     // And now we should remove Phis from the empty block
585     for (auto phi : bb->PhiInstsSafe()) {
586         bb->RemoveInst(phi);
587     }
588 }
589 
590 // Remove empty block with one successor, may have more than one predecessors and Phi(s)
RemoveEmptyBlock(bool irrLoop)591 void BasicBlock::RemoveEmptyBlock(bool irrLoop)
592 {
593     ASSERT(GetFirstInst() == nullptr);
594     ASSERT(!GetPredsBlocks().empty());
595     ASSERT(GetSuccsBlocks().size() == 1);
596     auto succ = succs_[0];
597 
598     // Save old amount of predecessors in successor block
599     size_t succPredsNum = succ->GetPredsBlocks().size();
600 
601     size_t numPreds = preds_.size();
602     // If empty block had more than one predecessors
603     if (numPreds > 1) {
604         if (succPredsNum > 1) {
605             // We have to process Phi instructions in successor block in a special way
606             RemovePhiProcessing(this, succ);
607         } else {  // successor didn't have other predecessors, we are moving Phi(s) into successor
608             ASSERT(!succ->HasPhi());
609             for (auto phi : PhiInstsSafe()) {
610                 succ->AppendPhi(phi);
611             }
612             firstPhi_ = nullptr;
613             lastInst_ = nullptr;
614         }
615     }
616 
617     // Set successor for all predecessor blocks, at the same time in successor we replace one predecessor
618     // and add others to the end (if there were many of them in empty block)
619     auto pred = preds_[0];
620     pred->succs_[pred->GetSuccBlockIndex(this)] = succ;
621     succ->preds_[succ->GetPredBlockIndex(this)] = pred;
622     for (size_t i = 1; i < numPreds; ++i) {
623         pred = preds_[i];
624         pred->succs_[pred->GetSuccBlockIndex(this)] = succ;
625         succ->preds_.push_back(pred);
626     }
627 
628     ASSERT(GetLastInst() == nullptr);
629     ASSERT(GetLoop()->IsIrreducible() == irrLoop);
630     // N.B. info about Irreducible loop can not be fixed on the fly
631     if (!irrLoop) {
632         RemoveFixLoopInfo();
633     }
634     // Finally clean lists
635     preds_.clear();
636     succs_.clear();
637 }
638 
FixLoopInfoHelper(BasicBlock * bb)639 static void FixLoopInfoHelper(BasicBlock *bb)
640 {
641     ASSERT(!bb->GetPredsBlocks().empty());
642     auto loop = bb->GetLoop();
643     auto firstPred = bb->GetPredBlockByIndex(0);
644     // Do not dup back-edge
645     if (loop->HasBackEdge(firstPred)) {
646         loop->RemoveBackEdge(bb);
647     } else {
648         loop->ReplaceBackEdge(bb, firstPred);
649     }
650     // If empty block has more than 1 predecessor, append others to the loop back-edges' list
651     for (size_t i = 1; i < bb->GetPredsBlocks().size(); ++i) {
652         auto pred = bb->GetPredBlockByIndex(i);
653         if (!loop->HasBackEdge(pred)) {
654             loop->AppendBackEdge(pred);
655         }
656     }
657 }
658 
RemoveFixLoopInfo()659 void BasicBlock::RemoveFixLoopInfo()
660 {
661     auto loop = GetLoop();
662     ASSERT(loop != nullptr);
663     ASSERT(!loop->IsIrreducible());
664     while (!loop->IsRoot()) {
665         if (loop->HasBackEdge(this)) {
666             FixLoopInfoHelper(this);
667         }
668         loop = loop->GetOuterLoop();
669     }
670     if (this == GetLoop()->GetHeader()) {
671         GetLoop()->MoveHeaderToSucc();
672     }
673     GetLoop()->RemoveBlock(this);
674 }
675 
676 /**
677  * Join single successor into single predecessor.
678  * Block must have one successor, and its successor must have one predecessor (this block).
679  * EXAMPLE:
680  *              [1]
681  *               |
682  *              [2]
683  *
684  * turns into this:
685  *              [1']
686  */
JoinSuccessorBlock()687 void BasicBlock::JoinSuccessorBlock()
688 {
689     ASSERT(!IsStartBlock());
690 
691     ASSERT(GetSuccsBlocks().size() == 1);
692     auto succ = GetSuccessor(0);
693     ASSERT(!succ->IsEndBlock());
694 
695     ASSERT(succ->GetPredsBlocks().size() == 1);
696     ASSERT(succ->GetPredBlockByIndex(0) == this);
697     ASSERT(!IsLoopPreHeader());
698     if (succ->IsLoopPreHeader()) {
699         succ->GetNextLoop()->SetPreHeader(this);
700     }
701 
702     // moving instructions from successor
703     ASSERT(!succ->HasPhi());
704     for (auto succInst : succ->Insts()) {
705         AppendInst(succInst);
706     }
707 
708     // moving successor blocks from the successor
709     GetSuccsBlocks().clear();
710     for (auto succSucc : succ->GetSuccsBlocks()) {
711         succSucc->ReplacePred(succ, this);
712     }
713 
714     if (GetGraph()->IsAnalysisValid<LoopAnalyzer>()) {
715         // fixing loop information
716         // invariant: succ has one predecessor, so it cannot be a loop header
717         auto loop = succ->GetLoop();
718         ASSERT(loop != nullptr);
719         // Irreducible loop can not be fixed on the fly
720         if (loop->IsIrreducible() || GetGraph()->IsThrowApplied()) {
721             GetGraph()->InvalidateAnalysis<LoopAnalyzer>();
722         } else {
723             // edge can have 2 successors, so it can be back-edge in 2 loops: own loop and outer loop
724             ReplaceSuccessorLoopBackEdges(loop, succ);
725             loop->RemoveBlock(succ);
726         }
727     }
728 
729     succ->firstInst_ = nullptr;
730     succ->lastInst_ = nullptr;
731     succ->GetPredsBlocks().clear();
732     succ->GetSuccsBlocks().clear();
733 
734     this->bitFields_ |= succ->bitFields_;
735     // NOTE (a.popov) replace by assert
736     if (succ->tryId_ != INVALID_ID) {
737         this->tryId_ = succ->tryId_;
738     }
739     GetGraph()->RemoveEmptyBlock(succ);
740 }
741 
ReplaceSuccessorLoopBackEdges(Loop * loop,BasicBlock * succ)742 void BasicBlock::ReplaceSuccessorLoopBackEdges(Loop *loop, BasicBlock *succ)
743 {
744     if (loop->HasBackEdge(succ)) {
745         loop->ReplaceBackEdge(succ, this);
746     }
747     for (auto outerLoop = loop->GetOuterLoop(); outerLoop != nullptr; outerLoop = outerLoop->GetOuterLoop()) {
748         if (outerLoop->HasBackEdge(succ)) {
749             outerLoop->ReplaceBackEdge(succ, this);
750         }
751     }
752     for (auto innerLoop : loop->GetInnerLoops()) {
753         if (innerLoop->GetPreHeader() == succ) {
754             innerLoop->SetPreHeader(this);
755         }
756     }
757 }
758 
759 /**
760  * Join successor block into the block, which have another successor;
761  * Used in if-conversion pass and fixes dataflow using Select instructions.
762  * @param succ is a successor block which must have one predecessor and
763  * one successor, function will remove Phi(s) from the latter successor.
764  * @param select_bb is a block to insert generated Select instructions.
765  * When 'select_bb' is nullptr, we generate Select(s) in 'this' block.
766  * @param swapped == true means 'succ' is False successor (instead of True).
767  * How conversion works in the following two cases:
768  *
769  * EXAMPLE 1 (Comes from TryTriangle in if_conversion.cpp):
770  *
771  *                [this] ('select_bb' == nullptr)
772  *                (last inst: if-jump)
773  *                 |  \
774  *                 |  [succ]
775  *                 |  (one inst: arithmetic)
776  *                 |  /
777  *                (first inst: phi)
778  *                [other]
779  *
780  * turns into this:
781  *                [this]
782  *                (arithmetic)
783  *                (select)
784  *                 |
785  *                 |
786  *                (may be phi if there are another predecessors)
787  *                [other]
788  *
789  * EXAMPLE 2 (Comes from TryDiamond in if_conversion.cpp):
790  *
791  *                [this]
792  *                (last inst: if-jump)
793  *                /   \
794  *       [select_bb]  [succ]
795  *     (arithmetic2)  (arithmetic1)
796  *                \   /
797  *                (first inst: phi)
798  *                [other]
799  *
800  * turns into this:
801  *                [this]
802  *                (arithmetic1)
803  *                 |
804  *                 |
805  *                [select_bb]
806  *                (arithmetic2)
807  *                (select)
808  *                 |
809  *                 |
810  *                (may be phi if there are another predecessors)
811  *                [other]
812  *
813  * Function returns whether we need DCE for If inputs.
814  */
JoinBlocksUsingSelect(BasicBlock * succ,BasicBlock * selectBb,bool swapped)815 void BasicBlock::JoinBlocksUsingSelect(BasicBlock *succ, BasicBlock *selectBb, bool swapped)
816 {
817     ASSERT(!IsStartBlock());
818     ASSERT(GetSuccsBlocks().size() == MAX_SUCCS_NUM);
819     ASSERT(succ == GetSuccessor(0) || succ == GetSuccessor(1));
820     ASSERT(!succ->IsEndBlock());
821     ASSERT(succ->GetPredsBlocks().size() == 1);
822     ASSERT(succ->GetPredBlockByIndex(0) == this);
823     ASSERT(succ->GetSuccsBlocks().size() == 1);
824     /**
825      * There are 2 steps in Join operation.
826      * Step 1. Move instructions from 'succ' into 'this'.
827      */
828     Inst *ifInst = GetLastInst();
829     SavedIfInfo ifInfo {succ,
830                         swapped,
831                         0,
832                         ConditionCode::CC_FIRST,
833                         DataType::NO_TYPE,
834                         ifInst->GetPc(),
835                         ifInst->GetOpcode(),
836                         ifInst->GetInput(0).GetInst(),
837                         nullptr};
838 
839     // Save necessary info
840     if (ifInfo.ifOpcode == Opcode::IfImm) {
841         ifInfo.ifImm = ifInst->CastToIfImm()->GetImm();
842         ifInfo.ifCc = ifInst->CastToIfImm()->GetCc();
843         ifInfo.ifType = ifInst->CastToIfImm()->GetOperandsType();
844     } else if (ifInfo.ifOpcode == Opcode::If) {
845         ifInfo.ifInput1 = ifInst->GetInput(1).GetInst();
846         ifInfo.ifCc = ifInst->CastToIf()->GetCc();
847         ifInfo.ifType = ifInst->CastToIf()->GetOperandsType();
848     } else {
849         UNREACHABLE();
850     }
851 
852     // Remove 'If' instruction
853     RemoveInst(ifInst);
854 
855     // Remove incoming 'this->succ' edge
856     RemoveSucc(succ);
857     succ->GetPredsBlocks().clear();
858 
859     // Main loop in "Step 1", moving instructions from successor.
860     ASSERT(!succ->HasPhi());
861     for (auto inst : succ->Insts()) {
862         AppendInst(inst);
863     }
864     succ->firstInst_ = nullptr;
865     succ->lastInst_ = nullptr;
866 
867     auto other = succ->GetSuccessor(0);
868     /**
869      * Step 2. Generate Select(s).
870      * We generate them in 'select_bb' if provided (another successor in Diamond case),
871      * or in 'this' block otherwise (Triangle case).
872      */
873     if (selectBb == nullptr) {
874         selectBb = this;
875     }
876     selectBb->GenerateSelects(&ifInfo);
877     succ->SelectsFixLoopInfo(selectBb, other);
878 }
879 
GenerateSelect(Inst * phi,Inst * inst1,Inst * inst2,const SavedIfInfo * ifInfo)880 void BasicBlock::GenerateSelect(Inst *phi, Inst *inst1, Inst *inst2, const SavedIfInfo *ifInfo)
881 {
882     auto other = ifInfo->succ->GetSuccessor(0);
883     Inst *select = nullptr;
884     ASSERT(GetGraph()->GetEncoder()->CanEncodeFloatSelect() || !DataType::IsFloatType(phi->GetType()));
885     if (ifInfo->ifOpcode == Opcode::IfImm) {
886         select = GetGraph()->CreateInstSelectImm(phi->GetType(), ifInfo->ifPc, ifInfo->swapped ? inst2 : inst1,
887                                                  ifInfo->swapped ? inst1 : inst2, ifInfo->ifInput0, ifInfo->ifImm,
888                                                  ifInfo->ifType, ifInfo->ifCc);
889     } else if (ifInfo->ifOpcode == Opcode::If) {
890         select = GetGraph()->CreateInstSelect(phi->GetType(), ifInfo->ifPc,
891                                               std::array<Inst *, 4U> {ifInfo->swapped ? inst2 : inst1,
892                                                                       ifInfo->swapped ? inst1 : inst2, ifInfo->ifInput0,
893                                                                       ifInfo->ifInput1},
894                                               ifInfo->ifType, ifInfo->ifCc);
895     } else {
896         UNREACHABLE();
897     }
898 
899     AppendInst(select);
900 
901     if (other->GetPredsBlocks().size() > 2U) {
902         // Change input (from this block) to new Select instruction
903         auto index = phi->CastToPhi()->GetPredBlockIndex(this);
904         phi->CastToPhi()->SetInput(index, select);
905         // Remove input from 'succ'
906         index = phi->CastToPhi()->GetPredBlockIndex(ifInfo->succ);
907         phi->CastToPhi()->RemoveInput(index);
908     } else {
909         // Remove Phi
910         phi->ReplaceUsers(select);
911         other->RemoveInst(phi);
912     }
913     // Select now must have users
914     ASSERT(select->HasUsers());
915 }
916 
GenerateSelects(const SavedIfInfo * ifInfo)917 void BasicBlock::GenerateSelects(const SavedIfInfo *ifInfo)
918 {
919     auto succ = ifInfo->succ;
920 
921     // The only successor whether we will check Phi(s)
922     auto other = succ->GetSuccessor(0);
923     constexpr auto TWO = 2;
924     ASSERT(other->GetPredsBlocks().size() >= TWO);
925 
926     // Main loop in "Step 2", generate select(s) and drop phi(s) when possible
927     for (auto phi : other->PhiInstsSafe()) {
928         size_t index1 = phi->CastToPhi()->GetPredBlockIndex(succ);
929         size_t index2 = phi->CastToPhi()->GetPredBlockIndex(this);
930         ASSERT(index1 != index2);
931 
932         auto inst1 = phi->GetInput(index1).GetInst();
933         auto inst2 = phi->GetInput(index2).GetInst();
934         if (inst1 == inst2) {
935             // No select needed
936             if (other->GetPredsBlocks().size() > TWO) {
937                 // Remove input from 'succ'
938                 auto index = phi->CastToPhi()->GetPredBlockIndex(succ);
939                 phi->CastToPhi()->RemoveInput(index);
940             } else {
941                 // Remove Phi
942                 phi->ReplaceUsers(inst1);
943                 other->RemoveInst(phi);
944             }
945             continue;
946         }
947 
948         GenerateSelect(phi, inst1, inst2, ifInfo);
949     }
950 }
951 
SelectsFixLoopInfo(BasicBlock * selectBb,BasicBlock * other)952 void BasicBlock::SelectsFixLoopInfo(BasicBlock *selectBb, BasicBlock *other)
953 {
954     // invariant: 'this' block has one predecessor, so it cannot be a loop header
955     auto loop = GetLoop();
956     ASSERT(loop != nullptr);
957     // Irreducible loop can not be fixed on the fly
958     if (loop->IsIrreducible()) {
959         GetGraph()->InvalidateAnalysis<LoopAnalyzer>();
960     } else {
961         if (loop->HasBackEdge(this)) {
962             loop->RemoveBackEdge(this);
963         }
964         for (auto innerLoop : loop->GetInnerLoops()) {
965             if (innerLoop->GetPreHeader() == this) {
966                 innerLoop->SetPreHeader(selectBb);
967                 break;
968             }
969         }
970         loop->RemoveBlock(this);
971     }
972 
973     // Remove outgoing 'this->other' edge
974     RemoveSucc(other);
975     other->RemovePred(this);
976     // Disconnect
977     GetGraph()->RemoveEmptyBlock(this);
978 }
979 
AppendPhi(Inst * inst)980 void BasicBlock::AppendPhi(Inst *inst)
981 {
982     ASSERT_PRINT(inst->IsPhi(), "Instruction must be phi");
983     inst->SetBasicBlock(this);
984     if (firstPhi_ == nullptr) {
985         inst->SetNext(firstInst_);
986         if (firstInst_ != nullptr) {
987             firstInst_->SetPrev(inst);
988         }
989         firstPhi_ = inst;
990         if (lastInst_ == nullptr) {
991             lastInst_ = inst;
992         }
993     } else {
994         if (firstInst_ != nullptr) {
995             Inst *prev = firstInst_->GetPrev();
996             ASSERT_PRINT(prev && prev->IsPhi(), "There is no phi in the block");
997             inst->SetPrev(prev);
998             prev->SetNext(inst);
999             inst->SetNext(firstInst_);
1000             firstInst_->SetPrev(inst);
1001         } else {
1002             ASSERT_PRINT(lastInst_ && lastInst_->IsPhi(),
1003                          "If first_phi is defined and first_inst is undefined, last_inst must be phi");
1004             lastInst_->SetNext(inst);
1005             inst->SetPrev(lastInst_);
1006             lastInst_ = inst;
1007         }
1008     }
1009 }
1010 
1011 template <bool TO_END>
AddInst(Inst * inst)1012 void BasicBlock::AddInst(Inst *inst)
1013 {
1014     ASSERT_PRINT(!inst->IsPhi(), "Instruction mustn't be phi");
1015     inst->SetBasicBlock(this);
1016     if (firstInst_ == nullptr) {
1017         inst->SetPrev(lastInst_);
1018         if (lastInst_ != nullptr) {
1019             ASSERT(lastInst_->IsPhi());
1020             lastInst_->SetNext(inst);
1021         }
1022         firstInst_ = inst;
1023         lastInst_ = inst;
1024     } else {
1025         // NOLINTNEXTLINE(readability-braces-around-statements)
1026         if constexpr (TO_END) {
1027             ASSERT_PRINT(lastInst_, "Last instruction is undefined");
1028             inst->SetPrev(lastInst_);
1029             lastInst_->SetNext(inst);
1030             lastInst_ = inst;
1031             // NOLINTNEXTLINE(readability-misleading-indentation)
1032         } else {
1033             auto firstPrev = firstInst_->GetPrev();
1034             if (firstPrev != nullptr) {
1035                 firstPrev->SetNext(inst);
1036             }
1037             inst->SetPrev(firstPrev);
1038             inst->SetNext(firstInst_);
1039             firstInst_->SetPrev(inst);
1040             firstInst_ = inst;
1041         }
1042     }
1043 }
1044 
AppendRangeInst(Inst * rangeFirst,Inst * rangeLast)1045 void BasicBlock::AppendRangeInst(Inst *rangeFirst, Inst *rangeLast)
1046 {
1047 #ifndef NDEBUG
1048     ASSERT(rangeFirst && rangeLast && rangeFirst->IsDominate(rangeLast));
1049     ASSERT(rangeFirst->GetPrev() == nullptr);
1050     ASSERT(rangeLast->GetNext() == nullptr);
1051     auto instDb = rangeFirst;
1052     while (instDb != rangeLast) {
1053         ASSERT_PRINT(!instDb->IsPhi(), "Instruction mustn't be phi");
1054         ASSERT_PRINT(instDb->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
1055         instDb = instDb->GetNext();
1056     }
1057     ASSERT_PRINT(!instDb->IsPhi(), "Instruction mustn't be phi");
1058     ASSERT_PRINT(instDb->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
1059 #endif
1060 
1061     if (firstInst_ == nullptr) {
1062         rangeFirst->SetPrev(lastInst_);
1063         if (lastInst_ != nullptr) {
1064             ASSERT(lastInst_->IsPhi());
1065             lastInst_->SetNext(rangeFirst);
1066         }
1067         firstInst_ = rangeFirst;
1068         lastInst_ = rangeLast;
1069     } else {
1070         ASSERT_PRINT(lastInst_, "Last instruction is undefined");
1071         rangeFirst->SetPrev(lastInst_);
1072         lastInst_->SetNext(rangeFirst);
1073         lastInst_ = rangeLast;
1074     }
1075 }
1076 
InsertAfter(Inst * inst,Inst * after)1077 void BasicBlock::InsertAfter(Inst *inst, Inst *after)
1078 {
1079     ASSERT(inst && after);
1080     ASSERT(inst->IsPhi() == after->IsPhi());
1081     ASSERT(after->GetBasicBlock() == this);
1082     ASSERT(inst->GetBasicBlock() == nullptr);
1083     inst->SetBasicBlock(this);
1084     Inst *next = after->GetNext();
1085     inst->SetPrev(after);
1086     inst->SetNext(next);
1087     after->SetNext(inst);
1088     if (next != nullptr) {
1089         next->SetPrev(inst);
1090     } else {
1091         ASSERT(after == lastInst_);
1092         lastInst_ = inst;
1093     }
1094 }
1095 
InsertBefore(Inst * inst,Inst * before)1096 void BasicBlock::InsertBefore(Inst *inst, Inst *before)
1097 {
1098     ASSERT(inst && before);
1099     ASSERT(inst->IsPhi() == before->IsPhi());
1100     ASSERT(before->GetBasicBlock() == this);
1101     ASSERT(inst->GetBasicBlock() == nullptr);
1102     inst->SetBasicBlock(this);
1103     Inst *prev = before->GetPrev();
1104     inst->SetPrev(prev);
1105     inst->SetNext(before);
1106     before->SetPrev(inst);
1107     if (prev != nullptr) {
1108         prev->SetNext(inst);
1109     }
1110     if (before == firstPhi_) {
1111         firstPhi_ = inst;
1112     }
1113     if (before == firstInst_) {
1114         firstInst_ = inst;
1115     }
1116 }
1117 
InsertRangeBefore(Inst * rangeFirst,Inst * rangeLast,Inst * before)1118 void BasicBlock::InsertRangeBefore(Inst *rangeFirst, Inst *rangeLast, Inst *before)
1119 {
1120 #ifndef NDEBUG
1121     ASSERT(rangeFirst && rangeLast && rangeFirst->IsDominate(rangeLast));
1122     ASSERT(before && !before->IsPhi());
1123     ASSERT(rangeFirst->GetPrev() == nullptr);
1124     ASSERT(rangeLast->GetNext() == nullptr);
1125     ASSERT(before->GetBasicBlock() == this);
1126     auto instDb = rangeFirst;
1127     while (instDb != rangeLast) {
1128         ASSERT_PRINT(!instDb->IsPhi(), "Instruction mustn't be phi");
1129         ASSERT_PRINT(instDb->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
1130         instDb = instDb->GetNext();
1131     }
1132     ASSERT_PRINT(!instDb->IsPhi(), "Instruction mustn't be phi");
1133     ASSERT_PRINT(instDb->GetBasicBlock() == this, "Inst::SetBasicBlock() should be called beforehand");
1134 #endif
1135 
1136     Inst *prev = before->GetPrev();
1137     rangeFirst->SetPrev(prev);
1138     rangeLast->SetNext(before);
1139     before->SetPrev(rangeLast);
1140     if (prev != nullptr) {
1141         prev->SetNext(rangeFirst);
1142     }
1143     if (before == firstInst_) {
1144         firstInst_ = rangeFirst;
1145     }
1146 }
1147 
ReplaceInst(Inst * oldInst,Inst * newInst)1148 void BasicBlock::ReplaceInst(Inst *oldInst, Inst *newInst)
1149 {
1150     ASSERT(oldInst && newInst);
1151     ASSERT(oldInst->IsPhi() == newInst->IsPhi());
1152     ASSERT(oldInst->GetBasicBlock() == this);
1153     ASSERT(newInst->GetBasicBlock() == nullptr);
1154     newInst->SetBasicBlock(this);
1155     Inst *prev = oldInst->GetPrev();
1156     Inst *next = oldInst->GetNext();
1157 
1158     oldInst->SetBasicBlock(nullptr);
1159     if (prev != nullptr) {
1160         prev->SetNext(newInst);
1161     }
1162     if (next != nullptr) {
1163         next->SetPrev(newInst);
1164     }
1165     newInst->SetPrev(prev);
1166     newInst->SetNext(next);
1167     if (firstPhi_ == oldInst) {
1168         firstPhi_ = newInst;
1169     }
1170     if (firstInst_ == oldInst) {
1171         firstInst_ = newInst;
1172     }
1173     if (lastInst_ == oldInst) {
1174         lastInst_ = newInst;
1175     }
1176 
1177     if (graph_->IsInstThrowable(oldInst)) {
1178         graph_->ReplaceThrowableInst(oldInst, newInst);
1179     }
1180 }
1181 
ReplaceInstByDeoptimize(Inst * inst)1182 void BasicBlock::ReplaceInstByDeoptimize(Inst *inst)
1183 {
1184     ASSERT(inst != nullptr);
1185     ASSERT(inst->GetBasicBlock() == this);
1186     auto ss = inst->GetSaveState();
1187     ASSERT(ss != nullptr);
1188     auto callInst = ss->GetCallerInst();
1189     // if inst in inlined method, we need to build all return.inlined before deoptimize to correct restore registers.
1190     while (callInst != nullptr && callInst->IsInlined()) {
1191         ss = callInst->GetSaveState();
1192         ASSERT(ss != nullptr);
1193         auto retInl = GetGraph()->CreateInstReturnInlined(DataType::NO_TYPE, INVALID_PC, ss);
1194         retInl->SetExtendedLiveness();
1195         InsertBefore(retInl, inst);
1196         callInst = ss->GetCallerInst();
1197     }
1198     // Replace Inst
1199     auto deopt = GetGraph()->CreateInstDeoptimize(DataType::NO_TYPE, inst->GetPc(), inst->GetSaveState());
1200     deopt->SetDeoptimizeType(inst);
1201     inst->RemoveInputs();
1202     inst->RemoveUsers();
1203     ReplaceInst(inst, deopt);
1204     // Build control flow
1205     BasicBlock *succ = GetSuccsBlocks()[0];
1206     if (GetLastInst() != deopt) {
1207         succ = SplitBlockAfterInstruction(deopt, true);
1208     }
1209     ASSERT(GetSuccsBlocks().size() == 1);
1210     GetGraph()->RemoveSuccessors(this);
1211     auto endBlock = GetGraph()->HasEndBlock() ? GetGraph()->GetEndBlock() : GetGraph()->CreateEndBlock();
1212     ASSERT(endBlock->GetGraph() != nullptr);
1213     this->AddSucc(endBlock);
1214     ASSERT(GetGraph()->IsAnalysisValid<LoopAnalyzer>());
1215     GetGraph()->DisconnectBlockRec(succ, true, false);
1216 }
1217 
RemoveOverflowCheck(Inst * inst)1218 void BasicBlock::RemoveOverflowCheck(Inst *inst)
1219 {
1220     // replace by Add/Sub
1221     Inst *newInst = nullptr;
1222     switch (inst->GetOpcode()) {
1223         case Opcode::AddOverflowCheck:
1224             newInst = GetGraph()->CreateInstAdd(inst->GetType(), inst->GetPc());
1225             break;
1226         case Opcode::SubOverflowCheck:
1227             newInst = GetGraph()->CreateInstSub(inst->GetType(), inst->GetPc());
1228             break;
1229         case Opcode::NegOverflowAndZeroCheck:
1230             newInst = GetGraph()->CreateInstNeg(inst->GetType(), inst->GetPc());
1231             break;
1232         default:
1233             UNREACHABLE();
1234     }
1235     // clone inputs, except savestate
1236     for (size_t i = 0; i < inst->GetInputsCount() - 1; ++i) {
1237         newInst->SetInput(i, inst->GetInput(i).GetInst());
1238     }
1239     inst->ReplaceUsers(newInst);
1240     inst->RemoveInputs();
1241     ReplaceInst(inst, newInst);
1242 }
1243 
EraseInst(Inst * inst,bool willBeMoved)1244 void BasicBlock::EraseInst(Inst *inst, [[maybe_unused]] bool willBeMoved)
1245 {
1246     ASSERT(willBeMoved || !GetGraph()->IsInstThrowable(inst));
1247     Inst *prev = inst->GetPrev();
1248     Inst *next = inst->GetNext();
1249 
1250     ASSERT(inst->GetBasicBlock() == this);
1251     inst->SetBasicBlock(nullptr);
1252     if (prev != nullptr) {
1253         prev->SetNext(next);
1254     }
1255     if (next != nullptr) {
1256         next->SetPrev(prev);
1257     }
1258     inst->SetPrev(nullptr);
1259     inst->SetNext(nullptr);
1260     if (inst == firstPhi_) {
1261         firstPhi_ = (next != nullptr && next->IsPhi()) ? next : nullptr;
1262     }
1263     if (inst == firstInst_) {
1264         firstInst_ = next;
1265     }
1266     if (inst == lastInst_) {
1267         lastInst_ = prev;
1268     }
1269 }
1270 
RemoveInst(Inst * inst)1271 void BasicBlock::RemoveInst(Inst *inst)
1272 {
1273     inst->RemoveUsers();
1274     ASSERT(!inst->HasUsers());
1275     inst->RemoveInputs();
1276     if (inst->GetOpcode() == Opcode::NullPtr) {
1277         graph_->UnsetNullPtrInst();
1278     } else if (inst->GetOpcode() == Opcode::LoadUndefined) {
1279         graph_->UnsetUndefinedInst();
1280     } else if (inst->GetOpcode() == Opcode::Constant) {
1281         graph_->RemoveConstFromList(static_cast<ConstantInst *>(inst));
1282     } else if (inst->GetOpcode() == Opcode::LoadUndefined) {
1283         graph_->UnsetUndefinedInst();
1284     }
1285 
1286     if (graph_->IsInstThrowable(inst)) {
1287         graph_->RemoveThrowableInst(inst);
1288     }
1289     EraseInst(inst);
1290 }
1291 
Clear()1292 void BasicBlock::Clear()
1293 {
1294     for (auto inst : AllInstsSafeReverse()) {
1295         RemoveInst(inst);
1296     }
1297 }
1298 
1299 /*
1300  * Check if this block is dominate other
1301  */
IsDominate(const BasicBlock * other) const1302 bool BasicBlock::IsDominate(const BasicBlock *other) const
1303 {
1304     if (other == this) {
1305         return true;
1306     }
1307     ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
1308     BasicBlock *domBlock = other->GetDominator();
1309     while (domBlock != nullptr) {
1310         if (domBlock == this) {
1311             return true;
1312         }
1313         // Otherwise we are in infinite loop!?
1314         ASSERT(domBlock != domBlock->GetDominator());
1315         domBlock = domBlock->GetDominator();
1316     }
1317     return false;
1318 }
1319 
CreateImmediateDominator()1320 BasicBlock *BasicBlock::CreateImmediateDominator()
1321 {
1322     ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
1323     auto dominator = GetGraph()->CreateEmptyBlock();
1324     GetGraph()->GetAnalysis<DominatorsTree>().SetValid(true);
1325     if (GetDominator() != nullptr) {
1326         GetDominator()->RemoveDominatedBlock(this);
1327         GetDominator()->AddDominatedBlock(dominator);
1328         dominator->SetDominator(GetDominator());
1329     }
1330     dominator->AddDominatedBlock(this);
1331     SetDominator(dominator);
1332     return dominator;
1333 }
1334 
GetDominator() const1335 BasicBlock *BasicBlock::GetDominator() const
1336 {
1337     ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
1338     return dominator_;
1339 }
1340 
GetDominatedBlocks() const1341 const ArenaVector<BasicBlock *> &BasicBlock::GetDominatedBlocks() const
1342 {
1343     ASSERT(GetGraph()->IsAnalysisValid<DominatorsTree>());
1344     return domBlocks_;
1345 }
1346 
PhiInsts() const1347 PhiInstIter BasicBlock::PhiInsts() const
1348 {
1349     return PhiInstIter(*this);
1350 }
Insts() const1351 InstIter BasicBlock::Insts() const
1352 {
1353     return InstIter(*this);
1354 }
AllInsts() const1355 AllInstIter BasicBlock::AllInsts() const
1356 {
1357     return AllInstIter(*this);
1358 }
1359 
InstsReverse() const1360 InstReverseIter BasicBlock::InstsReverse() const
1361 {
1362     return InstReverseIter(*this);
1363 }
1364 
PhiInstsSafe() const1365 PhiInstSafeIter BasicBlock::PhiInstsSafe() const
1366 {
1367     return PhiInstSafeIter(*this);
1368 }
InstsSafe() const1369 InstSafeIter BasicBlock::InstsSafe() const
1370 {
1371     return InstSafeIter(*this);
1372 }
AllInstsSafe() const1373 AllInstSafeIter BasicBlock::AllInstsSafe() const
1374 {
1375     return AllInstSafeIter(*this);
1376 }
1377 
PhiInstsSafeReverse() const1378 PhiInstSafeReverseIter BasicBlock::PhiInstsSafeReverse() const
1379 {
1380     return PhiInstSafeReverseIter(*this);
1381 }
InstsSafeReverse() const1382 InstSafeReverseIter BasicBlock::InstsSafeReverse() const
1383 {
1384     return InstSafeReverseIter(*this);
1385 }
AllInstsSafeReverse() const1386 AllInstSafeReverseIter BasicBlock::AllInstsSafeReverse() const
1387 {
1388     return AllInstSafeReverseIter(*this);
1389 }
1390 
1391 template void BasicBlock::AddInst<false>(Inst *inst);
1392 template void BasicBlock::AddInst<true>(Inst *inst);
1393 
InsertBlockBefore(BasicBlock * block)1394 void BasicBlock::InsertBlockBefore(BasicBlock *block)
1395 {
1396     for (auto pred : GetPredsBlocks()) {
1397         pred->ReplaceSucc(this, block);
1398     }
1399     GetPredsBlocks().clear();
1400     block->AddSucc(this);
1401 }
1402 
Clone(Graph * targetGraph) const1403 BasicBlock *BasicBlock::Clone(Graph *targetGraph) const
1404 {
1405     BasicBlock *clone = nullptr;
1406 #ifndef NDEBUG
1407     if (GetGraph() == targetGraph) {
1408         clone = targetGraph->CreateEmptyBlock();
1409     } else {
1410         clone = targetGraph->CreateEmptyBlock(GetId(), GetGuestPc());
1411     }
1412 #else
1413     clone = targetGraph->CreateEmptyBlock();
1414 #endif
1415     clone->SetAllFields(GetAllFields());
1416     clone->tryId_ = GetTryId();
1417     if (IsStartBlock()) {
1418         targetGraph->SetStartBlock(clone);
1419     } else if (IsEndBlock()) {
1420         targetGraph->SetEndBlock(clone);
1421     }
1422     return clone;
1423 }
1424 
GetFistThrowableInst() const1425 Inst *BasicBlock::GetFistThrowableInst() const
1426 {
1427     if (!IsTry()) {
1428         return nullptr;
1429     }
1430     for (auto inst : AllInsts()) {
1431         if (GetGraph()->IsInstThrowable(inst)) {
1432             return inst;
1433         }
1434     }
1435     return nullptr;
1436 }
1437 
FindSaveStateDeoptimize() const1438 Inst *BasicBlock::FindSaveStateDeoptimize() const
1439 {
1440     for (auto inst : InstsReverse()) {
1441         if (inst->GetOpcode() == Opcode::SaveStateDeoptimize) {
1442             return inst;
1443         }
1444     }
1445     return nullptr;
1446 }
1447 
InvalidateLoopIfIrreducible()1448 void BasicBlock::InvalidateLoopIfIrreducible()
1449 {
1450     auto loop = GetLoop();
1451     ASSERT(loop != nullptr);
1452     if (loop->IsIrreducible()) {
1453         GetGraph()->InvalidateAnalysis<LoopAnalyzer>();
1454     }
1455 }
1456 
CountInsts() const1457 uint32_t BasicBlock::CountInsts() const
1458 {
1459     uint32_t count = 0;
1460     for ([[maybe_unused]] auto inst : AllInsts()) {
1461         count++;
1462     }
1463     return count;
1464 }
1465 
BlocksPathDfsSearch(Marker marker,BasicBlock * block,const BasicBlock * targetBlock,const BasicBlock * excludeBlock)1466 bool BlocksPathDfsSearch(Marker marker, BasicBlock *block, const BasicBlock *targetBlock,
1467                          const BasicBlock *excludeBlock)
1468 {
1469     ASSERT(marker != UNDEF_MARKER);
1470     if (block == targetBlock) {
1471         return true;
1472     }
1473     block->SetMarker(marker);
1474 
1475     for (auto succBlock : block->GetSuccsBlocks()) {
1476         if (!succBlock->IsMarked(marker) && succBlock != excludeBlock) {
1477             if (BlocksPathDfsSearch(marker, succBlock, targetBlock, excludeBlock)) {
1478                 return true;
1479             }
1480         }
1481     }
1482     return false;
1483 }
1484 }  // namespace ark::compiler
1485