wasm-inlining.h 5.46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#if !V8_ENABLE_WEBASSEMBLY
#error This header should only be included if WebAssembly is enabled.
#endif  // !V8_ENABLE_WEBASSEMBLY

#ifndef V8_COMPILER_WASM_INLINING_H_
#define V8_COMPILER_WASM_INLINING_H_

#include "src/compiler/graph-reducer.h"
#include "src/compiler/js-graph.h"

namespace v8 {
namespace internal {

namespace wasm {
struct CompilationEnv;
struct WasmModule;
21
struct WasmFunction;
22 23 24 25 26 27 28 29 30 31
class WireBytesStorage;
}  // namespace wasm

class BytecodeOffset;
class OptimizedCompilationInfo;

namespace compiler {

class NodeOriginTable;
class SourcePositionTable;
32
struct WasmLoopInfo;
33 34

// The WasmInliner provides the core graph inlining machinery for Webassembly
35
// graphs.
36 37 38
class WasmInliner final : public AdvancedReducer {
 public:
  WasmInliner(Editor* editor, wasm::CompilationEnv* env,
39
              uint32_t function_index, SourcePositionTable* source_positions,
40
              NodeOriginTable* node_origins, MachineGraph* mcgraph,
41 42
              const wasm::WireBytesStorage* wire_bytes,
              std::vector<WasmLoopInfo>* loop_infos)
43 44
      : AdvancedReducer(editor),
        env_(env),
45
        function_index_(function_index),
46
        source_positions_(source_positions),
47 48 49
        node_origins_(node_origins),
        mcgraph_(mcgraph),
        wire_bytes_(wire_bytes),
50
        loop_infos_(loop_infos),
51 52 53
        initial_graph_size_(mcgraph->graph()->NodeCount()),
        current_graph_size_(initial_graph_size_),
        inlining_candidates_() {}
54 55 56 57

  const char* reducer_name() const override { return "WasmInliner"; }

  Reduction Reduce(Node* node) final;
58 59 60 61 62 63
  void Finalize() final;

  static bool any_inlining_impossible(size_t initial_graph_size) {
    return size_limit(initial_graph_size) - initial_graph_size <
           kMinimumFunctionNodeCount;
  }
64 65

 private:
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
  struct CandidateInfo {
    Node* node;
    uint32_t inlinee_index;
    bool is_speculative_call_ref;
    int call_count;
    int wire_byte_size;
  };

  struct LexicographicOrdering {
    // Returns if c1 should be prioritized less than c2.
    bool operator()(CandidateInfo& c1, CandidateInfo& c2) {
      if (c1.is_speculative_call_ref && !c2.is_speculative_call_ref) {
        return false;
      }
      if (c2.is_speculative_call_ref && !c1.is_speculative_call_ref) {
        return true;
      }
      if (c1.call_count > c2.call_count) return false;
      if (c2.call_count > c1.call_count) return true;
      return c1.wire_byte_size > c2.wire_byte_size;
    }
  };

  // TODO(manoskouk): This has not been found to be useful, but something
  // similar may be tried again in the future.
  // struct AdvancedOrdering {
  //  // Returns if c1 should be prioritized less than c2.
  //  bool operator()(CandidateInfo& c1, CandidateInfo& c2) {
  //    if (c1.is_speculative_call_ref && c2.is_speculative_call_ref) {
  //      if (c1.call_count > c2.call_count) return false;
  //      if (c2.call_count > c1.call_count) return true;
  //      return c1.wire_byte_size > c2.wire_byte_size;
  //    }
  //    if (!c1.is_speculative_call_ref && !c2.is_speculative_call_ref) {
  //      return c1.wire_byte_size > c2.wire_byte_size;
  //    }
  //
  //    constexpr int kAssumedCallCountForDirectCalls = 3;
  //
  //    int c1_call_count = c1.is_speculative_call_ref
  //                            ? c1.call_count
  //                            : kAssumedCallCountForDirectCalls;
  //    int c2_call_count = c2.is_speculative_call_ref
  //                            ? c2.call_count
  //                            : kAssumedCallCountForDirectCalls;
  //
  //    return static_cast<float>(c1_call_count) / c1.wire_byte_size <
  //           static_cast<float>(c2_call_count) / c2.wire_byte_size;
  //  }
  //};

117 118 119 120 121
  Zone* zone() const { return mcgraph_->zone(); }
  CommonOperatorBuilder* common() const { return mcgraph_->common(); }
  Graph* graph() const { return mcgraph_->graph(); }
  MachineGraph* mcgraph() const { return mcgraph_; }
  const wasm::WasmModule* module() const;
122 123 124 125 126 127 128 129 130

  // A limit to the size of the inlined graph as a function of its initial size.
  static size_t size_limit(size_t initial_graph_size) {
    return initial_graph_size +
           std::min(FLAG_wasm_inlining_max_size,
                    FLAG_wasm_inlining_budget_factor / initial_graph_size);
  }

  // The smallest size in TF nodes any meaningful wasm function can have
131 132
  // (start, return, IntConstant(0), end).
  static constexpr size_t kMinimumFunctionNodeCount = 4;
133 134

  Reduction ReduceCall(Node* call);
135 136 137 138
  void InlineCall(Node* call, Node* callee_start, Node* callee_end,
                  const wasm::FunctionSig* inlinee_sig,
                  size_t subgraph_min_node_id);
  void InlineTailCall(Node* call, Node* callee_start, Node* callee_end);
139
  void RewireFunctionEntry(Node* call, Node* callee_start);
140 141

  wasm::CompilationEnv* const env_;
142
  uint32_t function_index_;
143
  SourcePositionTable* const source_positions_;
144 145 146
  NodeOriginTable* const node_origins_;
  MachineGraph* const mcgraph_;
  const wasm::WireBytesStorage* const wire_bytes_;
147
  std::vector<WasmLoopInfo>* const loop_infos_;
148 149 150 151 152 153
  const size_t initial_graph_size_;
  size_t current_graph_size_;
  std::priority_queue<CandidateInfo, std::vector<CandidateInfo>,
                      LexicographicOrdering>
      inlining_candidates_;
  std::unordered_set<Node*> seen_;
154 155 156 157 158 159 160
};

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_WASM_INLINING_H_