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