11cb0ef41Sopenharmony_ci// Copyright 2022 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_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_
61cb0ef41Sopenharmony_ci#define V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "src/compiler/bytecode-analysis.h"
91cb0ef41Sopenharmony_ci#include "src/maglev/maglev-basic-block.h"
101cb0ef41Sopenharmony_ci#include "src/maglev/maglev-graph.h"
111cb0ef41Sopenharmony_ci#include "src/maglev/maglev-interpreter-frame-state.h"
121cb0ef41Sopenharmony_ci#include "src/maglev/maglev-ir.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace v8 {
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_cinamespace maglev {
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ci// The GraphProcessor takes a NodeProcessor, and applies it to each Node in the
191cb0ef41Sopenharmony_ci// Graph by calling NodeProcessor::Process on each Node.
201cb0ef41Sopenharmony_ci//
211cb0ef41Sopenharmony_ci// The GraphProcessor also keeps track of the current ProcessingState, including
221cb0ef41Sopenharmony_ci// the inferred corresponding InterpreterFrameState and (optionally) the state
231cb0ef41Sopenharmony_ci// at the most recent Checkpoint, and passes this to the Process method.
241cb0ef41Sopenharmony_ci//
251cb0ef41Sopenharmony_ci// It expects a NodeProcessor class with:
261cb0ef41Sopenharmony_ci//
271cb0ef41Sopenharmony_ci//   // A function that processes the graph before the nodes are walked.
281cb0ef41Sopenharmony_ci//   void PreProcessGraph(MaglevCompilationUnit*, Graph* graph);
291cb0ef41Sopenharmony_ci//
301cb0ef41Sopenharmony_ci//   // A function that processes the graph after the nodes are walked.
311cb0ef41Sopenharmony_ci//   void PostProcessGraph(MaglevCompilationUnit*, Graph* graph);
321cb0ef41Sopenharmony_ci//
331cb0ef41Sopenharmony_ci//   // A function that processes each basic block before its nodes are walked.
341cb0ef41Sopenharmony_ci//   void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block);
351cb0ef41Sopenharmony_ci//
361cb0ef41Sopenharmony_ci//   // Process methods for each Node type. The GraphProcessor switches over
371cb0ef41Sopenharmony_ci//   // the Node's opcode, casts it to the appropriate FooNode, and dispatches
381cb0ef41Sopenharmony_ci//   // to NodeProcessor::Process. It's then up to the NodeProcessor to provide
391cb0ef41Sopenharmony_ci//   // either distinct Process methods per Node type, or using templates or
401cb0ef41Sopenharmony_ci//   // overloading as appropriate to group node processing.
411cb0ef41Sopenharmony_ci//   void Process(FooNode* node, const ProcessingState& state) {}
421cb0ef41Sopenharmony_ci//
431cb0ef41Sopenharmony_citemplate <typename NodeProcessor>
441cb0ef41Sopenharmony_ciclass GraphProcessor;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciclass ProcessingState {
471cb0ef41Sopenharmony_ci public:
481cb0ef41Sopenharmony_ci  explicit ProcessingState(MaglevCompilationUnit* compilation_unit,
491cb0ef41Sopenharmony_ci                           BlockConstIterator block_it)
501cb0ef41Sopenharmony_ci      : compilation_unit_(compilation_unit), block_it_(block_it) {}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  // Disallow copies, since the underlying frame states stay mutable.
531cb0ef41Sopenharmony_ci  ProcessingState(const ProcessingState&) = delete;
541cb0ef41Sopenharmony_ci  ProcessingState& operator=(const ProcessingState&) = delete;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  BasicBlock* block() const { return *block_it_; }
571cb0ef41Sopenharmony_ci  BasicBlock* next_block() const { return *(block_it_ + 1); }
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  MaglevCompilationUnit* compilation_unit() const { return compilation_unit_; }
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci  int register_count() const { return compilation_unit_->register_count(); }
621cb0ef41Sopenharmony_ci  int parameter_count() const { return compilation_unit_->parameter_count(); }
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  MaglevGraphLabeller* graph_labeller() const {
651cb0ef41Sopenharmony_ci    return compilation_unit_->graph_labeller();
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci private:
691cb0ef41Sopenharmony_ci  MaglevCompilationUnit* compilation_unit_;
701cb0ef41Sopenharmony_ci  BlockConstIterator block_it_;
711cb0ef41Sopenharmony_ci};
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_citemplate <typename NodeProcessor>
741cb0ef41Sopenharmony_ciclass GraphProcessor {
751cb0ef41Sopenharmony_ci public:
761cb0ef41Sopenharmony_ci  template <typename... Args>
771cb0ef41Sopenharmony_ci  explicit GraphProcessor(MaglevCompilationUnit* compilation_unit,
781cb0ef41Sopenharmony_ci                          Args&&... args)
791cb0ef41Sopenharmony_ci      : compilation_unit_(compilation_unit),
801cb0ef41Sopenharmony_ci        node_processor_(std::forward<Args>(args)...) {}
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  void ProcessGraph(Graph* graph) {
831cb0ef41Sopenharmony_ci    graph_ = graph;
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci    node_processor_.PreProcessGraph(compilation_unit_, graph);
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci    for (block_it_ = graph->begin(); block_it_ != graph->end(); ++block_it_) {
881cb0ef41Sopenharmony_ci      BasicBlock* block = *block_it_;
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci      node_processor_.PreProcessBasicBlock(compilation_unit_, block);
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci      if (block->has_phi()) {
931cb0ef41Sopenharmony_ci        for (Phi* phi : *block->phis()) {
941cb0ef41Sopenharmony_ci          node_processor_.Process(phi, GetCurrentState());
951cb0ef41Sopenharmony_ci        }
961cb0ef41Sopenharmony_ci      }
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci      for (node_it_ = block->nodes().begin(); node_it_ != block->nodes().end();
991cb0ef41Sopenharmony_ci           ++node_it_) {
1001cb0ef41Sopenharmony_ci        Node* node = *node_it_;
1011cb0ef41Sopenharmony_ci        ProcessNodeBase(node, GetCurrentState());
1021cb0ef41Sopenharmony_ci      }
1031cb0ef41Sopenharmony_ci
1041cb0ef41Sopenharmony_ci      ProcessNodeBase(block->control_node(), GetCurrentState());
1051cb0ef41Sopenharmony_ci    }
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci    node_processor_.PostProcessGraph(compilation_unit_, graph);
1081cb0ef41Sopenharmony_ci  }
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci  NodeProcessor& node_processor() { return node_processor_; }
1111cb0ef41Sopenharmony_ci  const NodeProcessor& node_processor() const { return node_processor_; }
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci private:
1141cb0ef41Sopenharmony_ci  ProcessingState GetCurrentState() {
1151cb0ef41Sopenharmony_ci    return ProcessingState(compilation_unit_, block_it_);
1161cb0ef41Sopenharmony_ci  }
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  void ProcessNodeBase(NodeBase* node, const ProcessingState& state) {
1191cb0ef41Sopenharmony_ci    switch (node->opcode()) {
1201cb0ef41Sopenharmony_ci#define CASE(OPCODE)                                      \
1211cb0ef41Sopenharmony_ci  case Opcode::k##OPCODE:                                 \
1221cb0ef41Sopenharmony_ci    PreProcess(node->Cast<OPCODE>(), state);              \
1231cb0ef41Sopenharmony_ci    node_processor_.Process(node->Cast<OPCODE>(), state); \
1241cb0ef41Sopenharmony_ci    break;
1251cb0ef41Sopenharmony_ci      NODE_BASE_LIST(CASE)
1261cb0ef41Sopenharmony_ci#undef CASE
1271cb0ef41Sopenharmony_ci    }
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci  void PreProcess(NodeBase* node, const ProcessingState& state) {}
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  int register_count() const { return compilation_unit_->register_count(); }
1331cb0ef41Sopenharmony_ci  const compiler::BytecodeAnalysis& bytecode_analysis() const {
1341cb0ef41Sopenharmony_ci    return compilation_unit_->bytecode_analysis();
1351cb0ef41Sopenharmony_ci  }
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci  MaglevCompilationUnit* const compilation_unit_;
1381cb0ef41Sopenharmony_ci  NodeProcessor node_processor_;
1391cb0ef41Sopenharmony_ci  Graph* graph_;
1401cb0ef41Sopenharmony_ci  BlockConstIterator block_it_;
1411cb0ef41Sopenharmony_ci  NodeConstIterator node_it_;
1421cb0ef41Sopenharmony_ci};
1431cb0ef41Sopenharmony_ci
1441cb0ef41Sopenharmony_ci// A NodeProcessor that wraps multiple NodeProcessors, and forwards to each of
1451cb0ef41Sopenharmony_ci// them iteratively.
1461cb0ef41Sopenharmony_citemplate <typename... Processors>
1471cb0ef41Sopenharmony_ciclass NodeMultiProcessor;
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_citemplate <>
1501cb0ef41Sopenharmony_ciclass NodeMultiProcessor<> {
1511cb0ef41Sopenharmony_ci public:
1521cb0ef41Sopenharmony_ci  void PreProcessGraph(MaglevCompilationUnit*, Graph* graph) {}
1531cb0ef41Sopenharmony_ci  void PostProcessGraph(MaglevCompilationUnit*, Graph* graph) {}
1541cb0ef41Sopenharmony_ci  void PreProcessBasicBlock(MaglevCompilationUnit*, BasicBlock* block) {}
1551cb0ef41Sopenharmony_ci  void Process(NodeBase* node, const ProcessingState& state) {}
1561cb0ef41Sopenharmony_ci};
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_citemplate <typename Processor, typename... Processors>
1591cb0ef41Sopenharmony_ciclass NodeMultiProcessor<Processor, Processors...>
1601cb0ef41Sopenharmony_ci    : NodeMultiProcessor<Processors...> {
1611cb0ef41Sopenharmony_ci  using Base = NodeMultiProcessor<Processors...>;
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci public:
1641cb0ef41Sopenharmony_ci  template <typename Node>
1651cb0ef41Sopenharmony_ci  void Process(Node* node, const ProcessingState& state) {
1661cb0ef41Sopenharmony_ci    processor_.Process(node, state);
1671cb0ef41Sopenharmony_ci    Base::Process(node, state);
1681cb0ef41Sopenharmony_ci  }
1691cb0ef41Sopenharmony_ci  void PreProcessGraph(MaglevCompilationUnit* unit, Graph* graph) {
1701cb0ef41Sopenharmony_ci    processor_.PreProcessGraph(unit, graph);
1711cb0ef41Sopenharmony_ci    Base::PreProcessGraph(unit, graph);
1721cb0ef41Sopenharmony_ci  }
1731cb0ef41Sopenharmony_ci  void PostProcessGraph(MaglevCompilationUnit* unit, Graph* graph) {
1741cb0ef41Sopenharmony_ci    // Post process in reverse order because that kind of makes sense.
1751cb0ef41Sopenharmony_ci    Base::PostProcessGraph(unit, graph);
1761cb0ef41Sopenharmony_ci    processor_.PostProcessGraph(unit, graph);
1771cb0ef41Sopenharmony_ci  }
1781cb0ef41Sopenharmony_ci  void PreProcessBasicBlock(MaglevCompilationUnit* unit, BasicBlock* block) {
1791cb0ef41Sopenharmony_ci    processor_.PreProcessBasicBlock(unit, block);
1801cb0ef41Sopenharmony_ci    Base::PreProcessBasicBlock(unit, block);
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci private:
1841cb0ef41Sopenharmony_ci  Processor processor_;
1851cb0ef41Sopenharmony_ci};
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_citemplate <typename... Processors>
1881cb0ef41Sopenharmony_ciusing GraphMultiProcessor = GraphProcessor<NodeMultiProcessor<Processors...>>;
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci}  // namespace maglev
1911cb0ef41Sopenharmony_ci}  // namespace internal
1921cb0ef41Sopenharmony_ci}  // namespace v8
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci#endif  // V8_MAGLEV_MAGLEV_GRAPH_PROCESSOR_H_
195