[wasm simd] Implement I64x2Add I64x2Sub on x64
Bug: v8:8460 Change-Id: I49c745f4dc2a97249621598ad0044c546638a9d5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1678402 Commit-Queue: Zhi An Ng <zhin@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Deepti Gandluri <gdeepti@chromium.org> Auto-Submit: Zhi An Ng <zhin@chromium.org> Cr-Commit-Position: refs/heads/master@{#62495}
This commit is contained in:
parent
c84e19eae0
commit
2e0faaf9a7
@ -21,6 +21,7 @@
|
||||
V(paddb, 66, 0F, FC) \
|
||||
V(paddw, 66, 0F, FD) \
|
||||
V(paddd, 66, 0F, FE) \
|
||||
V(paddq, 66, 0F, D4) \
|
||||
V(paddsb, 66, 0F, EC) \
|
||||
V(paddsw, 66, 0F, ED) \
|
||||
V(paddusb, 66, 0F, DC) \
|
||||
@ -46,6 +47,7 @@
|
||||
V(psubb, 66, 0F, F8) \
|
||||
V(psubw, 66, 0F, F9) \
|
||||
V(psubd, 66, 0F, FA) \
|
||||
V(psubq, 66, 0F, FB) \
|
||||
V(psubsb, 66, 0F, E8) \
|
||||
V(psubsw, 66, 0F, E9) \
|
||||
V(psubusb, 66, 0F, D8) \
|
||||
|
@ -1857,6 +1857,10 @@ void InstructionSelector::VisitNode(Node* node) {
|
||||
return MarkAsWord64(node), VisitI64x2ExtractLane(node);
|
||||
case IrOpcode::kI64x2ReplaceLane:
|
||||
return MarkAsSimd128(node), VisitI64x2ReplaceLane(node);
|
||||
case IrOpcode::kI64x2Add:
|
||||
return MarkAsSimd128(node), VisitI64x2Add(node);
|
||||
case IrOpcode::kI64x2Sub:
|
||||
return MarkAsSimd128(node), VisitI64x2Sub(node);
|
||||
case IrOpcode::kI32x4Splat:
|
||||
return MarkAsSimd128(node), VisitI32x4Splat(node);
|
||||
case IrOpcode::kI32x4ExtractLane:
|
||||
@ -2505,6 +2509,8 @@ void InstructionSelector::VisitF64x2Splat(Node* node) { UNIMPLEMENTED(); }
|
||||
void InstructionSelector::VisitI64x2Splat(Node* node) { UNIMPLEMENTED(); }
|
||||
void InstructionSelector::VisitI64x2ExtractLane(Node* node) { UNIMPLEMENTED(); }
|
||||
void InstructionSelector::VisitI64x2ReplaceLane(Node* node) { UNIMPLEMENTED(); }
|
||||
void InstructionSelector::VisitI64x2Add(Node* node) { UNIMPLEMENTED(); }
|
||||
void InstructionSelector::VisitI64x2Sub(Node* node) { UNIMPLEMENTED(); }
|
||||
#endif // !V8_TARGET_ARCH_X64
|
||||
|
||||
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
|
||||
|
@ -2434,6 +2434,16 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kX64I64x2Add: {
|
||||
DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0));
|
||||
__ paddq(i.OutputSimd128Register(), i.InputSimd128Register(1));
|
||||
break;
|
||||
}
|
||||
case kX64I64x2Sub: {
|
||||
DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0));
|
||||
__ psubq(i.OutputSimd128Register(), i.InputSimd128Register(1));
|
||||
break;
|
||||
}
|
||||
case kX64I32x4Splat: {
|
||||
XMMRegister dst = i.OutputSimd128Register();
|
||||
if (instr->InputAt(0)->IsRegister()) {
|
||||
|
@ -179,6 +179,8 @@ namespace compiler {
|
||||
V(X64F32x4Lt) \
|
||||
V(X64F32x4Le) \
|
||||
V(X64I64x2Splat) \
|
||||
V(X64I64x2Add) \
|
||||
V(X64I64x2Sub) \
|
||||
V(X64I32x4Splat) \
|
||||
V(X64I64x2ExtractLane) \
|
||||
V(X64I64x2ReplaceLane) \
|
||||
|
@ -145,6 +145,8 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kX64F32x4Lt:
|
||||
case kX64F32x4Le:
|
||||
case kX64I64x2Splat:
|
||||
case kX64I64x2Add:
|
||||
case kX64I64x2Sub:
|
||||
case kX64I32x4Splat:
|
||||
case kX64I64x2ExtractLane:
|
||||
case kX64I64x2ReplaceLane:
|
||||
|
@ -2563,6 +2563,8 @@ VISIT_ATOMIC_BINOP(Xor)
|
||||
V(F32x4Ne) \
|
||||
V(F32x4Lt) \
|
||||
V(F32x4Le) \
|
||||
V(I64x2Add) \
|
||||
V(I64x2Sub) \
|
||||
V(I32x4Add) \
|
||||
V(I32x4AddHoriz) \
|
||||
V(I32x4Sub) \
|
||||
|
@ -264,6 +264,8 @@ MachineType AtomicOpType(Operator const* op) {
|
||||
V(F32x4Lt, Operator::kNoProperties, 2, 0, 1) \
|
||||
V(F32x4Le, Operator::kNoProperties, 2, 0, 1) \
|
||||
V(I64x2Splat, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(I64x2Add, Operator::kCommutative, 2, 0, 1) \
|
||||
V(I64x2Sub, Operator::kNoProperties, 2, 0, 1) \
|
||||
V(I32x4Splat, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(I32x4SConvertF32x4, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(I32x4SConvertI16x8Low, Operator::kNoProperties, 1, 0, 1) \
|
||||
|
@ -493,6 +493,8 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
|
||||
const Operator* I64x2Splat();
|
||||
const Operator* I64x2ExtractLane(int32_t);
|
||||
const Operator* I64x2ReplaceLane(int32_t);
|
||||
const Operator* I64x2Add();
|
||||
const Operator* I64x2Sub();
|
||||
|
||||
const Operator* I32x4Splat();
|
||||
const Operator* I32x4ExtractLane(int32_t);
|
||||
|
@ -756,6 +756,8 @@
|
||||
V(I64x2Splat) \
|
||||
V(I64x2ExtractLane) \
|
||||
V(I64x2ReplaceLane) \
|
||||
V(I64x2Add) \
|
||||
V(I64x2Sub) \
|
||||
V(I32x4Splat) \
|
||||
V(I32x4ExtractLane) \
|
||||
V(I32x4ReplaceLane) \
|
||||
|
@ -4059,6 +4059,12 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
|
||||
inputs[0]);
|
||||
case wasm::kExprI64x2Splat:
|
||||
return graph()->NewNode(mcgraph()->machine()->I64x2Splat(), inputs[0]);
|
||||
case wasm::kExprI64x2Add:
|
||||
return graph()->NewNode(mcgraph()->machine()->I64x2Add(), inputs[0],
|
||||
inputs[1]);
|
||||
case wasm::kExprI64x2Sub:
|
||||
return graph()->NewNode(mcgraph()->machine()->I64x2Sub(), inputs[0],
|
||||
inputs[1]);
|
||||
case wasm::kExprI32x4Splat:
|
||||
return graph()->NewNode(mcgraph()->machine()->I32x4Splat(), inputs[0]);
|
||||
case wasm::kExprI32x4SConvertF32x4:
|
||||
|
@ -1873,6 +1873,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
|
||||
mnemonic = "psrlw";
|
||||
} else if (opcode == 0xD2) {
|
||||
mnemonic = "psrld";
|
||||
} else if (opcode == 0xD4) {
|
||||
mnemonic = "paddq";
|
||||
} else if (opcode == 0xD5) {
|
||||
mnemonic = "pmullw";
|
||||
} else if (opcode == 0xD7) {
|
||||
@ -1923,6 +1925,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
|
||||
mnemonic = "psubw";
|
||||
} else if (opcode == 0xFA) {
|
||||
mnemonic = "psubd";
|
||||
} else if (opcode == 0xFB) {
|
||||
mnemonic = "psubq";
|
||||
} else if (opcode == 0xFC) {
|
||||
mnemonic = "paddb";
|
||||
} else if (opcode == 0xFD) {
|
||||
|
@ -2177,6 +2177,8 @@ class ThreadImpl {
|
||||
BINOP_CASE(F32x4Mul, f32x4, float4, 4, a * b)
|
||||
BINOP_CASE(F32x4Min, f32x4, float4, 4, a < b ? a : b)
|
||||
BINOP_CASE(F32x4Max, f32x4, float4, 4, a > b ? a : b)
|
||||
BINOP_CASE(I64x2Add, i64x2, int2, 2, base::AddWithWraparound(a, b))
|
||||
BINOP_CASE(I64x2Sub, i64x2, int2, 2, base::SubWithWraparound(a, b))
|
||||
BINOP_CASE(I32x4Add, i32x4, int4, 4, base::AddWithWraparound(a, b))
|
||||
BINOP_CASE(I32x4Sub, i32x4, int4, 4, base::SubWithWraparound(a, b))
|
||||
BINOP_CASE(I32x4Mul, i32x4, int4, 4, base::MulWithWraparound(a, b))
|
||||
|
@ -222,7 +222,9 @@ const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
|
||||
CASE_SIMD_OP(Eq, "eq")
|
||||
CASE_SIMD_OP(Ne, "ne")
|
||||
CASE_SIMD_OP(Add, "add")
|
||||
CASE_I64x2_OP(Add, "add")
|
||||
CASE_SIMD_OP(Sub, "sub")
|
||||
CASE_I64x2_OP(Sub, "sub")
|
||||
CASE_SIMD_OP(Mul, "mul")
|
||||
CASE_F64x2_OP(Splat, "splat")
|
||||
CASE_F32x4_OP(Abs, "abs")
|
||||
|
@ -354,6 +354,8 @@ bool IsJSCompatibleSignature(const FunctionSig* sig, bool hasBigIntFeature);
|
||||
V(I32x4MinU, 0xfd81, s_ss) \
|
||||
V(I32x4MaxS, 0xfd82, s_ss) \
|
||||
V(I32x4MaxU, 0xfd83, s_ss) \
|
||||
V(I64x2Add, 0xfd8a, s_ss) \
|
||||
V(I64x2Sub, 0xfd8d, s_ss) \
|
||||
V(F32x4Abs, 0xfd95, s_s) \
|
||||
V(F32x4Neg, 0xfd96, s_s) \
|
||||
V(F32x4RecipApprox, 0xfd98, s_s) \
|
||||
|
@ -22,6 +22,7 @@ namespace {
|
||||
using FloatUnOp = float (*)(float);
|
||||
using FloatBinOp = float (*)(float, float);
|
||||
using FloatCompareOp = int (*)(float, float);
|
||||
using Int64BinOp = int64_t (*)(int64_t, int64_t);
|
||||
using Int32UnOp = int32_t (*)(int32_t);
|
||||
using Int32BinOp = int32_t (*)(int32_t, int32_t);
|
||||
using Int32CompareOp = int (*)(int32_t, int32_t);
|
||||
@ -758,6 +759,42 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ReplaceLane) {
|
||||
CHECK_EQ(i, ReadLittleEndianValue<int64_t>(&g[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void RunI64x2BinOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
|
||||
WasmOpcode opcode, Int64BinOp expected_op) {
|
||||
WasmRunner<int32_t, int64_t, int64_t> r(execution_tier, lower_simd);
|
||||
// Global to hold output.
|
||||
int64_t* g = r.builder().AddGlobal<int64_t>(kWasmS128);
|
||||
// Build fn to splat test values, perform binop, and write the result.
|
||||
byte value1 = 0, value2 = 1;
|
||||
byte temp1 = r.AllocateLocal(kWasmS128);
|
||||
byte temp2 = r.AllocateLocal(kWasmS128);
|
||||
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value1))),
|
||||
WASM_SET_LOCAL(temp2, WASM_SIMD_I64x2_SPLAT(WASM_GET_LOCAL(value2))),
|
||||
WASM_SET_GLOBAL(0, WASM_SIMD_BINOP(opcode, WASM_GET_LOCAL(temp1),
|
||||
WASM_GET_LOCAL(temp2))),
|
||||
WASM_ONE);
|
||||
|
||||
FOR_INT64_INPUTS(x) {
|
||||
FOR_INT64_INPUTS(y) {
|
||||
r.Call(x, y);
|
||||
int64_t expected = expected_op(x, y);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
CHECK_EQ(expected, ReadLittleEndianValue<int64_t>(&g[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WASM_SIMD_TEST_NO_LOWERING(I64x2Add) {
|
||||
RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2Add,
|
||||
base::AddWithWraparound);
|
||||
}
|
||||
|
||||
WASM_SIMD_TEST_NO_LOWERING(I64x2Sub) {
|
||||
RunI64x2BinOpTest(execution_tier, lower_simd, kExprI64x2Sub,
|
||||
base::SubWithWraparound);
|
||||
}
|
||||
#endif // V8_TARGET_ARCH_X64
|
||||
|
||||
WASM_SIMD_TEST(I32x4Splat) {
|
||||
|
Loading…
Reference in New Issue
Block a user