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