Commit 02c6b041 authored by gdeepti's avatar gdeepti Committed by Commit bot

[wasm] Implement I32x4ReplaceLane, I32x4Add, I32x4Sub.

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

Review-Url: https://codereview.chromium.org/2385393002
Cr-Commit-Position: refs/heads/master@{#41505}
parent f5cb17a8
...@@ -1131,6 +1131,43 @@ const Operator* CommonOperatorBuilder::ResizeMergeOrPhi(const Operator* op, ...@@ -1131,6 +1131,43 @@ const Operator* CommonOperatorBuilder::ResizeMergeOrPhi(const Operator* op,
} }
} }
const Operator* CommonOperatorBuilder::Int32x4ExtractLane(int32_t lane_number) {
DCHECK(0 <= lane_number && lane_number < 4);
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kInt32x4ExtractLane, Operator::kPure, // opcode
"Int32x4ExtractLane", // name
1, 0, 0, 1, 0, 0, // counts
lane_number); // parameter
}
const Operator* CommonOperatorBuilder::Int32x4ReplaceLane(int32_t lane_number) {
DCHECK(0 <= lane_number && lane_number < 4);
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kInt32x4ReplaceLane, Operator::kPure, // opcode
"Int32x4ReplaceLane", // name
2, 0, 0, 1, 0, 0, // counts
lane_number); // parameter
}
const Operator* CommonOperatorBuilder::Float32x4ExtractLane(
int32_t lane_number) {
DCHECK(0 <= lane_number && lane_number < 4);
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kFloat32x4ExtractLane, Operator::kPure, // opcode
"Float32x4ExtractLane", // name
1, 0, 0, 1, 0, 0, // counts
lane_number); // parameter
}
const Operator* CommonOperatorBuilder::Float32x4ReplaceLane(
int32_t lane_number) {
DCHECK(0 <= lane_number && lane_number < 4);
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kFloat32x4ReplaceLane, Operator::kPure, // opcode
"Float32x4ReplaceLane", // name
2, 0, 0, 1, 0, 0, // counts
lane_number); // parameter
}
const FrameStateFunctionInfo* const FrameStateFunctionInfo*
CommonOperatorBuilder::CreateFrameStateFunctionInfo( CommonOperatorBuilder::CreateFrameStateFunctionInfo(
......
...@@ -260,6 +260,12 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final ...@@ -260,6 +260,12 @@ class V8_EXPORT_PRIVATE CommonOperatorBuilder final
// with {size} inputs. // with {size} inputs.
const Operator* ResizeMergeOrPhi(const Operator* op, int size); const Operator* ResizeMergeOrPhi(const Operator* op, int size);
// Simd Operators
const Operator* Int32x4ExtractLane(int32_t);
const Operator* Int32x4ReplaceLane(int32_t);
const Operator* Float32x4ExtractLane(int32_t);
const Operator* Float32x4ReplaceLane(int32_t);
// Constructs function info for frame state construction. // Constructs function info for frame state construction.
const FrameStateFunctionInfo* CreateFrameStateFunctionInfo( const FrameStateFunctionInfo* CreateFrameStateFunctionInfo(
FrameStateType type, int parameter_count, int local_count, FrameStateType type, int parameter_count, int local_count,
......
...@@ -1396,6 +1396,12 @@ void InstructionSelector::VisitNode(Node* node) { ...@@ -1396,6 +1396,12 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsSimd128(node), VisitCreateInt32x4(node); return MarkAsSimd128(node), VisitCreateInt32x4(node);
case IrOpcode::kInt32x4ExtractLane: case IrOpcode::kInt32x4ExtractLane:
return MarkAsWord32(node), VisitInt32x4ExtractLane(node); return MarkAsWord32(node), VisitInt32x4ExtractLane(node);
case IrOpcode::kInt32x4ReplaceLane:
return MarkAsSimd128(node), VisitInt32x4ReplaceLane(node);
case IrOpcode::kInt32x4Add:
return MarkAsSimd128(node), VisitInt32x4Add(node);
case IrOpcode::kInt32x4Sub:
return MarkAsSimd128(node), VisitInt32x4Sub(node);
default: default:
V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d", V8_Fatal(__FILE__, __LINE__, "Unexpected operator #%d:%s @ node #%d",
node->opcode(), node->op()->mnemonic(), node->id()); node->opcode(), node->op()->mnemonic(), node->id());
...@@ -1729,6 +1735,14 @@ void InstructionSelector::VisitCreateInt32x4(Node* node) { UNIMPLEMENTED(); } ...@@ -1729,6 +1735,14 @@ void InstructionSelector::VisitCreateInt32x4(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32x4ExtractLane(Node* node) { void InstructionSelector::VisitInt32x4ExtractLane(Node* node) {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void InstructionSelector::VisitInt32x4ReplaceLane(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitInt32x4Add(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitInt32x4Sub(Node* node) { UNIMPLEMENTED(); }
#endif // !V8_TARGET_ARCH_X64 #endif // !V8_TARGET_ARCH_X64
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); } void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
......
...@@ -399,9 +399,7 @@ void SimdScalarLowering::LowerNode(Node* node) { ...@@ -399,9 +399,7 @@ void SimdScalarLowering::LowerNode(Node* node) {
} }
case IrOpcode::kInt32x4ExtractLane: case IrOpcode::kInt32x4ExtractLane:
case IrOpcode::kFloat32x4ExtractLane: { case IrOpcode::kFloat32x4ExtractLane: {
Node* laneNode = node->InputAt(1); int32_t lane = OpParameter<int32_t>(node);
DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant);
int32_t lane = OpParameter<int32_t>(laneNode);
Node* rep_node[kMaxLanes] = { Node* rep_node[kMaxLanes] = {
GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr, GetReplacementsWithType(node->InputAt(0), rep_type)[lane], nullptr,
nullptr, nullptr}; nullptr, nullptr};
...@@ -410,11 +408,9 @@ void SimdScalarLowering::LowerNode(Node* node) { ...@@ -410,11 +408,9 @@ void SimdScalarLowering::LowerNode(Node* node) {
} }
case IrOpcode::kInt32x4ReplaceLane: case IrOpcode::kInt32x4ReplaceLane:
case IrOpcode::kFloat32x4ReplaceLane: { case IrOpcode::kFloat32x4ReplaceLane: {
DCHECK_EQ(3, node->InputCount()); DCHECK_EQ(2, node->InputCount());
Node* laneNode = node->InputAt(1); Node* repNode = node->InputAt(1);
Node* repNode = node->InputAt(2); int32_t lane = OpParameter<int32_t>(node);
DCHECK_EQ(laneNode->opcode(), IrOpcode::kInt32Constant);
int32_t lane = OpParameter<int32_t>(laneNode);
DCHECK(lane >= 0 && lane <= 3); DCHECK(lane >= 0 && lane <= 3);
Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type); Node** rep_node = GetReplacementsWithType(node->InputAt(0), rep_type);
if (HasReplacement(0, repNode)) { if (HasReplacement(0, repNode)) {
......
...@@ -3124,6 +3124,9 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, ...@@ -3124,6 +3124,9 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode,
case wasm::kExprI32x4Add: case wasm::kExprI32x4Add:
return graph()->NewNode(jsgraph()->machine()->Int32x4Add(), inputs[0], return graph()->NewNode(jsgraph()->machine()->Int32x4Add(), inputs[0],
inputs[1]); inputs[1]);
case wasm::kExprI32x4Sub:
return graph()->NewNode(jsgraph()->machine()->Int32x4Sub(), inputs[0],
inputs[1]);
case wasm::kExprF32x4Splat: case wasm::kExprF32x4Splat:
return graph()->NewNode(jsgraph()->machine()->CreateFloat32x4(), return graph()->NewNode(jsgraph()->machine()->CreateFloat32x4(),
inputs[0], inputs[0], inputs[0], inputs[0]); inputs[0], inputs[0], inputs[0], inputs[0]);
...@@ -3135,29 +3138,21 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, ...@@ -3135,29 +3138,21 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode,
} }
} }
Node* WasmGraphBuilder::SimdExtractLane(wasm::WasmOpcode opcode, uint8_t lane, Node* WasmGraphBuilder::SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
Node* input) { const NodeVector& inputs) {
switch (opcode) { switch (opcode) {
case wasm::kExprI32x4ExtractLane: case wasm::kExprI32x4ExtractLane:
return graph()->NewNode(jsgraph()->machine()->Int32x4ExtractLane(), input, return graph()->NewNode(jsgraph()->common()->Int32x4ExtractLane(lane),
Int32Constant(lane)); inputs[0]);
case wasm::kExprF32x4ExtractLane:
return graph()->NewNode(jsgraph()->machine()->Float32x4ExtractLane(),
input, Int32Constant(lane));
default:
return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
}
}
Node* WasmGraphBuilder::SimdReplaceLane(wasm::WasmOpcode opcode, uint8_t lane,
Node* input, Node* replacement) {
switch (opcode) {
case wasm::kExprI32x4ReplaceLane: case wasm::kExprI32x4ReplaceLane:
return graph()->NewNode(jsgraph()->machine()->Int32x4ReplaceLane(), input, return graph()->NewNode(jsgraph()->common()->Int32x4ReplaceLane(lane),
Int32Constant(lane), replacement); inputs[0], inputs[1]);
case wasm::kExprF32x4ExtractLane:
return graph()->NewNode(jsgraph()->common()->Float32x4ExtractLane(lane),
inputs[0]);
case wasm::kExprF32x4ReplaceLane: case wasm::kExprF32x4ReplaceLane:
return graph()->NewNode(jsgraph()->machine()->Float32x4ReplaceLane(), return graph()->NewNode(jsgraph()->common()->Float32x4ReplaceLane(lane),
input, Int32Constant(lane), replacement); inputs[0], inputs[1]);
default: default:
return graph()->NewNode(UnsupportedOpcode(opcode), nullptr); return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
} }
......
...@@ -217,9 +217,9 @@ class WasmGraphBuilder { ...@@ -217,9 +217,9 @@ class WasmGraphBuilder {
Node* CreateS128Value(int32_t value); Node* CreateS128Value(int32_t value);
Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs); Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs);
Node* SimdExtractLane(wasm::WasmOpcode opcode, uint8_t lane, Node* input);
Node* SimdReplaceLane(wasm::WasmOpcode opcode, uint8_t lane, Node* input, Node* SimdLaneOp(wasm::WasmOpcode opcode, uint8_t lane,
Node* replacement); const NodeVector& inputs);
private: private:
static const int kDefaultBufferSize = 16; static const int kDefaultBufferSize = 16;
......
...@@ -2147,6 +2147,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2147,6 +2147,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Pextrd(i.OutputRegister(), i.InputSimd128Register(0), i.InputInt8(1)); __ Pextrd(i.OutputRegister(), i.InputSimd128Register(0), i.InputInt8(1));
break; break;
} }
case kX64Int32x4ReplaceLane: {
CpuFeatureScope sse_scope(masm(), SSE4_1);
if (instr->InputAt(2)->IsRegister()) {
__ Pinsrd(i.OutputSimd128Register(), i.InputRegister(2),
i.InputInt8(1));
} else {
__ Pinsrd(i.OutputSimd128Register(), i.InputOperand(2), i.InputInt8(1));
}
break;
}
case kX64Int32x4Add: {
CpuFeatureScope sse_scope(masm(), SSE4_1);
__ paddd(i.OutputSimd128Register(), i.InputSimd128Register(1));
break;
}
case kX64Int32x4Sub: {
CpuFeatureScope sse_scope(masm(), SSE4_1);
__ psubd(i.OutputSimd128Register(), i.InputSimd128Register(1));
break;
}
case kCheckedLoadInt8: case kCheckedLoadInt8:
ASSEMBLE_CHECKED_LOAD_INTEGER(movsxbl); ASSEMBLE_CHECKED_LOAD_INTEGER(movsxbl);
break; break;
......
...@@ -147,7 +147,10 @@ namespace compiler { ...@@ -147,7 +147,10 @@ namespace compiler {
V(X64Xchgw) \ V(X64Xchgw) \
V(X64Xchgl) \ V(X64Xchgl) \
V(X64Int32x4Create) \ V(X64Int32x4Create) \
V(X64Int32x4ExtractLane) V(X64Int32x4ExtractLane) \
V(X64Int32x4ReplaceLane) \
V(X64Int32x4Add) \
V(X64Int32x4Sub)
// Addressing modes represent the "shape" of inputs to an instruction. // Addressing modes represent the "shape" of inputs to an instruction.
// Many instructions support multiple addressing modes. Addressing modes // Many instructions support multiple addressing modes. Addressing modes
......
...@@ -125,6 +125,9 @@ int InstructionScheduler::GetTargetInstructionFlags( ...@@ -125,6 +125,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Inc32: case kX64Inc32:
case kX64Int32x4Create: case kX64Int32x4Create:
case kX64Int32x4ExtractLane: case kX64Int32x4ExtractLane:
case kX64Int32x4ReplaceLane:
case kX64Int32x4Add:
case kX64Int32x4Sub:
return (instr->addressing_mode() == kMode_None) return (instr->addressing_mode() == kMode_None)
? kNoOpcodeFlags ? kNoOpcodeFlags
: kIsLoadOperation | kHasSideEffect; : kIsLoadOperation | kHasSideEffect;
......
...@@ -2379,8 +2379,29 @@ void InstructionSelector::VisitCreateInt32x4(Node* node) { ...@@ -2379,8 +2379,29 @@ void InstructionSelector::VisitCreateInt32x4(Node* node) {
void InstructionSelector::VisitInt32x4ExtractLane(Node* node) { void InstructionSelector::VisitInt32x4ExtractLane(Node* node) {
X64OperandGenerator g(this); X64OperandGenerator g(this);
int32_t lane = OpParameter<int32_t>(node);
Emit(kX64Int32x4ExtractLane, g.DefineAsRegister(node), Emit(kX64Int32x4ExtractLane, g.DefineAsRegister(node),
g.UseRegister(node->InputAt(0)), g.UseImmediate(node->InputAt(1))); g.UseRegister(node->InputAt(0)), g.UseImmediate(lane));
}
void InstructionSelector::VisitInt32x4ReplaceLane(Node* node) {
X64OperandGenerator g(this);
int32_t lane = OpParameter<int32_t>(node);
Emit(kX64Int32x4ReplaceLane, g.DefineSameAsFirst(node),
g.UseRegister(node->InputAt(0)), g.UseImmediate(lane),
g.Use(node->InputAt(1)));
}
void InstructionSelector::VisitInt32x4Add(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Int32x4Add, g.DefineSameAsFirst(node),
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
}
void InstructionSelector::VisitInt32x4Sub(Node* node) {
X64OperandGenerator g(this);
Emit(kX64Int32x4Sub, g.DefineSameAsFirst(node),
g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
} }
// static // static
......
...@@ -1331,8 +1331,9 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1331,8 +1331,9 @@ class WasmFullDecoder : public WasmDecoder {
unsigned ExtractLane(WasmOpcode opcode, LocalType type) { unsigned ExtractLane(WasmOpcode opcode, LocalType type) {
LaneOperand operand(this, pc_); LaneOperand operand(this, pc_);
if (Validate(pc_, operand)) { if (Validate(pc_, operand)) {
TFNode* input = Pop(0, LocalType::kSimd128).node; compiler::NodeVector inputs(1, zone_);
TFNode* node = BUILD(SimdExtractLane, opcode, operand.lane, input); inputs[0] = Pop(0, LocalType::kSimd128).node;
TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
Push(type, node); Push(type, node);
} }
return operand.length; return operand.length;
...@@ -1341,10 +1342,10 @@ class WasmFullDecoder : public WasmDecoder { ...@@ -1341,10 +1342,10 @@ class WasmFullDecoder : public WasmDecoder {
unsigned ReplaceLane(WasmOpcode opcode, LocalType type) { unsigned ReplaceLane(WasmOpcode opcode, LocalType type) {
LaneOperand operand(this, pc_); LaneOperand operand(this, pc_);
if (Validate(pc_, operand)) { if (Validate(pc_, operand)) {
TFNode* input = Pop(0, LocalType::kSimd128).node; compiler::NodeVector inputs(2, zone_);
TFNode* replacement = Pop(1, type).node; inputs[1] = Pop(1, type).node;
TFNode* node = inputs[0] = Pop(0, LocalType::kSimd128).node;
BUILD(SimdReplaceLane, opcode, operand.lane, input, replacement); TFNode* node = BUILD(SimdLaneOp, opcode, operand.lane, inputs);
Push(LocalType::kSimd128, node); Push(LocalType::kSimd128, node);
} }
return operand.length; return operand.length;
......
...@@ -624,15 +624,16 @@ class LocalDeclEncoder { ...@@ -624,15 +624,16 @@ class LocalDeclEncoder {
#define WASM_SIMD_I32x4_SPLAT(x) x, kSimdPrefix, kExprI32x4Splat & 0xff #define WASM_SIMD_I32x4_SPLAT(x) x, kSimdPrefix, kExprI32x4Splat & 0xff
#define WASM_SIMD_I32x4_EXTRACT_LANE(lane, x) \ #define WASM_SIMD_I32x4_EXTRACT_LANE(lane, x) \
x, kSimdPrefix, kExprI32x4ExtractLane & 0xff, static_cast<byte>(lane) x, kSimdPrefix, kExprI32x4ExtractLane & 0xff, static_cast<byte>(lane)
#define WASM_SIMD_I32x4_REPLACE_LANE(lane, x, y) \
x, y, kSimdPrefix, kExprI32x4ReplaceLane & 0xff, static_cast<byte>(lane)
#define WASM_SIMD_I32x4_ADD(x, y) x, y, kSimdPrefix, kExprI32x4Add & 0xff #define WASM_SIMD_I32x4_ADD(x, y) x, y, kSimdPrefix, kExprI32x4Add & 0xff
#define WASM_SIMD_I32x4_SUB(x, y) x, y, kSimdPrefix, kExprI32x4Sub & 0xff
#define WASM_SIMD_F32x4_SPLAT(x) x, kSimdPrefix, kExprF32x4Splat & 0xff #define WASM_SIMD_F32x4_SPLAT(x) x, kSimdPrefix, kExprF32x4Splat & 0xff
#define WASM_SIMD_F32x4_EXTRACT_LANE(lane, x) \ #define WASM_SIMD_F32x4_EXTRACT_LANE(lane, x) \
x, kSimdPrefix, kExprF32x4ExtractLane & 0xff, static_cast<byte>(lane) x, kSimdPrefix, kExprF32x4ExtractLane & 0xff, static_cast<byte>(lane)
#define WASM_SIMD_F32x4_ADD(x, y) x, y, kSimdPrefix, kExprF32x4Add & 0xff #define WASM_SIMD_F32x4_ADD(x, y) x, y, kSimdPrefix, kExprF32x4Add & 0xff
#define WASM_SIMD_I32x4_REPLACE_LANE(lane, x, y) \
y, x, kSimdPrefix, kExprI32x4ReplaceLane & 0xff, static_cast<byte>(lane)
#define WASM_SIMD_F32x4_REPLACE_LANE(lane, x, y) \ #define WASM_SIMD_F32x4_REPLACE_LANE(lane, x, y) \
y, x, kSimdPrefix, kExprF32x4ReplaceLane & 0xff, static_cast<byte>(lane) x, y, kSimdPrefix, kExprF32x4ReplaceLane & 0xff, static_cast<byte>(lane)
#define SIG_ENTRY_v_v kWasmFunctionTypeForm, 0, 0 #define SIG_ENTRY_v_v kWasmFunctionTypeForm, 0, 0
#define SIZEOF_SIG_ENTRY_v_v 3 #define SIZEOF_SIG_ENTRY_v_v 3
......
...@@ -392,11 +392,11 @@ const WasmCodePosition kNoCodePosition = -1; ...@@ -392,11 +392,11 @@ const WasmCodePosition kNoCodePosition = -1;
#define FOREACH_SIMD_1_OPERAND_OPCODE(V) \ #define FOREACH_SIMD_1_OPERAND_OPCODE(V) \
V(F32x4ExtractLane, 0xe501, _) \ V(F32x4ExtractLane, 0xe501, _) \
V(F32x4ReplaceLane, 0xe502, _) \
V(I32x4ExtractLane, 0xe51c, _) \ V(I32x4ExtractLane, 0xe51c, _) \
V(I32x4ReplaceLane, 0xe51d, _) \
V(I16x8ExtractLane, 0xe539, _) \ V(I16x8ExtractLane, 0xe539, _) \
V(I8x16ExtractLane, 0xe558, _) \ V(I8x16ExtractLane, 0xe558, _) \
V(F32x4ReplaceLane, 0xe502, _) \
V(I32x4ReplaceLane, 0xe51d, _) \
V(I16x8ReplaceLane, 0xe53a, _) \ V(I16x8ReplaceLane, 0xe53a, _) \
V(I8x16ReplaceLane, 0xe559, _) V(I8x16ReplaceLane, 0xe559, _)
...@@ -484,11 +484,9 @@ const WasmCodePosition kNoCodePosition = -1; ...@@ -484,11 +484,9 @@ const WasmCodePosition kNoCodePosition = -1;
#define FOREACH_SIMD_SIGNATURE(V) \ #define FOREACH_SIMD_SIGNATURE(V) \
V(s_s, kAstS128, kAstS128) \ V(s_s, kAstS128, kAstS128) \
V(s_f, kAstS128, kAstF32) \ V(s_f, kAstS128, kAstF32) \
V(s_sif, kAstS128, kAstS128, kAstI32, kAstF32) \
V(s_ss, kAstS128, kAstS128, kAstS128) \ V(s_ss, kAstS128, kAstS128, kAstS128) \
V(s_sss, kAstS128, kAstS128, kAstS128, kAstS128) \ V(s_sss, kAstS128, kAstS128, kAstS128, kAstS128) \
V(s_i, kAstS128, kAstI32) \ V(s_i, kAstS128, kAstI32) \
V(s_sii, kAstS128, kAstS128, kAstI32, kAstI32) \
V(s_si, kAstS128, kAstS128, kAstI32) V(s_si, kAstS128, kAstS128, kAstI32)
#define FOREACH_PREFIX(V) \ #define FOREACH_PREFIX(V) \
......
...@@ -13,7 +13,26 @@ using namespace v8::internal; ...@@ -13,7 +13,26 @@ using namespace v8::internal;
using namespace v8::internal::compiler; using namespace v8::internal::compiler;
using namespace v8::internal::wasm; using namespace v8::internal::wasm;
WASM_EXEC_TEST(Splat) { // TODO(gdeepti): These are tests using sample values to verify functional
// correctness of opcodes, add more tests for a range of values and macroize
// tests.
#define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \
WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \
WASM_SIMD_##TYPE##_EXTRACT_LANE( \
lane_index, WASM_GET_LOCAL(value))), \
WASM_RETURN1(WASM_ZERO))
#define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \
WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \
, WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \
WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \
WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3)
#define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \
WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv)
WASM_EXEC_TEST(I32x4Splat) {
FLAG_wasm_simd_prototype = true; FLAG_wasm_simd_prototype = true;
// Store SIMD value in a local variable, use extract lane to check lane values // Store SIMD value in a local variable, use extract lane to check lane values
...@@ -27,23 +46,92 @@ WASM_EXEC_TEST(Splat) { ...@@ -27,23 +46,92 @@ WASM_EXEC_TEST(Splat) {
// //
// return 1 // return 1
WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32());
r.AllocateLocal(kAstS128); byte lane_val = 0;
byte simd = r.AllocateLocal(kAstS128);
BUILD(r, WASM_BLOCK(WASM_SET_LOCAL(simd, WASM_SIMD_I32x4_SPLAT(
WASM_GET_LOCAL(lane_val))),
WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, lane_val),
WASM_RETURN1(WASM_ONE)));
FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); }
}
WASM_EXEC_TEST(I32x4ReplaceLane) {
FLAG_wasm_simd_prototype = true;
WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32(),
MachineType::Int32());
byte old_val = 0;
byte new_val = 1;
byte simd = r.AllocateLocal(kAstS128);
BUILD(r, WASM_BLOCK(
WASM_SET_LOCAL(simd,
WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(old_val))),
WASM_SET_LOCAL(
simd, WASM_SIMD_I32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd),
WASM_GET_LOCAL(new_val))),
WASM_SIMD_CHECK4(I32x4, simd, I32, new_val, old_val, old_val,
old_val),
WASM_SET_LOCAL(
simd, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd),
WASM_GET_LOCAL(new_val))),
WASM_SIMD_CHECK4(I32x4, simd, I32, new_val, new_val, old_val,
old_val),
WASM_SET_LOCAL(
simd, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd),
WASM_GET_LOCAL(new_val))),
WASM_SIMD_CHECK4(I32x4, simd, I32, new_val, new_val, new_val,
old_val),
WASM_SET_LOCAL(
simd, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd),
WASM_GET_LOCAL(new_val))),
WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, new_val),
WASM_RETURN1(WASM_ONE)));
CHECK_EQ(1, r.Call(1, 2));
}
WASM_EXEC_TEST(I32x4Add) {
FLAG_wasm_simd_prototype = true;
WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32(),
MachineType::Int32(), MachineType::Int32());
byte a = 0;
byte b = 1;
byte expected = 2;
byte simd0 = r.AllocateLocal(kAstS128);
byte simd1 = r.AllocateLocal(kAstS128);
BUILD(r, BUILD(r,
WASM_BLOCK( WASM_BLOCK(
WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))), WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE( WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))),
0, WASM_GET_LOCAL(1))), WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_ADD(WASM_GET_LOCAL(simd0),
WASM_RETURN1(WASM_ZERO)), WASM_GET_LOCAL(simd1))),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE( WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected),
1, WASM_GET_LOCAL(1))),
WASM_RETURN1(WASM_ZERO)),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE(
2, WASM_GET_LOCAL(1))),
WASM_RETURN1(WASM_ZERO)),
WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE(
3, WASM_GET_LOCAL(1))),
WASM_RETURN1(WASM_ZERO)),
WASM_RETURN1(WASM_ONE))); WASM_RETURN1(WASM_ONE)));
FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); } FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, *i + *j)); }
}
}
WASM_EXEC_TEST(I32x4Sub) {
FLAG_wasm_simd_prototype = true;
WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32(),
MachineType::Int32(), MachineType::Int32());
byte a = 0;
byte b = 1;
byte expected = 2;
byte simd0 = r.AllocateLocal(kAstS128);
byte simd1 = r.AllocateLocal(kAstS128);
BUILD(r,
WASM_BLOCK(
WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))),
WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))),
WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SUB(WASM_GET_LOCAL(simd0),
WASM_GET_LOCAL(simd1))),
WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected),
WASM_RETURN1(WASM_ONE)));
FOR_INT32_INPUTS(i) {
FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, *i - *j)); }
}
} }
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