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