Commit 4319876d authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm][turbofan] Introduce wasm inlining heuristics

We introduce the WasmInliningHeuristics virtual class and implement it
with a trivial heuristics that inlines direct calls based on callee
index only. Other, more meaningful heuristics will be introduced later.

Bug: v8:12166
Change-Id: I74fd8f61e0c97b975827fa062629e9ff7463e058
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3157952
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76816}
parent d90e873e
......@@ -1696,8 +1696,11 @@ struct WasmInliningPhase {
data->jsgraph()->Dead(), data->observe_node_manager());
DeadCodeElimination dead(&graph_reducer, data->graph(),
data->mcgraph()->common(), temp_zone);
// For now, hard-code inlining the function at index 0.
InlineByIndex heuristics({0});
WasmInliner inliner(&graph_reducer, env, data->source_positions(),
data->node_origins(), data->mcgraph(), wire_bytes, 0);
data->node_origins(), data->mcgraph(), wire_bytes,
&heuristics);
AddReducer(data, &graph_reducer, &dead);
AddReducer(data, &graph_reducer, &inliner);
......
......@@ -5,6 +5,7 @@
#include "src/compiler/wasm-inlining.h"
#include "src/compiler/all-nodes.h"
#include "src/compiler/compiler-source-position-table.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/wasm-compiler.h"
#include "src/wasm/function-body-decoder.h"
......@@ -26,7 +27,9 @@ Reduction WasmInliner::Reduce(Node* node) {
}
}
// TODO(12166): Abstract over a heuristics provider.
// TODO(12166): Save inlined frames for trap/--trace-wasm purposes. Consider
// tail calls.
// TODO(12166): Inline indirect calls/call_ref.
Reduction WasmInliner::ReduceCall(Node* call) {
DCHECK(call->opcode() == IrOpcode::kCall ||
call->opcode() == IrOpcode::kTailCall);
......@@ -36,16 +39,23 @@ Reduction WasmInliner::ReduceCall(Node* call) {
: IrOpcode::kRelocatableInt64Constant;
if (callee->opcode() != reloc_opcode) return NoChange();
auto info = OpParameter<RelocatablePtrConstantInfo>(callee->op());
if (static_cast<uint32_t>(info.value()) != inlinee_index_) return NoChange();
uint32_t inlinee_index = static_cast<uint32_t>(info.value());
if (!heuristics_->DoInline(source_positions_->GetSourcePosition(call),
inlinee_index)) {
return NoChange();
}
CHECK_LT(inlinee_index, module()->functions.size());
const wasm::WasmFunction* inlinee = &module()->functions[inlinee_index];
CHECK_LT(inlinee_index_, module()->functions.size());
base::Vector<const byte> function_bytes =
wire_bytes_->GetCode(inlinee()->code);
const wasm::FunctionBody inlinee_body(
inlinee()->sig, inlinee()->code.offset(), function_bytes.begin(),
base::Vector<const byte> function_bytes = wire_bytes_->GetCode(inlinee->code);
const wasm::FunctionBody inlinee_body(inlinee->sig, inlinee->code.offset(),
function_bytes.begin(),
function_bytes.end());
wasm::WasmFeatures detected;
WasmGraphBuilder builder(env_, zone(), mcgraph_, inlinee_body.sig, spt_);
WasmGraphBuilder builder(env_, zone(), mcgraph_, inlinee_body.sig,
source_positions_);
std::vector<WasmLoopInfo> infos;
size_t subgraph_min_node_id = graph()->NodeCount();
......@@ -56,7 +66,7 @@ Reduction WasmInliner::ReduceCall(Node* call) {
Graph::SubgraphScope scope(graph());
result = wasm::BuildTFGraph(zone()->allocator(), env_->enabled_features,
module(), &builder, &detected, inlinee_body,
&infos, node_origins_, inlinee_index_,
&infos, node_origins_, inlinee_index,
wasm::kDoNotInstrumentEndpoints);
inlinee_start = graph()->start();
inlinee_end = graph()->end();
......@@ -64,7 +74,7 @@ Reduction WasmInliner::ReduceCall(Node* call) {
if (result.failed()) return NoChange();
return call->opcode() == IrOpcode::kCall
? InlineCall(call, inlinee_start, inlinee_end,
? InlineCall(call, inlinee_start, inlinee_end, inlinee->sig,
subgraph_min_node_id)
: InlineTailCall(call, inlinee_start, inlinee_end);
}
......@@ -117,6 +127,7 @@ Reduction WasmInliner::InlineTailCall(Node* call, Node* callee_start,
Reduction WasmInliner::InlineCall(Node* call, Node* callee_start,
Node* callee_end,
const wasm::FunctionSig* inlinee_sig,
size_t subgraph_min_node_id) {
DCHECK(call->opcode() == IrOpcode::kCall);
......@@ -159,7 +170,7 @@ Reduction WasmInliner::InlineCall(Node* call, Node* callee_start,
// inlinee. It will then be handled like any other return.
auto descriptor = CallDescriptorOf(input->op());
NodeProperties::ChangeOp(input, common()->Call(descriptor));
int return_arity = static_cast<int>(inlinee()->sig->return_count());
int return_arity = static_cast<int>(inlinee_sig->return_count());
NodeVector return_inputs(zone());
// The first input of a return node is always the 0 constant.
return_inputs.push_back(graph()->NewNode(common()->Int32Constant(0)));
......@@ -256,7 +267,7 @@ Reduction WasmInliner::InlineCall(Node* call, Node* callee_start,
// Find the correct machine representation for the return values from the
// inlinee signature.
MachineRepresentation repr =
inlinee()->sig->GetReturn(i).machine_representation();
inlinee_sig->GetReturn(i).machine_representation();
Node* ith_value_output = graph()->NewNode(
common()->Phi(repr, return_count),
static_cast<int>(ith_values.size()), &ith_values.front());
......@@ -295,10 +306,6 @@ Reduction WasmInliner::InlineCall(Node* call, Node* callee_start,
const wasm::WasmModule* WasmInliner::module() const { return env_->module; }
const wasm::WasmFunction* WasmInliner::inlinee() const {
return &module()->functions[inlinee_index_];
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -30,24 +30,49 @@ namespace compiler {
class NodeOriginTable;
class SourcePositionTable;
// Parent class for classes that provide heuristics on how to inline in wasm.
class WasmInliningHeuristics {
public:
virtual bool DoInline(SourcePosition position,
uint32_t function_index) const = 0;
};
// A simple inlining heuristic that inlines all function calls to a set of given
// function indices.
class InlineByIndex : public WasmInliningHeuristics {
public:
explicit InlineByIndex(uint32_t function_index)
: WasmInliningHeuristics(), function_indices_(function_index) {}
InlineByIndex(std::initializer_list<uint32_t> function_indices)
: WasmInliningHeuristics(), function_indices_(function_indices) {}
bool DoInline(SourcePosition position,
uint32_t function_index) const override {
return function_indices_.count(function_index) > 0;
}
private:
std::unordered_set<uint32_t> function_indices_;
};
// The WasmInliner provides the core graph inlining machinery for Webassembly
// graphs. Note that this class only deals with the mechanics of how to inline
// one graph into another, heuristics that decide what and how much to inline
// are beyond its scope. As a current placeholder, only a function at specific
// given index {inlinee_index} is inlined.
// one graph into another; heuristics that decide what and how much to inline
// are provided by {WasmInliningHeuristics}.
class WasmInliner final : public AdvancedReducer {
public:
WasmInliner(Editor* editor, wasm::CompilationEnv* env,
SourcePositionTable* spt, NodeOriginTable* node_origins,
MachineGraph* mcgraph, const wasm::WireBytesStorage* wire_bytes,
uint32_t inlinee_index)
SourcePositionTable* source_positions,
NodeOriginTable* node_origins, MachineGraph* mcgraph,
const wasm::WireBytesStorage* wire_bytes,
const WasmInliningHeuristics* heuristics)
: AdvancedReducer(editor),
env_(env),
spt_(spt),
source_positions_(source_positions),
node_origins_(node_origins),
mcgraph_(mcgraph),
wire_bytes_(wire_bytes),
inlinee_index_(inlinee_index) {}
heuristics_(heuristics) {}
const char* reducer_name() const override { return "WasmInliner"; }
......@@ -63,16 +88,17 @@ class WasmInliner final : public AdvancedReducer {
Reduction ReduceCall(Node* call);
Reduction InlineCall(Node* call, Node* callee_start, Node* callee_end,
const wasm::FunctionSig* inlinee_sig,
size_t subgraph_min_node_id);
Reduction InlineTailCall(Node* call, Node* callee_start, Node* callee_end);
void RewireFunctionEntry(Node* call, Node* callee_start);
wasm::CompilationEnv* const env_;
SourcePositionTable* const spt_;
SourcePositionTable* const source_positions_;
NodeOriginTable* const node_origins_;
MachineGraph* const mcgraph_;
const wasm::WireBytesStorage* const wire_bytes_;
const uint32_t inlinee_index_;
const WasmInliningHeuristics* const heuristics_;
};
} // namespace compiler
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment