Commit 11017398 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Initial commit for the Int64Reducer.

The goal of the Int64Reducer is to replace all int64 nodes in a tf graph
with a set of int32 nodes such that 64 bit tf functions can be executed
on 32 bit platforms. At the moment the Int64Reducer only replaces
Int64Constants, TruncateInt64ToInt32, and Word64And.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1655883002

Cr-Commit-Position: refs/heads/master@{#33721}
parent 85306a0a
......@@ -783,6 +783,8 @@ source_set("v8_base") {
"src/compiler/instruction-selector.h",
"src/compiler/instruction.cc",
"src/compiler/instruction.h",
"src/compiler/int64-lowering.cc",
"src/compiler/int64-lowering.h",
"src/compiler/interpreter-assembler.cc",
"src/compiler/interpreter-assembler.h",
"src/compiler/js-builtin-reducer.cc",
......
// Copyright 2014 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.
#include "src/compiler/int64-lowering.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
namespace compiler {
Int64Lowering::Int64Lowering(Graph* graph, MachineOperatorBuilder* machine,
CommonOperatorBuilder* common, Zone* zone)
: graph_(graph),
machine_(machine),
common_(common),
state_(graph, 4),
stack_(zone),
replacements_(zone->NewArray<Replacement>(graph->NodeCount())) {
memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount());
}
void Int64Lowering::ReduceGraph() {
stack_.push(graph()->end());
state_.Set(graph()->end(), State::kOnStack);
while (!stack_.empty()) {
Node* top = stack_.top();
if (state_.Get(top) == State::kInputsPushed) {
stack_.pop();
state_.Set(top, State::kVisited);
// All inputs of top have already been reduced, now reduce top.
ReduceNode(top);
} else {
// Push all children onto the stack.
for (Node* input : top->inputs()) {
if (state_.Get(input) == State::kUnvisited) {
stack_.push(input);
state_.Set(input, State::kOnStack);
}
}
state_.Set(top, State::kInputsPushed);
}
}
}
void Int64Lowering::ReduceNode(Node* node) {
switch (node->opcode()) {
case IrOpcode::kInt64Constant: {
int64_t value = OpParameter<int64_t>(node);
Node* low_node = graph()->NewNode(
common()->Int32Constant(static_cast<int32_t>(value & 0xFFFFFFFF)));
Node* high_node = graph()->NewNode(
common()->Int32Constant(static_cast<int32_t>(value >> 32)));
replacements_[node->id()].low = low_node;
replacements_[node->id()].high = high_node;
break;
}
case IrOpcode::kWord64And: {
Node* left = node->InputAt(0);
DCHECK(replacements_[left->id()].low);
Node* left_low = replacements_[left->id()].low;
Node* left_high = replacements_[left->id()].high;
Node* right = node->InputAt(1);
DCHECK(replacements_[right->id()].low);
Node* right_low = replacements_[right->id()].low;
Node* right_high = replacements_[right->id()].high;
replacements_[node->id()].low =
graph()->NewNode(machine()->Word32And(), left_low, right_low);
replacements_[node->id()].high =
graph()->NewNode(machine()->Word32And(), left_high, right_high);
break;
}
case IrOpcode::kTruncateInt64ToInt32: {
Node* input = node->InputAt(0);
DCHECK(replacements_[input->id()].low);
replacements_[node->id()].low = replacements_[input->id()].low;
break;
}
default: {
// Also the inputs of nodes can change which do not expect int64 inputs.
for (int i = 0; i < node->InputCount(); i++) {
Node* input = node->InputAt(i);
// The input has changed altough it was not an int64 input. This can
// happen e.g. if the input node is IrOpcode::kTruncateInt64ToInt32. We
// use the low word replacement as the new input.
if (replacements_[input->id()].low) {
node->ReplaceInput(i, replacements_[input->id()].low);
}
}
}
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
// Copyright 2014 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.
#ifndef V8_COMPILER_INT64_REDUCER_H_
#define V8_COMPILER_INT64_REDUCER_H_
#include "src/compiler/common-operator.h"
#include "src/compiler/graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-marker.h"
#include "src/zone-containers.h"
namespace v8 {
namespace internal {
namespace compiler {
class Int64Lowering {
public:
Int64Lowering(Graph* graph, MachineOperatorBuilder* machine,
CommonOperatorBuilder* common, Zone* zone);
void ReduceGraph();
Graph* graph() const { return graph_; }
MachineOperatorBuilder* machine() const { return machine_; }
CommonOperatorBuilder* common() const { return common_; }
private:
enum class State : uint8_t { kUnvisited, kOnStack, kInputsPushed, kVisited };
struct Replacement {
Node* low;
Node* high;
};
void ReduceTop();
void ReduceNode(Node* node);
Graph* const graph_;
MachineOperatorBuilder* machine_;
CommonOperatorBuilder* common_;
NodeMarker<State> state_;
ZoneStack<Node*> stack_;
Replacement* replacements_;
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_INT64_REDUCER_H_
......@@ -15,6 +15,7 @@
#include "src/compiler/graph.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/int64-lowering.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/js-operator.h"
......@@ -481,6 +482,9 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
op = m->Uint32LessThanOrEqual();
std::swap(left, right);
break;
case wasm::kExprI64And:
op = m->Word64And();
break;
#if WASM_64
// Opcodes only supported on 64-bit platforms.
// TODO(titzer): query the machine operator builder here instead of #ifdef.
......@@ -531,9 +535,6 @@ Node* WasmGraphBuilder::Binop(wasm::WasmOpcode opcode, Node* left,
op = m->Uint64Mod();
return graph()->NewNode(op, left, right,
trap_->ZeroCheck64(kTrapRemByZero, right));
case wasm::kExprI64And:
op = m->Word64And();
break;
case wasm::kExprI64Ior:
op = m->Word64Or();
break;
......@@ -783,13 +784,12 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
op = m->Float64RoundTiesEven().op();
break;
}
#if WASM_64
// Opcodes only supported on 64-bit platforms.
// TODO(titzer): query the machine operator builder here instead of #ifdef.
case wasm::kExprI32ConvertI64:
op = m->TruncateInt64ToInt32();
break;
#if WASM_64
// Opcodes only supported on 64-bit platforms.
// TODO(titzer): query the machine operator builder here instead of #ifdef.
case wasm::kExprI64SConvertI32:
op = m->ChangeInt32ToInt64();
break;
......@@ -1888,6 +1888,13 @@ Node* WasmGraphBuilder::String(const char* string) {
Graph* WasmGraphBuilder::graph() { return jsgraph()->graph(); }
void WasmGraphBuilder::Int64LoweringForTesting() {
#if !WASM_64
Int64Lowering r(jsgraph()->graph(), jsgraph()->machine(), jsgraph()->common(),
jsgraph()->zone());
r.ReduceGraph();
#endif
}
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
CompilationInfo* info,
......@@ -1910,7 +1917,6 @@ static void RecordFunctionCompilation(Logger::LogEventsAndTags tag,
}
}
Handle<JSFunction> CompileJSToWasmWrapper(
Isolate* isolate, wasm::ModuleEnv* module, Handle<String> name,
Handle<Code> wasm_code, Handle<JSObject> module_object, uint32_t index) {
......@@ -2119,6 +2125,7 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
func_name = buffer.start();
}
CompilationInfo info(func_name, isolate, &zone, flags);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, descriptor, &graph);
if (debugging) {
......
......@@ -132,6 +132,8 @@ class WasmGraphBuilder {
wasm::FunctionSig* GetFunctionSignature() { return function_signature_; }
void Int64LoweringForTesting();
private:
static const int kDefaultBufferSize = 16;
friend class WasmTrapHelper;
......
......@@ -116,6 +116,23 @@ TEST(Run_WasmInt64Const_many) {
}
#endif
TEST(Run_WasmI32ConvertI64) {
FOR_INT64_INPUTS(i) {
WasmRunner<int32_t> r;
BUILD(r, WASM_I32_CONVERT_I64(WASM_I64(*i)));
CHECK_EQ(static_cast<int32_t>(*i), r.Call());
}
}
TEST(Run_WasmI64AndConstants) {
FOR_INT64_INPUTS(i) {
FOR_INT64_INPUTS(j) {
WasmRunner<int32_t> r;
BUILD(r, WASM_I32_CONVERT_I64(WASM_I64_AND(WASM_I64(*i), WASM_I64(*j))));
CHECK_EQ(static_cast<int32_t>(*i & *j), r.Call());
}
}
}
TEST(Run_WasmInt32Param0) {
WasmRunner<int32_t> r(MachineType::Int32());
......@@ -216,7 +233,6 @@ void TestInt32Binop(WasmOpcode opcode, int32_t expected, int32_t a, int32_t b) {
}
}
TEST(Run_WasmInt32Binops) {
TestInt32Binop(kExprI32Add, 88888888, 33333333, 55555555);
TestInt32Binop(kExprI32Sub, -1111111, 7777777, 8888888);
......
......@@ -12,6 +12,7 @@
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/int64-lowering.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/wasm-compiler.h"
......@@ -236,6 +237,7 @@ inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, FunctionEnv* env,
str << ", msg = " << result.error_msg.get();
FATAL(str.str().c_str());
}
builder.Int64LoweringForTesting();
if (FLAG_trace_turbo_graph) {
OFStream os(stdout);
os << AsRPO(*jsgraph->graph());
......
......@@ -541,6 +541,8 @@
'../../src/compiler/instruction-scheduler.h',
'../../src/compiler/instruction.cc',
'../../src/compiler/instruction.h',
'../../src/compiler/int64-lowering.cc',
'../../src/compiler/int64-lowering.h',
'../../src/compiler/interpreter-assembler.cc',
'../../src/compiler/interpreter-assembler.h',
'../../src/compiler/js-builtin-reducer.cc',
......
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