[wasm-simd][arm64] prototype i64x2 widen i32x4

Prototype these 4 instructions:

- i64x2.widen_low_i32x4_s
- i64x2.widen_high_i32x4_s
- i64x2.widen_low_i32x4_u
- i64x2.widen_high_i32x4_u

Bug: v8:10972
Change-Id: I3cc3bfdd6dfd0f0bab1dfef63399ed9fa68bd2d2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2441369
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: Bill Budge <bbudge@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70395}
This commit is contained in:
Ng Zhi An 2020-10-06 13:45:45 -07:00 committed by Commit Bot
parent 23b5d936cd
commit 9f0b3413b1
10 changed files with 121 additions and 5 deletions

View File

@ -3725,6 +3725,22 @@ void VisitSignExtendLong(InstructionSelector* selector, ArchOpcode opcode,
}
} // namespace
void InstructionSelector::VisitI64x2SConvertI32x4Low(Node* node) {
VisitSignExtendLong(this, kArm64Sxtl, node, 64);
}
void InstructionSelector::VisitI64x2SConvertI32x4High(Node* node) {
VisitSignExtendLong(this, kArm64Sxtl2, node, 64);
}
void InstructionSelector::VisitI64x2UConvertI32x4Low(Node* node) {
VisitSignExtendLong(this, kArm64Uxtl, node, 64);
}
void InstructionSelector::VisitI64x2UConvertI32x4High(Node* node) {
VisitSignExtendLong(this, kArm64Uxtl2, node, 64);
}
void InstructionSelector::VisitI32x4SConvertI16x8Low(Node* node) {
VisitSignExtendLong(this, kArm64Sxtl, node, 32);
}

View File

