11cb0ef41Sopenharmony_ci// Copyright 2013 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h" 81cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 91cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h" 101cb0ef41Sopenharmony_ci 111cb0ef41Sopenharmony_cinamespace v8 { 121cb0ef41Sopenharmony_cinamespace internal { 131cb0ef41Sopenharmony_cinamespace compiler { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ciBasicBlock::BasicBlock(Zone* zone, Id id) 161cb0ef41Sopenharmony_ci : loop_number_(-1), 171cb0ef41Sopenharmony_ci rpo_number_(-1), 181cb0ef41Sopenharmony_ci deferred_(false), 191cb0ef41Sopenharmony_ci dominator_depth_(-1), 201cb0ef41Sopenharmony_ci dominator_(nullptr), 211cb0ef41Sopenharmony_ci rpo_next_(nullptr), 221cb0ef41Sopenharmony_ci loop_header_(nullptr), 231cb0ef41Sopenharmony_ci loop_end_(nullptr), 241cb0ef41Sopenharmony_ci loop_depth_(0), 251cb0ef41Sopenharmony_ci control_(kNone), 261cb0ef41Sopenharmony_ci control_input_(nullptr), 271cb0ef41Sopenharmony_ci nodes_(zone), 281cb0ef41Sopenharmony_ci successors_(zone), 291cb0ef41Sopenharmony_ci predecessors_(zone), 301cb0ef41Sopenharmony_ci#if DEBUG 311cb0ef41Sopenharmony_ci debug_info_(AssemblerDebugInfo(nullptr, nullptr, -1)), 321cb0ef41Sopenharmony_ci#endif 331cb0ef41Sopenharmony_ci id_(id) { 341cb0ef41Sopenharmony_ci} 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_cibool BasicBlock::LoopContains(BasicBlock* block) const { 371cb0ef41Sopenharmony_ci // RPO numbers must be initialized. 381cb0ef41Sopenharmony_ci DCHECK_LE(0, rpo_number_); 391cb0ef41Sopenharmony_ci DCHECK_LE(0, block->rpo_number_); 401cb0ef41Sopenharmony_ci if (loop_end_ == nullptr) return false; // This is not a loop. 411cb0ef41Sopenharmony_ci return block->rpo_number_ >= rpo_number_ && 421cb0ef41Sopenharmony_ci block->rpo_number_ < loop_end_->rpo_number_; 431cb0ef41Sopenharmony_ci} 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_civoid BasicBlock::AddSuccessor(BasicBlock* successor) { 461cb0ef41Sopenharmony_ci successors_.push_back(successor); 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_civoid BasicBlock::AddPredecessor(BasicBlock* predecessor) { 501cb0ef41Sopenharmony_ci predecessors_.push_back(predecessor); 511cb0ef41Sopenharmony_ci} 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_civoid BasicBlock::RemovePredecessor(size_t index) { 541cb0ef41Sopenharmony_ci predecessors_.erase(predecessors_.begin() + index); 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_civoid BasicBlock::AddNode(Node* node) { nodes_.push_back(node); } 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_civoid BasicBlock::set_control(Control control) { control_ = control; } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_civoid BasicBlock::set_control_input(Node* control_input) { 621cb0ef41Sopenharmony_ci if (!nodes_.empty() && control_input == nodes_.back()) { 631cb0ef41Sopenharmony_ci nodes_.pop_back(); 641cb0ef41Sopenharmony_ci } 651cb0ef41Sopenharmony_ci control_input_ = control_input; 661cb0ef41Sopenharmony_ci} 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_civoid BasicBlock::set_loop_depth(int32_t loop_depth) { 691cb0ef41Sopenharmony_ci loop_depth_ = loop_depth; 701cb0ef41Sopenharmony_ci} 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_civoid BasicBlock::set_rpo_number(int32_t rpo_number) { 731cb0ef41Sopenharmony_ci rpo_number_ = rpo_number; 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_civoid BasicBlock::set_loop_end(BasicBlock* loop_end) { loop_end_ = loop_end; } 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_civoid BasicBlock::set_loop_header(BasicBlock* loop_header) { 791cb0ef41Sopenharmony_ci loop_header_ = loop_header; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_civoid BasicBlock::TrimNodes(iterator new_end) { nodes_.erase(new_end, end()); } 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_civoid BasicBlock::ResetRPOInfo() { 851cb0ef41Sopenharmony_ci loop_number_ = -1; 861cb0ef41Sopenharmony_ci rpo_number_ = -1; 871cb0ef41Sopenharmony_ci dominator_depth_ = -1; 881cb0ef41Sopenharmony_ci dominator_ = nullptr; 891cb0ef41Sopenharmony_ci rpo_next_ = nullptr; 901cb0ef41Sopenharmony_ci loop_header_ = nullptr; 911cb0ef41Sopenharmony_ci loop_end_ = nullptr; 921cb0ef41Sopenharmony_ci loop_depth_ = 0; 931cb0ef41Sopenharmony_ci} 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci// static 961cb0ef41Sopenharmony_ciBasicBlock* BasicBlock::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { 971cb0ef41Sopenharmony_ci while (b1 != b2) { 981cb0ef41Sopenharmony_ci if (b1->dominator_depth() < b2->dominator_depth()) { 991cb0ef41Sopenharmony_ci b2 = b2->dominator(); 1001cb0ef41Sopenharmony_ci } else { 1011cb0ef41Sopenharmony_ci b1 = b1->dominator(); 1021cb0ef41Sopenharmony_ci } 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci return b1; 1051cb0ef41Sopenharmony_ci} 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_civoid BasicBlock::Print() { StdoutStream{} << *this << "\n"; } 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const BasicBlock& block) { 1101cb0ef41Sopenharmony_ci os << "id:" << block.id(); 1111cb0ef41Sopenharmony_ci#if DEBUG 1121cb0ef41Sopenharmony_ci AssemblerDebugInfo info = block.debug_info(); 1131cb0ef41Sopenharmony_ci if (info.name) os << info; 1141cb0ef41Sopenharmony_ci // Print predecessor blocks for better debugging. 1151cb0ef41Sopenharmony_ci const int kMaxDisplayedBlocks = 4; 1161cb0ef41Sopenharmony_ci int i = 0; 1171cb0ef41Sopenharmony_ci const BasicBlock* current_block = █ 1181cb0ef41Sopenharmony_ci while (current_block->PredecessorCount() > 0 && i++ < kMaxDisplayedBlocks) { 1191cb0ef41Sopenharmony_ci current_block = current_block->predecessors().front(); 1201cb0ef41Sopenharmony_ci os << " <= id:" << current_block->id(); 1211cb0ef41Sopenharmony_ci info = current_block->debug_info(); 1221cb0ef41Sopenharmony_ci if (info.name) os << info; 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci#endif 1251cb0ef41Sopenharmony_ci return os; 1261cb0ef41Sopenharmony_ci} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const BasicBlock::Control& c) { 1291cb0ef41Sopenharmony_ci switch (c) { 1301cb0ef41Sopenharmony_ci case BasicBlock::kNone: 1311cb0ef41Sopenharmony_ci return os << "none"; 1321cb0ef41Sopenharmony_ci case BasicBlock::kGoto: 1331cb0ef41Sopenharmony_ci return os << "goto"; 1341cb0ef41Sopenharmony_ci case BasicBlock::kCall: 1351cb0ef41Sopenharmony_ci return os << "call"; 1361cb0ef41Sopenharmony_ci case BasicBlock::kBranch: 1371cb0ef41Sopenharmony_ci return os << "branch"; 1381cb0ef41Sopenharmony_ci case BasicBlock::kSwitch: 1391cb0ef41Sopenharmony_ci return os << "switch"; 1401cb0ef41Sopenharmony_ci case BasicBlock::kDeoptimize: 1411cb0ef41Sopenharmony_ci return os << "deoptimize"; 1421cb0ef41Sopenharmony_ci case BasicBlock::kTailCall: 1431cb0ef41Sopenharmony_ci return os << "tailcall"; 1441cb0ef41Sopenharmony_ci case BasicBlock::kReturn: 1451cb0ef41Sopenharmony_ci return os << "return"; 1461cb0ef41Sopenharmony_ci case BasicBlock::kThrow: 1471cb0ef41Sopenharmony_ci return os << "throw"; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci UNREACHABLE(); 1501cb0ef41Sopenharmony_ci} 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const BasicBlock::Id& id) { 1531cb0ef41Sopenharmony_ci return os << id.ToSize(); 1541cb0ef41Sopenharmony_ci} 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ciSchedule::Schedule(Zone* zone, size_t node_count_hint) 1571cb0ef41Sopenharmony_ci : zone_(zone), 1581cb0ef41Sopenharmony_ci all_blocks_(zone), 1591cb0ef41Sopenharmony_ci nodeid_to_block_(zone), 1601cb0ef41Sopenharmony_ci rpo_order_(zone), 1611cb0ef41Sopenharmony_ci start_(NewBasicBlock()), 1621cb0ef41Sopenharmony_ci end_(NewBasicBlock()) { 1631cb0ef41Sopenharmony_ci nodeid_to_block_.reserve(node_count_hint); 1641cb0ef41Sopenharmony_ci} 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ciBasicBlock* Schedule::block(Node* node) const { 1671cb0ef41Sopenharmony_ci if (node->id() < static_cast<NodeId>(nodeid_to_block_.size())) { 1681cb0ef41Sopenharmony_ci return nodeid_to_block_[node->id()]; 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci return nullptr; 1711cb0ef41Sopenharmony_ci} 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_cibool Schedule::IsScheduled(Node* node) { 1741cb0ef41Sopenharmony_ci if (node->id() >= nodeid_to_block_.size()) return false; 1751cb0ef41Sopenharmony_ci return nodeid_to_block_[node->id()] != nullptr; 1761cb0ef41Sopenharmony_ci} 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ciBasicBlock* Schedule::GetBlockById(BasicBlock::Id block_id) { 1791cb0ef41Sopenharmony_ci DCHECK(block_id.ToSize() < all_blocks_.size()); 1801cb0ef41Sopenharmony_ci return all_blocks_[block_id.ToSize()]; 1811cb0ef41Sopenharmony_ci} 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_civoid Schedule::ClearBlockById(BasicBlock::Id block_id) { 1841cb0ef41Sopenharmony_ci DCHECK(block_id.ToSize() < all_blocks_.size()); 1851cb0ef41Sopenharmony_ci all_blocks_[block_id.ToSize()] = nullptr; 1861cb0ef41Sopenharmony_ci} 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_cibool Schedule::SameBasicBlock(Node* a, Node* b) const { 1891cb0ef41Sopenharmony_ci BasicBlock* block = this->block(a); 1901cb0ef41Sopenharmony_ci return block != nullptr && block == this->block(b); 1911cb0ef41Sopenharmony_ci} 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ciBasicBlock* Schedule::NewBasicBlock() { 1941cb0ef41Sopenharmony_ci BasicBlock* block = zone_->New<BasicBlock>( 1951cb0ef41Sopenharmony_ci zone_, BasicBlock::Id::FromSize(all_blocks_.size())); 1961cb0ef41Sopenharmony_ci all_blocks_.push_back(block); 1971cb0ef41Sopenharmony_ci return block; 1981cb0ef41Sopenharmony_ci} 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_civoid Schedule::PlanNode(BasicBlock* block, Node* node) { 2011cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_scheduler) { 2021cb0ef41Sopenharmony_ci StdoutStream{} << "Planning #" << node->id() << ":" 2031cb0ef41Sopenharmony_ci << node->op()->mnemonic() 2041cb0ef41Sopenharmony_ci << " for future add to id:" << block->id() << "\n"; 2051cb0ef41Sopenharmony_ci } 2061cb0ef41Sopenharmony_ci DCHECK_NULL(this->block(node)); 2071cb0ef41Sopenharmony_ci SetBlockForNode(block, node); 2081cb0ef41Sopenharmony_ci} 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_civoid Schedule::AddNode(BasicBlock* block, Node* node) { 2111cb0ef41Sopenharmony_ci if (FLAG_trace_turbo_scheduler) { 2121cb0ef41Sopenharmony_ci StdoutStream{} << "Adding #" << node->id() << ":" << node->op()->mnemonic() 2131cb0ef41Sopenharmony_ci << " to id:" << block->id() << "\n"; 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci DCHECK(this->block(node) == nullptr || this->block(node) == block); 2161cb0ef41Sopenharmony_ci block->AddNode(node); 2171cb0ef41Sopenharmony_ci SetBlockForNode(block, node); 2181cb0ef41Sopenharmony_ci} 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_civoid Schedule::AddGoto(BasicBlock* block, BasicBlock* succ) { 2211cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2221cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kGoto); 2231cb0ef41Sopenharmony_ci AddSuccessor(block, succ); 2241cb0ef41Sopenharmony_ci} 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci#if DEBUG 2271cb0ef41Sopenharmony_cinamespace { 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_cibool IsPotentiallyThrowingCall(IrOpcode::Value opcode) { 2301cb0ef41Sopenharmony_ci switch (opcode) { 2311cb0ef41Sopenharmony_ci#define BUILD_BLOCK_JS_CASE(Name, ...) case IrOpcode::k##Name: 2321cb0ef41Sopenharmony_ci JS_OP_LIST(BUILD_BLOCK_JS_CASE) 2331cb0ef41Sopenharmony_ci#undef BUILD_BLOCK_JS_CASE 2341cb0ef41Sopenharmony_ci case IrOpcode::kCall: 2351cb0ef41Sopenharmony_ci return true; 2361cb0ef41Sopenharmony_ci default: 2371cb0ef41Sopenharmony_ci return false; 2381cb0ef41Sopenharmony_ci } 2391cb0ef41Sopenharmony_ci} 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci} // namespace 2421cb0ef41Sopenharmony_ci#endif // DEBUG 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_civoid Schedule::AddCall(BasicBlock* block, Node* call, BasicBlock* success_block, 2451cb0ef41Sopenharmony_ci BasicBlock* exception_block) { 2461cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2471cb0ef41Sopenharmony_ci DCHECK(IsPotentiallyThrowingCall(call->opcode())); 2481cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kCall); 2491cb0ef41Sopenharmony_ci AddSuccessor(block, success_block); 2501cb0ef41Sopenharmony_ci AddSuccessor(block, exception_block); 2511cb0ef41Sopenharmony_ci SetControlInput(block, call); 2521cb0ef41Sopenharmony_ci} 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_civoid Schedule::AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock, 2551cb0ef41Sopenharmony_ci BasicBlock* fblock) { 2561cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2571cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); 2581cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kBranch); 2591cb0ef41Sopenharmony_ci AddSuccessor(block, tblock); 2601cb0ef41Sopenharmony_ci AddSuccessor(block, fblock); 2611cb0ef41Sopenharmony_ci SetControlInput(block, branch); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_civoid Schedule::AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks, 2651cb0ef41Sopenharmony_ci size_t succ_count) { 2661cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2671cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kSwitch, sw->opcode()); 2681cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kSwitch); 2691cb0ef41Sopenharmony_ci for (size_t index = 0; index < succ_count; ++index) { 2701cb0ef41Sopenharmony_ci AddSuccessor(block, succ_blocks[index]); 2711cb0ef41Sopenharmony_ci } 2721cb0ef41Sopenharmony_ci SetControlInput(block, sw); 2731cb0ef41Sopenharmony_ci} 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_civoid Schedule::AddTailCall(BasicBlock* block, Node* input) { 2761cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2771cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kTailCall); 2781cb0ef41Sopenharmony_ci SetControlInput(block, input); 2791cb0ef41Sopenharmony_ci if (block != end()) AddSuccessor(block, end()); 2801cb0ef41Sopenharmony_ci} 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_civoid Schedule::AddReturn(BasicBlock* block, Node* input) { 2831cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2841cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kReturn); 2851cb0ef41Sopenharmony_ci SetControlInput(block, input); 2861cb0ef41Sopenharmony_ci if (block != end()) AddSuccessor(block, end()); 2871cb0ef41Sopenharmony_ci} 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_civoid Schedule::AddDeoptimize(BasicBlock* block, Node* input) { 2901cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2911cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kDeoptimize); 2921cb0ef41Sopenharmony_ci SetControlInput(block, input); 2931cb0ef41Sopenharmony_ci if (block != end()) AddSuccessor(block, end()); 2941cb0ef41Sopenharmony_ci} 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_civoid Schedule::AddThrow(BasicBlock* block, Node* input) { 2971cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, block->control()); 2981cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kThrow); 2991cb0ef41Sopenharmony_ci SetControlInput(block, input); 3001cb0ef41Sopenharmony_ci if (block != end()) AddSuccessor(block, end()); 3011cb0ef41Sopenharmony_ci} 3021cb0ef41Sopenharmony_ci 3031cb0ef41Sopenharmony_civoid Schedule::InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch, 3041cb0ef41Sopenharmony_ci BasicBlock* tblock, BasicBlock* fblock) { 3051cb0ef41Sopenharmony_ci CHECK_NE(BasicBlock::kNone, block->control()); 3061cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, end->control()); 3071cb0ef41Sopenharmony_ci end->set_control(block->control()); 3081cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kBranch); 3091cb0ef41Sopenharmony_ci MoveSuccessors(block, end); 3101cb0ef41Sopenharmony_ci AddSuccessor(block, tblock); 3111cb0ef41Sopenharmony_ci AddSuccessor(block, fblock); 3121cb0ef41Sopenharmony_ci if (block->control_input() != nullptr) { 3131cb0ef41Sopenharmony_ci SetControlInput(end, block->control_input()); 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci SetControlInput(block, branch); 3161cb0ef41Sopenharmony_ci} 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_civoid Schedule::InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw, 3191cb0ef41Sopenharmony_ci BasicBlock** succ_blocks, size_t succ_count) { 3201cb0ef41Sopenharmony_ci CHECK_NE(BasicBlock::kNone, block->control()); 3211cb0ef41Sopenharmony_ci CHECK_EQ(BasicBlock::kNone, end->control()); 3221cb0ef41Sopenharmony_ci end->set_control(block->control()); 3231cb0ef41Sopenharmony_ci block->set_control(BasicBlock::kSwitch); 3241cb0ef41Sopenharmony_ci MoveSuccessors(block, end); 3251cb0ef41Sopenharmony_ci for (size_t index = 0; index < succ_count; ++index) { 3261cb0ef41Sopenharmony_ci AddSuccessor(block, succ_blocks[index]); 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci if (block->control_input() != nullptr) { 3291cb0ef41Sopenharmony_ci SetControlInput(end, block->control_input()); 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci SetControlInput(block, sw); 3321cb0ef41Sopenharmony_ci} 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_civoid Schedule::EnsureCFGWellFormedness() { 3351cb0ef41Sopenharmony_ci // Make a copy of all the blocks for the iteration, since adding the split 3361cb0ef41Sopenharmony_ci // edges will allocate new blocks. 3371cb0ef41Sopenharmony_ci BasicBlockVector all_blocks_copy(all_blocks_); 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci // Insert missing split edge blocks. 3401cb0ef41Sopenharmony_ci for (BasicBlock* block : all_blocks_copy) { 3411cb0ef41Sopenharmony_ci if (block->PredecessorCount() > 1) { 3421cb0ef41Sopenharmony_ci if (block != end_) { 3431cb0ef41Sopenharmony_ci EnsureSplitEdgeForm(block); 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci EliminateRedundantPhiNodes(); 3491cb0ef41Sopenharmony_ci} 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_civoid Schedule::EliminateRedundantPhiNodes() { 3521cb0ef41Sopenharmony_ci // Ensure that useless phi nodes that only have a single input, identical 3531cb0ef41Sopenharmony_ci // inputs, or are a self-referential loop phi, 3541cb0ef41Sopenharmony_ci // -- which can happen with the automatically generated code in the CSA and 3551cb0ef41Sopenharmony_ci // torque -- are pruned. 3561cb0ef41Sopenharmony_ci // Since we have strucured control flow, this is enough to minimize the number 3571cb0ef41Sopenharmony_ci // of phi nodes. 3581cb0ef41Sopenharmony_ci bool reached_fixed_point = false; 3591cb0ef41Sopenharmony_ci while (!reached_fixed_point) { 3601cb0ef41Sopenharmony_ci reached_fixed_point = true; 3611cb0ef41Sopenharmony_ci for (BasicBlock* block : all_blocks_) { 3621cb0ef41Sopenharmony_ci int predecessor_count = static_cast<int>(block->PredecessorCount()); 3631cb0ef41Sopenharmony_ci for (size_t node_pos = 0; node_pos < block->NodeCount(); ++node_pos) { 3641cb0ef41Sopenharmony_ci Node* node = block->NodeAt(node_pos); 3651cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kPhi) { 3661cb0ef41Sopenharmony_ci Node* first_input = node->InputAt(0); 3671cb0ef41Sopenharmony_ci bool inputs_equal = true; 3681cb0ef41Sopenharmony_ci for (int i = 1; i < predecessor_count; ++i) { 3691cb0ef41Sopenharmony_ci Node* input = node->InputAt(i); 3701cb0ef41Sopenharmony_ci if (input != first_input && input != node) { 3711cb0ef41Sopenharmony_ci inputs_equal = false; 3721cb0ef41Sopenharmony_ci break; 3731cb0ef41Sopenharmony_ci } 3741cb0ef41Sopenharmony_ci } 3751cb0ef41Sopenharmony_ci if (!inputs_equal) continue; 3761cb0ef41Sopenharmony_ci node->ReplaceUses(first_input); 3771cb0ef41Sopenharmony_ci node->Kill(); 3781cb0ef41Sopenharmony_ci block->RemoveNode(block->begin() + node_pos); 3791cb0ef41Sopenharmony_ci --node_pos; 3801cb0ef41Sopenharmony_ci reached_fixed_point = false; 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci } 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci } 3851cb0ef41Sopenharmony_ci} 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_civoid Schedule::EnsureSplitEdgeForm(BasicBlock* block) { 3881cb0ef41Sopenharmony_ci#ifdef DEBUG 3891cb0ef41Sopenharmony_ci DCHECK(block->PredecessorCount() > 1 && block != end_); 3901cb0ef41Sopenharmony_ci for (auto current_pred = block->predecessors().begin(); 3911cb0ef41Sopenharmony_ci current_pred != block->predecessors().end(); ++current_pred) { 3921cb0ef41Sopenharmony_ci BasicBlock* pred = *current_pred; 3931cb0ef41Sopenharmony_ci DCHECK_LE(pred->SuccessorCount(), 1); 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci#endif 3961cb0ef41Sopenharmony_ci} 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_civoid Schedule::MovePhis(BasicBlock* from, BasicBlock* to) { 3991cb0ef41Sopenharmony_ci for (size_t i = 0; i < from->NodeCount();) { 4001cb0ef41Sopenharmony_ci Node* node = from->NodeAt(i); 4011cb0ef41Sopenharmony_ci if (node->opcode() == IrOpcode::kPhi) { 4021cb0ef41Sopenharmony_ci to->AddNode(node); 4031cb0ef41Sopenharmony_ci from->RemoveNode(from->begin() + i); 4041cb0ef41Sopenharmony_ci DCHECK_EQ(nodeid_to_block_[node->id()], from); 4051cb0ef41Sopenharmony_ci nodeid_to_block_[node->id()] = to; 4061cb0ef41Sopenharmony_ci } else { 4071cb0ef41Sopenharmony_ci ++i; 4081cb0ef41Sopenharmony_ci } 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_civoid Schedule::PropagateDeferredMark() { 4131cb0ef41Sopenharmony_ci // Push forward the deferred block marks through newly inserted blocks and 4141cb0ef41Sopenharmony_ci // other improperly marked blocks until a fixed point is reached. 4151cb0ef41Sopenharmony_ci // TODO(danno): optimize the propagation 4161cb0ef41Sopenharmony_ci bool done = false; 4171cb0ef41Sopenharmony_ci while (!done) { 4181cb0ef41Sopenharmony_ci done = true; 4191cb0ef41Sopenharmony_ci for (auto block : all_blocks_) { 4201cb0ef41Sopenharmony_ci if (!block->deferred()) { 4211cb0ef41Sopenharmony_ci bool deferred = block->PredecessorCount() > 0; 4221cb0ef41Sopenharmony_ci for (auto pred : block->predecessors()) { 4231cb0ef41Sopenharmony_ci if (!pred->deferred() && (pred->rpo_number() < block->rpo_number())) { 4241cb0ef41Sopenharmony_ci deferred = false; 4251cb0ef41Sopenharmony_ci } 4261cb0ef41Sopenharmony_ci } 4271cb0ef41Sopenharmony_ci if (deferred) { 4281cb0ef41Sopenharmony_ci block->set_deferred(true); 4291cb0ef41Sopenharmony_ci done = false; 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci } 4341cb0ef41Sopenharmony_ci} 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_civoid Schedule::AddSuccessor(BasicBlock* block, BasicBlock* succ) { 4371cb0ef41Sopenharmony_ci block->AddSuccessor(succ); 4381cb0ef41Sopenharmony_ci succ->AddPredecessor(block); 4391cb0ef41Sopenharmony_ci} 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_civoid Schedule::MoveSuccessors(BasicBlock* from, BasicBlock* to) { 4421cb0ef41Sopenharmony_ci for (BasicBlock* const successor : from->successors()) { 4431cb0ef41Sopenharmony_ci to->AddSuccessor(successor); 4441cb0ef41Sopenharmony_ci for (BasicBlock*& predecessor : successor->predecessors()) { 4451cb0ef41Sopenharmony_ci if (predecessor == from) predecessor = to; 4461cb0ef41Sopenharmony_ci } 4471cb0ef41Sopenharmony_ci } 4481cb0ef41Sopenharmony_ci from->ClearSuccessors(); 4491cb0ef41Sopenharmony_ci} 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_civoid Schedule::SetControlInput(BasicBlock* block, Node* node) { 4521cb0ef41Sopenharmony_ci block->set_control_input(node); 4531cb0ef41Sopenharmony_ci SetBlockForNode(block, node); 4541cb0ef41Sopenharmony_ci} 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_civoid Schedule::SetBlockForNode(BasicBlock* block, Node* node) { 4571cb0ef41Sopenharmony_ci if (node->id() >= nodeid_to_block_.size()) { 4581cb0ef41Sopenharmony_ci nodeid_to_block_.resize(node->id() + 1); 4591cb0ef41Sopenharmony_ci } 4601cb0ef41Sopenharmony_ci nodeid_to_block_[node->id()] = block; 4611cb0ef41Sopenharmony_ci} 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const Schedule& s) { 4641cb0ef41Sopenharmony_ci for (BasicBlock* block : 4651cb0ef41Sopenharmony_ci ((s.RpoBlockCount() == 0) ? *s.all_blocks() : *s.rpo_order())) { 4661cb0ef41Sopenharmony_ci if (block == nullptr) continue; 4671cb0ef41Sopenharmony_ci if (block->rpo_number() == -1) { 4681cb0ef41Sopenharmony_ci os << "--- BLOCK id:" << block->id(); 4691cb0ef41Sopenharmony_ci } else { 4701cb0ef41Sopenharmony_ci os << "--- BLOCK B" << block->rpo_number(); 4711cb0ef41Sopenharmony_ci } 4721cb0ef41Sopenharmony_ci if (block->deferred()) os << " (deferred)"; 4731cb0ef41Sopenharmony_ci if (block->PredecessorCount() != 0) os << " <- "; 4741cb0ef41Sopenharmony_ci bool comma = false; 4751cb0ef41Sopenharmony_ci for (BasicBlock const* predecessor : block->predecessors()) { 4761cb0ef41Sopenharmony_ci if (comma) os << ", "; 4771cb0ef41Sopenharmony_ci comma = true; 4781cb0ef41Sopenharmony_ci if (predecessor->rpo_number() == -1) { 4791cb0ef41Sopenharmony_ci os << "id:" << predecessor->id(); 4801cb0ef41Sopenharmony_ci } else { 4811cb0ef41Sopenharmony_ci os << "B" << predecessor->rpo_number(); 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci } 4841cb0ef41Sopenharmony_ci os << " ---\n"; 4851cb0ef41Sopenharmony_ci for (Node* node : *block) { 4861cb0ef41Sopenharmony_ci os << " " << *node; 4871cb0ef41Sopenharmony_ci if (NodeProperties::IsTyped(node)) { 4881cb0ef41Sopenharmony_ci os << " : " << NodeProperties::GetType(node); 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci os << "\n"; 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci BasicBlock::Control control = block->control(); 4931cb0ef41Sopenharmony_ci if (control != BasicBlock::kNone) { 4941cb0ef41Sopenharmony_ci os << " "; 4951cb0ef41Sopenharmony_ci if (block->control_input() != nullptr) { 4961cb0ef41Sopenharmony_ci os << *block->control_input(); 4971cb0ef41Sopenharmony_ci } else { 4981cb0ef41Sopenharmony_ci os << "Goto"; 4991cb0ef41Sopenharmony_ci } 5001cb0ef41Sopenharmony_ci os << " -> "; 5011cb0ef41Sopenharmony_ci comma = false; 5021cb0ef41Sopenharmony_ci for (BasicBlock const* successor : block->successors()) { 5031cb0ef41Sopenharmony_ci if (comma) os << ", "; 5041cb0ef41Sopenharmony_ci comma = true; 5051cb0ef41Sopenharmony_ci if (successor->rpo_number() == -1) { 5061cb0ef41Sopenharmony_ci os << "id:" << successor->id(); 5071cb0ef41Sopenharmony_ci } else { 5081cb0ef41Sopenharmony_ci os << "B" << successor->rpo_number(); 5091cb0ef41Sopenharmony_ci } 5101cb0ef41Sopenharmony_ci } 5111cb0ef41Sopenharmony_ci os << "\n"; 5121cb0ef41Sopenharmony_ci } 5131cb0ef41Sopenharmony_ci } 5141cb0ef41Sopenharmony_ci return os; 5151cb0ef41Sopenharmony_ci} 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci} // namespace compiler 5181cb0ef41Sopenharmony_ci} // namespace internal 5191cb0ef41Sopenharmony_ci} // namespace v8 520