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

[wasm] Run Int64Lowering on inlined code

On 32-bit architectures, we need to run Int64Lowering on the inlinee
code to make it compatible with the caller code.
Since Int64Lowering now runs while a GraphReducer is active, only one of
them can use node marks to store node states. Therefore, we move the
Int64Lowering node states to an internal map.

Bug: v8:12166
Change-Id: I53b85442d503e71fa533e06568f4b9db572a4401
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3283072Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77941}
parent f74ea020
...@@ -31,7 +31,7 @@ Int64Lowering::Int64Lowering( ...@@ -31,7 +31,7 @@ Int64Lowering::Int64Lowering(
machine_(machine), machine_(machine),
common_(common), common_(common),
simplified_(simplified), simplified_(simplified),
state_(graph, 3), state_(),
stack_(zone), stack_(zone),
replacements_(nullptr), replacements_(nullptr),
signature_(signature), signature_(signature),
...@@ -48,19 +48,21 @@ void Int64Lowering::LowerGraph() { ...@@ -48,19 +48,21 @@ void Int64Lowering::LowerGraph() {
return; return;
} }
stack_.push_back({graph()->end(), 0}); stack_.push_back({graph()->end(), 0});
state_.Set(graph()->end(), State::kOnStack); state_[graph()->end()] = State::kOnStack;
while (!stack_.empty()) { while (!stack_.empty()) {
NodeState& top = stack_.back(); NodeState& top = stack_.back();
if (top.input_index == top.node->InputCount()) { if (top.input_index == top.node->InputCount()) {
// All inputs of top have already been lowered, now lower top. // All inputs of top have already been lowered, now lower top.
stack_.pop_back(); stack_.pop_back();
state_.Set(top.node, State::kVisited); state_[top.node] = State::kVisited;
LowerNode(top.node); LowerNode(top.node);
} else { } else {
// Push the next input onto the stack. // Push the next input onto the stack.
Node* input = top.node->InputAt(top.input_index++); Node* input = top.node->InputAt(top.input_index++);
if (state_.Get(input) == State::kUnvisited) { static_assert(State() == State::kUnvisited,
"Default value for State has to be kUnvisited");
if (state_[input] == State::kUnvisited) {
if (input->opcode() == IrOpcode::kPhi) { if (input->opcode() == IrOpcode::kPhi) {
// To break cycles with phi nodes we push phis on a separate stack so // To break cycles with phi nodes we push phis on a separate stack so
// that they are processed after all other nodes. // that they are processed after all other nodes.
...@@ -72,7 +74,7 @@ void Int64Lowering::LowerGraph() { ...@@ -72,7 +74,7 @@ void Int64Lowering::LowerGraph() {
} else { } else {
stack_.push_back({input, 0}); stack_.push_back({input, 0});
} }
state_.Set(input, State::kOnStack); state_[input] = State::kOnStack;
} }
} }
} }
......
...@@ -93,7 +93,7 @@ class V8_EXPORT_PRIVATE Int64Lowering { ...@@ -93,7 +93,7 @@ class V8_EXPORT_PRIVATE Int64Lowering {
MachineOperatorBuilder* machine_; MachineOperatorBuilder* machine_;
CommonOperatorBuilder* common_; CommonOperatorBuilder* common_;
SimplifiedOperatorBuilder* simplified_; SimplifiedOperatorBuilder* simplified_;
NodeMarker<State> state_; std::unordered_map<Node*, State> state_;
ZoneDeque<NodeState> stack_; ZoneDeque<NodeState> stack_;
Replacement* replacements_; Replacement* replacements_;
Signature<MachineRepresentation>* signature_; Signature<MachineRepresentation>* signature_;
......
...@@ -8205,6 +8205,40 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig, ...@@ -8205,6 +8205,40 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
} }
namespace { namespace {
const wasm::FunctionSig* ReplaceTypeInSig(Zone* zone,
const wasm::FunctionSig* sig,
wasm::ValueType from,
wasm::ValueType to,
size_t num_replacements) {
size_t param_occurences =
std::count(sig->parameters().begin(), sig->parameters().end(), from);
size_t return_occurences =
std::count(sig->returns().begin(), sig->returns().end(), from);
if (param_occurences == 0 && return_occurences == 0) return sig;
wasm::FunctionSig::Builder builder(
zone, sig->return_count() + return_occurences * (num_replacements - 1),
sig->parameter_count() + param_occurences * (num_replacements - 1));
for (wasm::ValueType ret : sig->returns()) {
if (ret == from) {
for (size_t i = 0; i < num_replacements; i++) builder.AddReturn(to);
} else {
builder.AddReturn(ret);
}
}
for (wasm::ValueType param : sig->parameters()) {
if (param == from) {
for (size_t i = 0; i < num_replacements; i++) builder.AddParam(to);
} else {
builder.AddParam(param);
}
}
return builder.Build();
}
CallDescriptor* ReplaceTypeInCallDescriptorWith( CallDescriptor* ReplaceTypeInCallDescriptorWith(
Zone* zone, const CallDescriptor* call_descriptor, size_t num_replacements, Zone* zone, const CallDescriptor* call_descriptor, size_t num_replacements,
wasm::ValueType input_type, wasm::ValueType output_type) { wasm::ValueType input_type, wasm::ValueType output_type) {
...@@ -8272,28 +8306,8 @@ CallDescriptor* ReplaceTypeInCallDescriptorWith( ...@@ -8272,28 +8306,8 @@ CallDescriptor* ReplaceTypeInCallDescriptorWith(
int return_slots = rets.NumStackSlots(); int return_slots = rets.NumStackSlots();
wasm::FunctionSig::Builder sig( auto sig = ReplaceTypeInSig(zone, call_descriptor->wasm_sig(), input_type,
zone, output_type, num_replacements);
call_descriptor->wasm_sig()->return_count() + return_count -
call_descriptor->ReturnCount(),
call_descriptor->wasm_sig()->parameter_count() + parameter_count -
call_descriptor->ParameterCount());
for (wasm::ValueType ret : call_descriptor->wasm_sig()->returns()) {
if (ret == input_type) {
for (size_t i = 0; i < num_replacements; i++) sig.AddReturn(output_type);
} else {
sig.AddReturn(ret);
}
}
for (wasm::ValueType param : call_descriptor->wasm_sig()->parameters()) {
if (param == input_type) {
for (size_t i = 0; i < num_replacements; i++) sig.AddParam(output_type);
} else {
sig.AddParam(param);
}
}
return zone->New<CallDescriptor>( // -- return zone->New<CallDescriptor>( // --
call_descriptor->kind(), // kind call_descriptor->kind(), // kind
...@@ -8307,12 +8321,20 @@ CallDescriptor* ReplaceTypeInCallDescriptorWith( ...@@ -8307,12 +8321,20 @@ CallDescriptor* ReplaceTypeInCallDescriptorWith(
call_descriptor->flags(), // flags call_descriptor->flags(), // flags
call_descriptor->debug_name(), // debug name call_descriptor->debug_name(), // debug name
call_descriptor->GetStackArgumentOrder(), // stack order call_descriptor->GetStackArgumentOrder(), // stack order
sig.Build(), // signature sig, // signature
call_descriptor->AllocatableRegisters(), // allocatable registers call_descriptor->AllocatableRegisters(), // allocatable registers
return_slots); // return slot count return_slots); // return slot count
} }
} // namespace } // namespace
// static
const wasm::FunctionSig* WasmGraphBuilder::Int64LoweredSig(
Zone* zone, const wasm::FunctionSig* sig) {
return (kSystemPointerSize == 4)
? ReplaceTypeInSig(zone, sig, wasm::kWasmI64, wasm::kWasmI32, 2)
: sig;
}
CallDescriptor* GetI32WasmCallDescriptor( CallDescriptor* GetI32WasmCallDescriptor(
Zone* zone, const CallDescriptor* call_descriptor) { Zone* zone, const CallDescriptor* call_descriptor) {
return ReplaceTypeInCallDescriptorWith(zone, call_descriptor, 2, return ReplaceTypeInCallDescriptorWith(zone, call_descriptor, 2,
......
...@@ -544,6 +544,9 @@ class WasmGraphBuilder { ...@@ -544,6 +544,9 @@ class WasmGraphBuilder {
void RemoveBytecodePositionDecorator(); void RemoveBytecodePositionDecorator();
static const wasm::FunctionSig* Int64LoweredSig(Zone* zone,
const wasm::FunctionSig* sig);
protected: protected:
V8_EXPORT_PRIVATE WasmGraphBuilder(wasm::CompilationEnv* env, Zone* zone, V8_EXPORT_PRIVATE WasmGraphBuilder(wasm::CompilationEnv* env, Zone* zone,
MachineGraph* mcgraph, MachineGraph* mcgraph,
......
...@@ -129,18 +129,21 @@ void WasmInliner::Finalize() { ...@@ -129,18 +129,21 @@ void WasmInliner::Finalize() {
const wasm::FunctionSig* real_sig = const wasm::FunctionSig* real_sig =
CallDescriptorOf(call->op())->wasm_sig(); CallDescriptorOf(call->op())->wasm_sig();
// DCHECK that the real signature is a subtype of the formal one. #if DEBUG
DCHECK_EQ(real_sig->parameter_count(), inlinee->sig->parameter_count()); // Check that the real signature is a subtype of the formal one.
DCHECK_EQ(real_sig->return_count(), inlinee->sig->return_count()); const wasm::FunctionSig* formal_sig =
WasmGraphBuilder::Int64LoweredSig(zone(), inlinee->sig);
CHECK_EQ(real_sig->parameter_count(), formal_sig->parameter_count());
CHECK_EQ(real_sig->return_count(), formal_sig->return_count());
for (size_t i = 0; i < real_sig->parameter_count(); i++) { for (size_t i = 0; i < real_sig->parameter_count(); i++) {
DCHECK(wasm::IsSubtypeOf(real_sig->GetParam(i), inlinee->sig->GetParam(i), CHECK(wasm::IsSubtypeOf(real_sig->GetParam(i), formal_sig->GetParam(i),
module())); module()));
} }
for (size_t i = 0; i < real_sig->return_count(); i++) { for (size_t i = 0; i < real_sig->return_count(); i++) {
DCHECK(wasm::IsSubtypeOf(inlinee->sig->GetReturn(i), CHECK(wasm::IsSubtypeOf(formal_sig->GetReturn(i), real_sig->GetReturn(i),
real_sig->GetReturn(i), module())); module()));
} }
// End DCHECK. #endif
const wasm::FunctionBody inlinee_body(real_sig, inlinee->code.offset(), const wasm::FunctionBody inlinee_body(real_sig, inlinee->code.offset(),
function_bytes.begin(), function_bytes.begin(),
...@@ -151,24 +154,25 @@ void WasmInliner::Finalize() { ...@@ -151,24 +154,25 @@ void WasmInliner::Finalize() {
std::vector<WasmLoopInfo> infos; std::vector<WasmLoopInfo> infos;
size_t subgraph_min_node_id = graph()->NodeCount(); size_t subgraph_min_node_id = graph()->NodeCount();
wasm::DecodeResult result;
Node* inlinee_start; Node* inlinee_start;
Node* inlinee_end; Node* inlinee_end;
{ {
Graph::SubgraphScope scope(graph()); Graph::SubgraphScope scope(graph());
result = wasm::BuildTFGraph( wasm::DecodeResult result = wasm::BuildTFGraph(
zone()->allocator(), env_->enabled_features, module(), &builder, zone()->allocator(), env_->enabled_features, module(), &builder,
&detected, inlinee_body, &infos, node_origins_, &detected, inlinee_body, &infos, node_origins_,
candidate.inlinee_index, wasm::kInlinedFunction); candidate.inlinee_index, wasm::kInlinedFunction);
if (result.failed()) {
// This can happen if the inlinee has never been compiled before and is
// invalid. Return, as there is no point to keep optimizing.
TRACE("failed to compile]\n")
return;
}
builder.LowerInt64(WasmGraphBuilder::kCalledFromWasm);
inlinee_start = graph()->start(); inlinee_start = graph()->start();
inlinee_end = graph()->end(); inlinee_end = graph()->end();
} }
if (result.failed()) {
// This can happen if the inlinee has never been compiled before and is
// invalid. Return, as there is no point to keep optimizing.
TRACE("failed to compile]\n")
return;
}
size_t additional_nodes = graph()->NodeCount() - subgraph_min_node_id; size_t additional_nodes = graph()->NodeCount() - subgraph_min_node_id;
if (current_graph_size_ + additional_nodes > if (current_graph_size_ + additional_nodes >
......
...@@ -319,3 +319,23 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js"); ...@@ -319,3 +319,23 @@ d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
let instance = builder.instantiate({}); let instance = builder.instantiate({});
assertEquals(11, instance.exports.main(10)); assertEquals(11, instance.exports.main(10));
})(); })();
(function Int64Lowering() {
print(arguments.callee.name);
let kSig_l_li = makeSig([kWasmI64, kWasmI32], [kWasmI64]);
let builder = new WasmModuleBuilder();
let callee = builder.addFunction("callee", kSig_l_li)
.addBody([
kExprLocalGet, 0, kExprLocalGet, 1, kExprI64SConvertI32, kExprI64Add]);
builder.addFunction("main", kSig_l_li)
.addBody([
kExprLocalGet, 0, kExprLocalGet, 1, kExprCallFunction, callee.index])
.exportFunc();
let instance = builder.instantiate({});
assertEquals(BigInt(21), instance.exports.main(BigInt(10), 11));
})();
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