@ -1982,6 +1982,14 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsSimd128(node), VisitI64x2ReplaceLaneI32Pair(node);
case IrOpcode::kI64x2Neg:
return MarkAsSimd128(node), VisitI64x2Neg(node);
case IrOpcode::kI64x2SConvertI32x4Low:
return MarkAsSimd128(node), VisitI64x2SConvertI32x4Low(node);
case IrOpcode::kI64x2SConvertI32x4High:
return MarkAsSimd128(node), VisitI64x2SConvertI32x4High(node);
case IrOpcode::kI64x2UConvertI32x4Low:
return MarkAsSimd128(node), VisitI64x2UConvertI32x4Low(node);
case IrOpcode::kI64x2UConvertI32x4High:
return MarkAsSimd128(node), VisitI64x2UConvertI32x4High(node);
case IrOpcode::kI64x2Shl:
return MarkAsSimd128(node), VisitI64x2Shl(node);
case IrOpcode::kI64x2ShrS:
@ -2696,9 +2704,26 @@ void InstructionSelector::VisitI32x4DotI16x8S(Node* node) { UNIMPLEMENTED(); }
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM64
// && !V8_TARGET_ARCH_ARM
// TODO(v8:10971) Prototype i16x8.q15mulr_sat_s
#if !V8_TARGET_ARCH_ARM64
// TODO(v8:10971) Prototype i16x8.q15mulr_sat_s
void InstructionSelector::VisitI16x8Q15MulRSatS(Node* node) { UNIMPLEMENTED(); }
// TODO(v8:10972) Prototype i64x2 widen i32x4.
void InstructionSelector::VisitI64x2SConvertI32x4Low(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitI64x2SConvertI32x4High(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitI64x2UConvertI32x4Low(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitI64x2UConvertI32x4High(Node* node) {
UNIMPLEMENTED();
}
#endif // !V8_TARGET_ARCH_ARM64
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }

View File

@ -375,6 +375,10 @@ ShiftKind ShiftKindOf(Operator const* op) {
V(I64x2Splat, Operator::kNoProperties, 1, 0, 1) \
V(I64x2SplatI32Pair, Operator::kNoProperties, 2, 0, 1) \
V(I64x2Neg, Operator::kNoProperties, 1, 0, 1) \
V(I64x2SConvertI32x4Low, Operator::kNoProperties, 1, 0, 1) \
V(I64x2SConvertI32x4High, Operator::kNoProperties, 1, 0, 1) \
V(I64x2UConvertI32x4Low, Operator::kNoProperties, 1, 0, 1) \
V(I64x2UConvertI32x4High, Operator::kNoProperties, 1, 0, 1) \
V(I64x2Shl, Operator::kNoProperties, 2, 0, 1) \
V(I64x2ShrS, Operator::kNoProperties, 2, 0, 1) \
V(I64x2Add, Operator::kCommutative, 2, 0, 1) \

View File

@ -635,6 +635,10 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
const Operator* I64x2ReplaceLane(int32_t);
const Operator* I64x2ReplaceLaneI32Pair(int32_t);
const Operator* I64x2Neg();
const Operator* I64x2SConvertI32x4Low();
const Operator* I64x2SConvertI32x4High();
const Operator* I64x2UConvertI32x4Low();
const Operator* I64x2UConvertI32x4High();
const Operator* I64x2Shl();
const Operator* I64x2ShrS();
const Operator* I64x2Add();

View File

@ -819,6 +819,10 @@
V(I64x2ReplaceLane) \
V(I64x2ReplaceLaneI32Pair) \
V(I64x2Neg) \
V(I64x2SConvertI32x4Low) \
V(I64x2SConvertI32x4High) \
V(I64x2UConvertI32x4Low) \
V(I64x2UConvertI32x4High) \
V(I64x2Shl) \
V(I64x2ShrS) \
V(I64x2Add) \

View File

@ -4558,6 +4558,18 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
return graph()->NewNode(mcgraph()->machine()->I64x2Splat(), inputs[0]);
case wasm::kExprI64x2Neg:
return graph()->NewNode(mcgraph()->machine()->I64x2Neg(), inputs[0]);
case wasm::kExprI64x2SConvertI32x4Low:
return graph()->NewNode(mcgraph()->machine()->I64x2SConvertI32x4Low(),
inputs[0]);
case wasm::kExprI64x2SConvertI32x4High:
return graph()->NewNode(mcgraph()->machine()->I64x2SConvertI32x4High(),
inputs[0]);
case wasm::kExprI64x2UConvertI32x4Low:
return graph()->NewNode(mcgraph()->machine()->I64x2UConvertI32x4Low(),
inputs[0]);
case wasm::kExprI64x2UConvertI32x4High:
return graph()->NewNode(mcgraph()->machine()->I64x2UConvertI32x4High(),
inputs[0]);
case wasm::kExprI64x2Shl:
return graph()->NewNode(mcgraph()->machine()->I64x2Shl(), inputs[0],
inputs[1]);

View File

@ -278,6 +278,8 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_SIGN_OP(I64x2, Gt, "gt")
CASE_SIGN_OP(SIMDI, Ge, "ge")
CASE_SIGN_OP(I64x2, Ge, "ge")
CASE_CONVERT_OP(Convert, I64x2, I32x4Low, "i32", "convert")
CASE_CONVERT_OP(Convert, I64x2, I32x4High, "i32", "convert")
CASE_SIGN_OP(SIMDI, Shr, "shr")
CASE_SIGN_OP(I64x2, Shr, "shr")
CASE_SIMDI_OP(Shl, "shl")

View File

@ -417,6 +417,10 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(I32x4MaxS, 0xfdb8, s_ss) \
V(I32x4MaxU, 0xfdb9, s_ss) \
V(I64x2Neg, 0xfdc1, s_s) \
V(I64x2SConvertI32x4Low, 0xfdc7, s_s) \
V(I64x2SConvertI32x4High, 0xfdc8, s_s) \
V(I64x2UConvertI32x4Low, 0xfdc9, s_s) \
V(I64x2UConvertI32x4High, 0xfdca, s_s) \
V(I64x2Shl, 0xfdcb, s_si) \
V(I64x2ShrS, 0xfdcc, s_si) \
V(I64x2ShrU, 0xfdcd, s_si) \
@ -471,10 +475,10 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(I64x2Ne, 0xfdc4, s_ss) \
V(I64x2LtS, 0xfdc5, s_ss) \
V(I64x2LtU, 0xfdc6, s_ss) \
V(I64x2GtS, 0xfdc7, s_ss) \
V(I64x2GtU, 0xfdc8, s_ss) \
V(I64x2LeS, 0xfdc9, s_ss) \
V(I64x2LeU, 0xfdca, s_ss) \
V(I64x2GtS, 0xfdd2, s_ss) \
V(I64x2GtU, 0xfdd3, s_ss) \
V(I64x2LeS, 0xfda5, s_ss) \
V(I64x2LeU, 0xfda6, s_ss) \
V(I64x2GeS, 0xfdcf, s_ss) \
V(I64x2GeU, 0xfdd0, s_ss) \
V(I64x2MinS, 0xfdd6, s_ss) \

View File

@ -1829,6 +1829,44 @@ WASM_SIMD_TEST(I32x4ConvertI16x8) {
}
}
// TODO(v8:10972) Prototyping i64x2 convert from i32x4.
// Tests both signed and unsigned conversion from I32x4 (unpacking).
#if V8_TARGET_ARCH_ARM64
WASM_SIMD_TEST_NO_LOWERING(I64x2ConvertI32x4) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);
// Create four output vectors to hold signed and unsigned results.
int64_t* g0 = r.builder().AddGlobal<int64_t>(kWasmS128);
int64_t* g1 = r.builder().AddGlobal<int64_t>(kWasmS128);
int64_t* g2 = r.builder().AddGlobal<int64_t>(kWasmS128);
int64_t* g3 = r.builder().AddGlobal<int64_t>(kWasmS128);
// Build fn to splat test value, perform conversions, and write the results.
byte value = 0;
byte temp1 = r.AllocateLocal(kWasmS128);
BUILD(r, WASM_SET_LOCAL(temp1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(value))),
WASM_SET_GLOBAL(0, WASM_SIMD_UNOP(kExprI64x2SConvertI32x4High,
WASM_GET_LOCAL(temp1))),
WASM_SET_GLOBAL(1, WASM_SIMD_UNOP(kExprI64x2SConvertI32x4Low,
WASM_GET_LOCAL(temp1))),
WASM_SET_GLOBAL(2, WASM_SIMD_UNOP(kExprI64x2UConvertI32x4High,
WASM_GET_LOCAL(temp1))),
WASM_SET_GLOBAL(3, WASM_SIMD_UNOP(kExprI64x2UConvertI32x4Low,
WASM_GET_LOCAL(temp1))),
WASM_ONE);
FOR_INT32_INPUTS(x) {
r.Call(x);
int64_t expected_signed = static_cast<int64_t>(Widen<int32_t>(x));
int64_t expected_unsigned = static_cast<int64_t>(UnsignedWiden<int32_t>(x));
for (int i = 0; i < 2; i++) {
CHECK_EQ(expected_signed, ReadLittleEndianValue<int64_t>(&g0[i]));
CHECK_EQ(expected_signed, ReadLittleEndianValue<int64_t>(&g1[i]));
CHECK_EQ(expected_unsigned, ReadLittleEndianValue<int64_t>(&g2[i]));
CHECK_EQ(expected_unsigned, ReadLittleEndianValue<int64_t>(&g3[i]));
}
}
}
#endif // V8_TARGET_ARCH_ARM64
void RunI32x4UnOpTest(TestExecutionTier execution_tier, LowerSimd lower_simd,
WasmOpcode opcode, Int32UnOp expected_op) {
WasmRunner<int32_t, int32_t> r(execution_tier, lower_simd);

View File

@ -2477,6 +2477,13 @@ class WasmInterpreterInternals {
? 0
: a<0 ? 0 : a> kMaxUInt32 ? kMaxUInt32
: static_cast<uint32_t>(a))
CONVERT_CASE(I64x2SConvertI32x4Low, int4, i32x4, int2, 2, 0, int32_t, a)
CONVERT_CASE(I64x2SConvertI32x4High, int4, i32x4, int2, 2, 2, int32_t,
a)
CONVERT_CASE(I64x2UConvertI32x4Low, int4, i32x4, int2, 2, 0, uint32_t,
a)
CONVERT_CASE(I64x2UConvertI32x4High, int4, i32x4, int2, 2, 2, uint32_t,
a)
CONVERT_CASE(I32x4SConvertI16x8High, int8, i16x8, int4, 4, 4, int16_t,
a)
CONVERT_CASE(I32x4UConvertI16x8High, int8, i16x8, int4, 4, 4, uint16_t,