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#ifndef V8_COMPILER_SCHEDULER_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_SCHEDULER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/flags.h" 91cb0ef41Sopenharmony_ci#include "src/common/globals.h" 101cb0ef41Sopenharmony_ci#include "src/compiler/node.h" 111cb0ef41Sopenharmony_ci#include "src/compiler/opcodes.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/schedule.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/zone-stats.h" 141cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_cinamespace internal { 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ciclass ProfileDataFromFile; 201cb0ef41Sopenharmony_ciclass TickCounter; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cinamespace compiler { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// Forward declarations. 251cb0ef41Sopenharmony_ciclass CFGBuilder; 261cb0ef41Sopenharmony_ciclass ControlEquivalence; 271cb0ef41Sopenharmony_ciclass Graph; 281cb0ef41Sopenharmony_ciclass SpecialRPONumberer; 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci// Computes a schedule from a graph, placing nodes into basic blocks and 311cb0ef41Sopenharmony_ci// ordering the basic blocks in the special RPO order. 321cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE Scheduler { 331cb0ef41Sopenharmony_ci public: 341cb0ef41Sopenharmony_ci // Flags that control the mode of operation. 351cb0ef41Sopenharmony_ci enum Flag { kNoFlags = 0u, kSplitNodes = 1u << 1, kTempSchedule = 1u << 2 }; 361cb0ef41Sopenharmony_ci using Flags = base::Flags<Flag>; 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci // The complete scheduling algorithm. Creates a new schedule and places all 391cb0ef41Sopenharmony_ci // nodes from the graph into it. 401cb0ef41Sopenharmony_ci static Schedule* ComputeSchedule(Zone* temp_zone, Graph* graph, Flags flags, 411cb0ef41Sopenharmony_ci TickCounter* tick_counter, 421cb0ef41Sopenharmony_ci const ProfileDataFromFile* profile_data); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci // Compute the RPO of blocks in an existing schedule. 451cb0ef41Sopenharmony_ci static BasicBlockVector* ComputeSpecialRPO(Zone* zone, Schedule* schedule); 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci // Computes the dominator tree on an existing schedule that has RPO computed. 481cb0ef41Sopenharmony_ci static void GenerateDominatorTree(Schedule* schedule); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci const ProfileDataFromFile* profile_data() const { return profile_data_; } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci private: 531cb0ef41Sopenharmony_ci // Placement of a node changes during scheduling. The placement state 541cb0ef41Sopenharmony_ci // transitions over time while the scheduler is choosing a position: 551cb0ef41Sopenharmony_ci // 561cb0ef41Sopenharmony_ci // +---------------------+-----+----> kFixed 571cb0ef41Sopenharmony_ci // / / / 581cb0ef41Sopenharmony_ci // kUnknown ----+------> kCoupled ----+ / 591cb0ef41Sopenharmony_ci // \ / 601cb0ef41Sopenharmony_ci // +----> kSchedulable ----+--------> kScheduled 611cb0ef41Sopenharmony_ci // 621cb0ef41Sopenharmony_ci // 1) InitializePlacement(): kUnknown -> kCoupled|kSchedulable|kFixed 631cb0ef41Sopenharmony_ci // 2) UpdatePlacement(): kCoupled|kSchedulable -> kFixed|kScheduled 641cb0ef41Sopenharmony_ci // 651cb0ef41Sopenharmony_ci // We maintain the invariant that all nodes that are not reachable 661cb0ef41Sopenharmony_ci // from the end have kUnknown placement. After the PrepareUses phase runs, 671cb0ef41Sopenharmony_ci // also the opposite is true - all nodes with kUnknown placement are not 681cb0ef41Sopenharmony_ci // reachable from the end. 691cb0ef41Sopenharmony_ci enum Placement { kUnknown, kSchedulable, kFixed, kCoupled, kScheduled }; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci // Implements a two-dimensional map: (int, int) -> BasicBlock*. 721cb0ef41Sopenharmony_ci using CommonDominatorCache = ZoneMap<int, ZoneMap<int, BasicBlock*>*>; 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci // Per-node data tracked during scheduling. 751cb0ef41Sopenharmony_ci struct SchedulerData { 761cb0ef41Sopenharmony_ci BasicBlock* minimum_block_; // Minimum legal RPO placement. 771cb0ef41Sopenharmony_ci int unscheduled_count_; // Number of unscheduled uses of this node. 781cb0ef41Sopenharmony_ci Placement placement_; // Whether the node is fixed, schedulable, 791cb0ef41Sopenharmony_ci // coupled to another node, or not yet known. 801cb0ef41Sopenharmony_ci }; 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci Zone* zone_; 831cb0ef41Sopenharmony_ci Graph* graph_; 841cb0ef41Sopenharmony_ci Schedule* schedule_; 851cb0ef41Sopenharmony_ci Flags flags_; 861cb0ef41Sopenharmony_ci ZoneVector<NodeVector*> 871cb0ef41Sopenharmony_ci scheduled_nodes_; // Per-block list of nodes in reverse. 881cb0ef41Sopenharmony_ci NodeVector schedule_root_nodes_; // Fixed root nodes seed the worklist. 891cb0ef41Sopenharmony_ci ZoneQueue<Node*> schedule_queue_; // Worklist of schedulable nodes. 901cb0ef41Sopenharmony_ci ZoneVector<SchedulerData> node_data_; // Per-node data for all nodes. 911cb0ef41Sopenharmony_ci CFGBuilder* control_flow_builder_; // Builds basic blocks for controls. 921cb0ef41Sopenharmony_ci SpecialRPONumberer* special_rpo_; // Special RPO numbering of blocks. 931cb0ef41Sopenharmony_ci ControlEquivalence* equivalence_; // Control dependence equivalence. 941cb0ef41Sopenharmony_ci TickCounter* const tick_counter_; 951cb0ef41Sopenharmony_ci const ProfileDataFromFile* profile_data_; 961cb0ef41Sopenharmony_ci CommonDominatorCache common_dominator_cache_; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci Scheduler(Zone* zone, Graph* graph, Schedule* schedule, Flags flags, 991cb0ef41Sopenharmony_ci size_t node_count_hint_, TickCounter* tick_counter, 1001cb0ef41Sopenharmony_ci const ProfileDataFromFile* profile_data); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci inline SchedulerData DefaultSchedulerData(); 1031cb0ef41Sopenharmony_ci inline SchedulerData* GetData(Node* node); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci Placement GetPlacement(Node* node); 1061cb0ef41Sopenharmony_ci Placement InitializePlacement(Node* node); 1071cb0ef41Sopenharmony_ci void UpdatePlacement(Node* node, Placement placement); 1081cb0ef41Sopenharmony_ci bool IsLive(Node* node); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci // If the node is coupled, returns the coupled control edge index. 1111cb0ef41Sopenharmony_ci inline base::Optional<int> GetCoupledControlEdge(Node* node); 1121cb0ef41Sopenharmony_ci void IncrementUnscheduledUseCount(Node* node, Node* from); 1131cb0ef41Sopenharmony_ci void DecrementUnscheduledUseCount(Node* node, Node* from); 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci static void PropagateImmediateDominators(BasicBlock* block); 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci // Uses {common_dominator_cache_} to speed up repeated calls. 1181cb0ef41Sopenharmony_ci BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2); 1191cb0ef41Sopenharmony_ci // Returns the common dominator of {b1} and {b2} if it can be found in 1201cb0ef41Sopenharmony_ci // {common_dominator_cache_}, or nullptr otherwise. 1211cb0ef41Sopenharmony_ci // Not meant to be called directly, only from {GetCommonDominator}. 1221cb0ef41Sopenharmony_ci BasicBlock* GetCommonDominatorIfCached(BasicBlock* b1, BasicBlock* b2); 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci // Phase 1: Build control-flow graph. 1251cb0ef41Sopenharmony_ci friend class CFGBuilder; 1261cb0ef41Sopenharmony_ci void BuildCFG(); 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci // Phase 2: Compute special RPO and dominator tree. 1291cb0ef41Sopenharmony_ci friend class SpecialRPONumberer; 1301cb0ef41Sopenharmony_ci void ComputeSpecialRPONumbering(); 1311cb0ef41Sopenharmony_ci void GenerateDominatorTree(); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci // Phase 3: Prepare use counts for nodes. 1341cb0ef41Sopenharmony_ci friend class PrepareUsesVisitor; 1351cb0ef41Sopenharmony_ci void PrepareUses(); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci // Phase 4: Schedule nodes early. 1381cb0ef41Sopenharmony_ci friend class ScheduleEarlyNodeVisitor; 1391cb0ef41Sopenharmony_ci void ScheduleEarly(); 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci // Phase 5: Schedule nodes late. 1421cb0ef41Sopenharmony_ci friend class ScheduleLateNodeVisitor; 1431cb0ef41Sopenharmony_ci void ScheduleLate(); 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci // Phase 6: Seal the final schedule. 1461cb0ef41Sopenharmony_ci void SealFinalSchedule(); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci void FuseFloatingControl(BasicBlock* block, Node* node); 1491cb0ef41Sopenharmony_ci void MovePlannedNodes(BasicBlock* from, BasicBlock* to); 1501cb0ef41Sopenharmony_ci}; 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ciDEFINE_OPERATORS_FOR_FLAGS(Scheduler::Flags) 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci} // namespace compiler 1561cb0ef41Sopenharmony_ci} // namespace internal 1571cb0ef41Sopenharmony_ci} // namespace v8 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci#endif // V8_COMPILER_SCHEDULER_H_ 160