| Index: src/compiler/simd-lowering.cc
|
| diff --git a/src/compiler/simd-lowering.cc b/src/compiler/simd-lowering.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7eb95928e8f9ab39702f40a9ff1b8de8e86d0e23
|
| --- /dev/null
|
| +++ b/src/compiler/simd-lowering.cc
|
| @@ -0,0 +1,157 @@
|
| +// Copyright 2016 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/simd-lowering.h"
|
| +
|
| +#include "src/assembler.h"
|
| +#include "src/compiler/js-graph.h"
|
| +#include "src/compiler/linkage.h"
|
| +#include "src/compiler/machine-operator.h"
|
| +#include "src/compiler/operator-properties.h"
|
| +#include "src/compiler/simplified-operator.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +namespace compiler {
|
| +
|
| +SimdLowering::~SimdLowering() {}
|
| +
|
| +Reduction SimdLowering::Reduce(Node* node) {
|
| + // For now lower everything to runtime calls.
|
| + switch (node->opcode()) {
|
| + case IrOpcode::kCreateInt32x4: {
|
| + static const Conversion signature[] = {kOpaque, kInt32, kInt32, kInt32,
|
| + kInt32};
|
| + return ChangeToRuntimeCall(node, Runtime::kCreateInt32x4, signature);
|
| + }
|
| + case IrOpcode::kCreateInt16x8: {
|
| + static const Conversion signature[] = {
|
| + kOpaque, kInt32, kInt32, kInt32, kInt32,
|
| + kInt32, kInt32, kInt32, kInt32,
|
| + };
|
| + return ChangeToRuntimeCall(node, Runtime::kCreateInt16x8, signature);
|
| + }
|
| + case IrOpcode::kCreateInt8x16: {
|
| + static const Conversion signature[] = {
|
| + kOpaque, kInt32, kInt32, kInt32, kInt32, kInt32,
|
| + kInt32, kInt32, kInt32, kInt32, kInt32, kInt32,
|
| + kInt32, kInt32, kInt32, kInt32, kInt32,
|
| + };
|
| + return ChangeToRuntimeCall(node, Runtime::kCreateInt8x16, signature);
|
| + }
|
| + case IrOpcode::kCreateFloat32x4: {
|
| + static const Conversion signature[] = {kOpaque, kFloat32, kFloat32,
|
| + kFloat32, kFloat32};
|
| + return ChangeToRuntimeCall(node, Runtime::kCreateFloat32x4, signature);
|
| + }
|
| + case IrOpcode::kInt8x16ExtractLane:
|
| + case IrOpcode::kInt16x8ExtractLane:
|
| + case IrOpcode::kInt32x4ExtractLane: {
|
| + static const Conversion signature[] = {kInt32, kOpaque, kInt32};
|
| + return ChangeToRuntimeCall(node, Runtime::kInt32x4ExtractLane, signature);
|
| + }
|
| + case IrOpcode::kFloat32x4ExtractLane: {
|
| + static const Conversion signature[] = {kFloat32, kOpaque, kInt32};
|
| + return ChangeToRuntimeCall(node, Runtime::kFloat32x4ExtractLane,
|
| + signature);
|
| + }
|
| + default: { break; }
|
| + }
|
| +
|
| + // TODO(gdeepti): Implement and test.
|
| + // Assume the others are all just simd in and out.
|
| + Conversion signature[17] = {
|
| + kNone, kNone, kNone, kNone, kNone, kNone, kNone, kNone, kNone,
|
| + kNone, kNone, kNone, kNone, kNone, kNone, kNone, kNone,
|
| + };
|
| + switch (node->opcode()) {
|
| +#define F(Opcode) \
|
| + case IrOpcode::k##Opcode: { \
|
| + return ChangeToRuntimeCall(node, Runtime::k##Opcode, signature); \
|
| + }
|
| + MACHINE_SIMD_RETURN_SIMD_OP_LIST(F)
|
| + MACHINE_SIMD_RETURN_BOOL_OP_LIST(F)
|
| +#undef F
|
| + default: { return NoChange(); }
|
| + }
|
| + UNREACHABLE();
|
| + return NoChange();
|
| +}
|
| +
|
| +Reduction SimdLowering::ChangeToRuntimeCall(Node* node,
|
| + Runtime::FunctionId function_id,
|
| + const Conversion* signature) {
|
| + SimplifiedOperatorBuilder simplified(jsgraph()->zone());
|
| + const Runtime::Function* function = Runtime::FunctionForId(function_id);
|
| + CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
|
| + jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties,
|
| + CallDescriptor::kNoFlags);
|
| + const int kInputSize = 16;
|
| + const int kDefaultFunctionParams = 6;
|
| + Node* inputs[kInputSize + kDefaultFunctionParams];
|
| + DCHECK_LE(function->nargs + kDefaultFunctionParams,
|
| + static_cast<int>(arraysize(inputs)));
|
| + // Either there are control + effect or not.
|
| + DCHECK(node->InputCount() == function->nargs ||
|
| + node->InputCount() == function->nargs + 2);
|
| + int index = 0;
|
| + inputs[index++] = jsgraph()->CEntryStubConstant(function->result_size);
|
| + for (int i = 0; i < function->nargs; ++i) {
|
| + Node* arg = node->InputAt(i);
|
| + switch (signature[i + 1]) {
|
| + case kInt32:
|
| + arg = builder_->BuildChangeInt32ToTagged(arg);
|
| + break;
|
| + case kFloat32:
|
| + arg = jsgraph()->graph()->NewNode(
|
| + jsgraph()->machine()->ChangeFloat32ToFloat64(), arg);
|
| + arg = builder_->BuildChangeFloat64ToTagged(arg);
|
| + break;
|
| + case kFloat64:
|
| + arg = builder_->BuildChangeFloat64ToTagged(arg);
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + inputs[index++] = arg;
|
| + }
|
| + inputs[index++] = jsgraph()->ExternalConstant(
|
| + ExternalReference(function_id, jsgraph()->isolate()));
|
| + inputs[index++] = jsgraph()->Int32Constant(function->nargs);
|
| + inputs[index++] = jsgraph()->Constant(context_);
|
| + // Loads and stores have control and effect, others do not and use
|
| + // the start node instead.
|
| + if (node->InputCount() == function->nargs + 2) {
|
| + inputs[index++] = node->InputAt(function->nargs + 1); // effect
|
| + inputs[index++] = node->InputAt(function->nargs + 2); // control
|
| + } else {
|
| + inputs[index++] = jsgraph()->graph()->start(); // effect
|
| + inputs[index++] = jsgraph()->graph()->start(); // control
|
| + }
|
| + Node* ret = jsgraph()->graph()->NewNode(jsgraph()->common()->Call(desc),
|
| + index, inputs);
|
| +
|
| + Conversion return_type = signature[0];
|
| + switch (return_type) {
|
| + case kInt32:
|
| + ret = builder_->BuildChangeTaggedToInt32(ret);
|
| + break;
|
| + case kFloat32:
|
| + NodeProperties::SetType(ret, Type::Number());
|
| + ret = builder_->BuildChangeTaggedToFloat64(ret);
|
| + ret = jsgraph()->graph()->NewNode(
|
| + jsgraph()->machine()->TruncateInt64ToInt32(), ret);
|
| + break;
|
| + case kFloat64:
|
| + ret = builder_->BuildChangeTaggedToFloat64(ret);
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + return Replace(ret);
|
| +}
|
| +
|
| +} // namespace compiler
|
| +} // namespace internal
|
| +} // namespace v8
|
|
|