Commit 77d9e997 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm-gc] Improve wasm escape analysis/allocation folding

Changes:
- Enable allocation folding for wasm-gc graphs.
- Improve structure of wasm escape analysis code. Kill dead nodes.
- Revisit object node after eliminating a load or a store to that node.
- Add a couple of tests, rename one test file.

Bug: v8:11510
Change-Id: I8b3c5186cd0a8827744a05eba366ff79bc7bc975
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3264215Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77840}
parent bfea0fda
......@@ -348,6 +348,9 @@ Reduction CsaLoadElimination::ReduceLoadFromObject(Node* node,
Node* replacement =
TruncateAndExtend(lookup_result.value, from, access.machine_type);
ReplaceWithValue(node, replacement, effect);
// This might have opened an opportunity for escape analysis to eliminate
// the object altogether.
Revisit(object);
return Replace(replacement);
}
}
......
......@@ -8000,6 +8000,8 @@ wasm::WasmCompilationResult ExecuteTurbofanWasmCompilation(
info.set_wasm_runtime_exception_support();
}
if (FLAG_experimental_wasm_gc) info.set_allocation_folding();
if (info.trace_turbo_json()) {
TurboCfgFile tcf;
tcf << AsC1VCompilation(&info);
......
......@@ -22,35 +22,38 @@ Reduction WasmEscapeAnalysis::Reduce(Node* node) {
Reduction WasmEscapeAnalysis::ReduceAllocateRaw(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kAllocateRaw);
// TODO(manoskouk): Account for phis.
std::vector<Edge> use_edges;
// Collect all value edges of {node} in this vector.
std::vector<Edge> value_edges;
for (Edge edge : node->use_edges()) {
if (NodeProperties::IsValueEdge(edge)) {
if (edge.index() != 0 ||
edge.from()->opcode() != IrOpcode::kStoreToObject) {
// The allocated object is used for something other than storing into.
return NoChange();
}
value_edges.push_back(edge);
}
use_edges.push_back(edge);
}
// Remove all stores from the effect chain.
for (Edge edge : use_edges) {
if (NodeProperties::IsValueEdge(edge)) {
Node* use = edge.from();
DCHECK_EQ(edge.index(), 0);
DCHECK_EQ(use->opcode(), IrOpcode::kStoreToObject);
ReplaceWithValue(use, mcgraph_->Dead(),
NodeProperties::GetEffectInput(use), mcgraph_->Dead());
}
// Remove all discovered stores from the effect chain.
for (Edge edge : value_edges) {
DCHECK(NodeProperties::IsValueEdge(edge));
DCHECK_EQ(edge.index(), 0);
Node* use = edge.from();
DCHECK(!use->IsDead());
DCHECK_EQ(use->opcode(), IrOpcode::kStoreToObject);
ReplaceWithValue(use, mcgraph_->Dead(), NodeProperties::GetEffectInput(use),
mcgraph_->Dead());
use->Kill();
}
// Remove the allocation from the effect and control chains.
ReplaceWithValue(node, mcgraph_->Dead(), NodeProperties::GetEffectInput(node),
NodeProperties::GetControlInput(node));
return NoChange();
return Changed(node);
}
} // namespace compiler
......
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --experimental-wasm-gc
// Flags: --experimental-wasm-gc --no-liftoff
// This tests are meant to examine if Turbofan CsaLoadElimination works
// correctly for wasm. The TurboFan graphs can be examined with --trace-turbo.
......@@ -317,3 +317,58 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
let instance = builder.instantiate({});
assertEquals(value_0 + value_1, instance.exports.main());
})();
(function EscapeAnalysis() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let struct1 = builder.addStruct([makeField(kWasmI32, true)]);
let struct2 = builder.addStruct([makeField(wasmOptRefType(struct1), true)]);
// TF should eliminate both allocations in this function.
builder.addFunction("main", kSig_i_i)
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprRttCanon, struct1,
kGCPrefix, kExprStructNewWithRtt, struct1,
kGCPrefix, kExprRttCanon, struct2,
kGCPrefix, kExprStructNewWithRtt, struct2,
kGCPrefix, kExprStructGet, struct2, 0,
kGCPrefix, kExprStructGet, struct1, 0])
.exportFunc();
let instance = builder.instantiate({});
assertEquals(42, instance.exports.main(42));
})();
(function AllocationFolding() {
print(arguments.callee.name);
var builder = new WasmModuleBuilder();
let struct_index = builder.addStructSubtype([makeField(kWasmI32, true)]);
let struct_2 = builder.addStructSubtype([
makeField(wasmRefType(struct_index), false),
makeField(wasmRefType(struct_index), false)
]);
let global = builder.addGlobal(
wasmOptRefType(struct_2), true, WasmInitExpr.RefNull(struct_2));
// The three alocations should be folded.
builder.addFunction("main", kSig_i_i)
.addBody([
kExprLocalGet, 0,
kGCPrefix, kExprStructNew, struct_index,
kExprI32Const, 43,
kGCPrefix, kExprStructNew, struct_index,
kGCPrefix, kExprStructNew, struct_2,
kExprGlobalSet, global.index,
kExprLocalGet, 0,
])
.exportFunc();
let instance = builder.instantiate();
assertEquals(10, instance.exports.main(10));
})();
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