Commit 6122465c authored by gdeepti's avatar gdeepti Committed by Commit bot

[wasm] Add native x64 implementations for I32x4Splat, I32x4ExtractLane

 - Instruction selection, code generation, test for Splat/Extract
 - Fixes for AstS128 Locals in wasm

R=bbudge@chromium.org, titzer@chromium.org

Review-Url: https://codereview.chromium.org/2264533002
Cr-Commit-Position: refs/heads/master@{#38843}
parent 55a6588d
......@@ -1307,6 +1307,10 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kUnsafePointerAdd:
MarkAsRepresentation(MachineType::PointerRepresentation(), node);
return VisitUnsafePointerAdd(node);
case IrOpcode::kCreateInt32x4:
return MarkAsSimd128(node), VisitCreateInt32x4(node);
case IrOpcode::kInt32x4ExtractLane:
return MarkAsWord32(node), VisitInt32x4ExtractLane(node);
default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id());
......@@ -1647,7 +1651,6 @@ void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
UNIMPLEMENTED();
}
#endif // V8_TARGET_ARCH_32_BIT
// 64 bit targets do not implement the following instructions.
......@@ -1665,6 +1668,14 @@ void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); }
#endif // V8_TARGET_ARCH_64_BIT
#if !V8_TARGET_ARCH_X64
void InstructionSelector::VisitCreateInt32x4(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32x4ExtractLane(Node* node) {
UNIMPLEMENTED();
}
#endif // !V8_TARGET_ARCH_X64
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
void InstructionSelector::VisitParameter(Node* node) {
......
......@@ -228,6 +228,9 @@ class InstructionSelector final {
void MarkAsFloat64(Node* node) {
MarkAsRepresentation(MachineRepresentation::kFloat64, node);
}
void MarkAsSimd128(Node* node) {
MarkAsRepresentation(MachineRepresentation::kSimd128, node);
}
void MarkAsReference(Node* node) {
MarkAsRepresentation(MachineRepresentation::kTagged, node);
}
......@@ -276,6 +279,8 @@ class InstructionSelector final {
#define DECLARE_GENERATOR(x) void Visit##x(Node* node);
MACHINE_OP_LIST(DECLARE_GENERATOR)
MACHINE_SIMD_RETURN_NUM_OP_LIST(DECLARE_GENERATOR)
MACHINE_SIMD_RETURN_SIMD_OP_LIST(DECLARE_GENERATOR)
#undef DECLARE_GENERATOR
void VisitFinishRegion(Node* node);
......
......@@ -2866,6 +2866,14 @@ void WasmGraphBuilder::SetSourcePosition(Node* node,
source_position_table_->SetSourcePosition(node, pos);
}
Node* WasmGraphBuilder::DefaultS128Value() {
// TODO(gdeepti): Introduce Simd128Constant to common-operator.h and use
// instead of creating a SIMD Value.
return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(),
Int32Constant(0), Int32Constant(0), Int32Constant(0),
Int32Constant(0));
}
Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode,
const NodeVector& inputs) {
switch (opcode) {
......@@ -2873,8 +2881,8 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode,
return graph()->NewNode(jsgraph()->machine()->Int32x4ExtractLane(),
inputs[0], inputs[1]);
case wasm::kExprI32x4Splat:
return graph()->NewNode(jsgraph()->machine()->Int32x4ExtractLane(),
inputs[0], inputs[0], inputs[0], inputs[0]);
return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), inputs[0],
inputs[0], inputs[0], inputs[0]);
default:
return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
}
......
......@@ -194,6 +194,8 @@ class WasmGraphBuilder {
void SetSourcePosition(Node* node, wasm::WasmCodePosition position);
Node* DefaultS128Value();
Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs);
private:
......
......@@ -2032,6 +2032,18 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ xchgl(i.InputRegister(index), operand);
break;
}
case kX64Int32x4Create: {
CpuFeatureScope sse_scope(masm(), SSE4_1);
XMMRegister dst = i.OutputSimd128Register();
__ Movd(dst, i.InputRegister(0));
__ shufps(dst, dst, 0x0);
break;
}
case kX64Int32x4ExtractLane: {
CpuFeatureScope sse_scope(masm(), SSE4_1);
__ Pextrd(i.OutputRegister(), i.InputSimd128Register(0), i.InputInt8(1));
break;
}
case kCheckedLoadInt8:
ASSEMBLE_CHECKED_LOAD_INTEGER(movsxbl);
break;
......
......@@ -145,7 +145,9 @@ namespace compiler {
V(X64StackCheck) \
V(X64Xchgb) \
V(X64Xchgw) \
V(X64Xchgl)
V(X64Xchgl) \
V(X64Int32x4Create) \
V(X64Int32x4ExtractLane)
// Addressing modes represent the "shape" of inputs to an instruction.
// Many instructions support multiple addressing modes. Addressing modes
......
......@@ -127,6 +127,8 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Lea:
case kX64Dec32:
case kX64Inc32:
case kX64Int32x4Create:
case kX64Int32x4ExtractLane:
return (instr->addressing_mode() == kMode_None)
? kNoOpcodeFlags
: kIsLoadOperation | kHasSideEffect;
......
......@@ -2213,6 +2213,17 @@ void InstructionSelector::VisitAtomicStore(Node* node) {
Emit(code, 0, static_cast<InstructionOperand*>(nullptr), input_count, inputs);
}
void InstructionSelector::VisitCreateInt32x4(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Int32x4Create, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
}
void InstructionSelector::VisitInt32x4ExtractLane(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Int32x4ExtractLane, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)), g.UseImmediate(node->InputAt(1)));
}
// static
MachineOperatorBuilder::Flags
InstructionSelector::SupportedMachineOperatorFlags() {
......
......@@ -574,6 +574,8 @@ class WasmFullDecoder : public WasmDecoder {
return builder_->Float32Constant(0);
case kAstF64:
return builder_->Float64Constant(0);
case kAstS128:
return builder_->DefaultS128Value();
default:
UNREACHABLE();
return nullptr;
......@@ -620,6 +622,9 @@ class WasmFullDecoder : public WasmDecoder {
case kLocalF64:
type = kAstF64;
break;
case kLocalS128:
type = kAstS128;
break;
default:
error(pc_ - 1, "invalid local type");
return;
......
......@@ -634,6 +634,8 @@ class ModuleDecoder : public Decoder {
return kAstF32;
case kLocalF64:
return kAstF64;
case kLocalS128:
return kAstS128;
default:
error(pc_ - 1, "invalid local type");
return kAstStmt;
......
......@@ -507,10 +507,10 @@ class WasmOpcodes {
return kLocalF32;
case kAstF64:
return kLocalF64;
case kAstStmt:
return kLocalVoid;
case kAstS128:
return kLocalS128;
case kAstStmt:
return kLocalVoid;
default:
UNREACHABLE();
return kLocalVoid;
......
......@@ -3325,12 +3325,12 @@ void MacroAssembler::Pextrd(Register dst, XMMRegister src, int8_t imm8) {
Movd(dst, src);
return;
}
DCHECK_EQ(1, imm8);
if (CpuFeatures::IsSupported(SSE4_1)) {
CpuFeatureScope sse_scope(this, SSE4_1);
pextrd(dst, src, imm8);
return;
}
DCHECK_EQ(1, imm8);
movq(dst, src);
shrq(dst, Immediate(32));
}
......
......@@ -214,7 +214,8 @@
'test-disasm-x64.cc',
'test-macro-assembler-x64.cc',
'test-log-stack-tracer.cc',
'test-run-wasm-relocation-x64.cc'
'test-run-wasm-relocation-x64.cc',
'wasm/test-run-wasm-simd.cc'
],
'cctest_sources_arm': [ ### gcmole(arch:arm) ###
'test-assembler-arm.cc',
......
// 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/wasm/wasm-macro-gen.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/value-helper.h"
#include "test/cctest/wasm/wasm-run-utils.h"
using namespace v8::base;
using namespace v8::internal;
using namespace v8::internal::compiler;
using namespace v8::internal::wasm;
WASM_EXEC_TEST(Splat) {
FLAG_wasm_simd_prototype = true;
// Store SIMD value in a local variable, use extract lane to check lane values
// This test is not a test for ExtractLane as Splat does not create
// interesting SIMD values.
//
// SetLocal(1, I32x4Splat(Local(0)));
// For each lane index
// if(Local(0) != I32x4ExtractLane(Local(1), index)
// return 0
//
// return 1
WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
r.AllocateLocal(kAstS128);
BUILD(r,
WASM_BLOCK(WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0),
WASM_SIMD_I32x4_EXTRACT_LANE(
WASM_GET_LOCAL(1), WASM_I8(0))),
WASM_RETURN1(WASM_ZERO)),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0),
WASM_SIMD_I32x4_EXTRACT_LANE(
WASM_GET_LOCAL(1), WASM_I8(1))),
WASM_RETURN1(WASM_ZERO)),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0),
WASM_SIMD_I32x4_EXTRACT_LANE(
WASM_GET_LOCAL(1), WASM_I8(2))),
WASM_RETURN1(WASM_ZERO)),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0),
WASM_SIMD_I32x4_EXTRACT_LANE(
WASM_GET_LOCAL(1), WASM_I8(3))),
WASM_RETURN1(WASM_ZERO)),
WASM_RETURN1(WASM_ONE)));
FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); }
}
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