Commit d0e6ff15 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Implement v128.const for arm

And removed the ifdef guards around instruction-selector and
tests since v128.const is now implemented for x86, x64, arm, arm64.

Bug: v8:8460
Change-Id: I0ed8aede0a07db2fd286bf0c3385eba1079558f8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2285149
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68745}
parent 07585a34
...@@ -2813,11 +2813,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2813,11 +2813,26 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ vmov(NeonU16, dst, tmp2.low(), 0); __ vmov(NeonU16, dst, tmp2.low(), 0);
break; break;
} }
case kArmS128Const: {
QwNeonRegister dst = i.OutputSimd128Register();
uint64_t imm1 =
i.InputInt32(0) | (static_cast<uint64_t>(i.InputInt32(1)) << 32);
uint64_t imm2 =
i.InputInt32(2) | (static_cast<uint64_t>(i.InputInt32(3)) << 32);
__ vmov(dst.low(), Double(imm1));
__ vmov(dst.high(), Double(imm2));
break;
}
case kArmS128Zero: { case kArmS128Zero: {
__ veor(i.OutputSimd128Register(), i.OutputSimd128Register(), __ veor(i.OutputSimd128Register(), i.OutputSimd128Register(),
i.OutputSimd128Register()); i.OutputSimd128Register());
break; break;
} }
case kArmS128AllOnes: {
__ vceq(i.OutputSimd128Register(), i.OutputSimd128Register(),
i.OutputSimd128Register());
break;
}
case kArmS128Dup: { case kArmS128Dup: {
NeonSize size = static_cast<NeonSize>(i.InputInt32(1)); NeonSize size = static_cast<NeonSize>(i.InputInt32(1));
int lanes = kSimd128Size >> size; int lanes = kSimd128Size >> size;
......
...@@ -277,7 +277,9 @@ namespace compiler { ...@@ -277,7 +277,9 @@ namespace compiler {
V(ArmI8x16RoundingAverageU) \ V(ArmI8x16RoundingAverageU) \
V(ArmI8x16Abs) \ V(ArmI8x16Abs) \
V(ArmI8x16BitMask) \ V(ArmI8x16BitMask) \
V(ArmS128Const) \
V(ArmS128Zero) \ V(ArmS128Zero) \
V(ArmS128AllOnes) \
V(ArmS128Dup) \ V(ArmS128Dup) \
V(ArmS128And) \ V(ArmS128And) \
V(ArmS128Or) \ V(ArmS128Or) \
......
...@@ -257,7 +257,9 @@ int InstructionScheduler::GetTargetInstructionFlags( ...@@ -257,7 +257,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArmI8x16RoundingAverageU: case kArmI8x16RoundingAverageU:
case kArmI8x16Abs: case kArmI8x16Abs:
case kArmI8x16BitMask: case kArmI8x16BitMask:
case kArmS128Const:
case kArmS128Zero: case kArmS128Zero:
case kArmS128AllOnes:
case kArmS128Dup: case kArmS128Dup:
case kArmS128And: case kArmS128And:
case kArmS128Or: case kArmS128Or:
......
...@@ -2650,6 +2650,25 @@ void InstructionSelector::VisitI32x4DotI16x8S(Node* node) { ...@@ -2650,6 +2650,25 @@ void InstructionSelector::VisitI32x4DotI16x8S(Node* node) {
g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps); g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps);
} }
void InstructionSelector::VisitS128Const(Node* node) {
ArmOperandGenerator g(this);
uint32_t val[kSimd128Size / sizeof(uint32_t)];
memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size);
// If all bytes are zeros, avoid emitting code for generic constants.
bool all_zeros = !(val[0] || val[1] || val[2] || val[3]);
bool all_ones = val[0] == UINT32_MAX && val[1] == UINT32_MAX &&
val[2] == UINT32_MAX && val[3] == UINT32_MAX;
InstructionOperand dst = g.DefineAsRegister(node);
if (all_zeros) {
Emit(kArmS128Zero, dst);
} else if (all_ones) {
Emit(kArmS128AllOnes, dst);
} else {
Emit(kArmS128Const, dst, g.UseImmediate(val[0]), g.UseImmediate(val[1]),
g.UseImmediate(val[2]), g.UseImmediate(val[3]));
}
}
void InstructionSelector::VisitS128Zero(Node* node) { void InstructionSelector::VisitS128Zero(Node* node) {
ArmOperandGenerator g(this); ArmOperandGenerator g(this);
Emit(kArmS128Zero, g.DefineAsRegister(node)); Emit(kArmS128Zero, g.DefineAsRegister(node));
......
...@@ -3317,7 +3317,7 @@ void InstructionSelector::VisitS128Const(Node* node) { ...@@ -3317,7 +3317,7 @@ void InstructionSelector::VisitS128Const(Node* node) {
STATIC_ASSERT(sizeof(val) == kSimd128Size); STATIC_ASSERT(sizeof(val) == kSimd128Size);
memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size); memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size);
// If all bytes are zeros, avoid emitting code for generic constants // If all bytes are zeros, avoid emitting code for generic constants
bool all_zeros = !(val[0] && val[1] && val[2] && val[3]); bool all_zeros = !(val[0] || val[1] || val[2] || val[3]);
InstructionOperand dst = g.DefineAsRegister(node); InstructionOperand dst = g.DefineAsRegister(node);
if (all_zeros) { if (all_zeros) {
Emit(kArm64S128Zero, dst); Emit(kArm64S128Zero, dst);
......
...@@ -2187,7 +2187,7 @@ void InstructionSelector::VisitS128Const(Node* node) { ...@@ -2187,7 +2187,7 @@ void InstructionSelector::VisitS128Const(Node* node) {
uint32_t val[kUint32Immediates]; uint32_t val[kUint32Immediates];
memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size); memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size);
// If all bytes are zeros or ones, avoid emitting code for generic constants // If all bytes are zeros or ones, avoid emitting code for generic constants
bool all_zeros = !(val[0] && val[1] && val[2] && val[3]); bool all_zeros = !(val[0] || val[1] || val[2] || val[3]);
bool all_ones = val[0] == UINT32_MAX && val[1] == UINT32_MAX && bool all_ones = val[0] == UINT32_MAX && val[1] == UINT32_MAX &&
val[2] == UINT32_MAX && val[3] == UINT32_MAX; val[2] == UINT32_MAX && val[3] == UINT32_MAX;
InstructionOperand dst = g.DefineAsRegister(node); InstructionOperand dst = g.DefineAsRegister(node);
......
...@@ -2712,12 +2712,6 @@ void InstructionSelector::VisitI32x4DotI16x8S(Node* node) { UNIMPLEMENTED(); } ...@@ -2712,12 +2712,6 @@ void InstructionSelector::VisitI32x4DotI16x8S(Node* node) { UNIMPLEMENTED(); }
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM64 #endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM64
// && !V8_TARGET_ARCH_ARM // && !V8_TARGET_ARCH_ARM
#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_S390X && \
!V8_TARGET_ARCH_IA32
void InstructionSelector::VisitS128Const(Node* node) { UNIMPLEMENTED(); }
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_S390X
// && !V8_TARGET_ARCH_IA32
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); } void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
void InstructionSelector::VisitParameter(Node* node) { void InstructionSelector::VisitParameter(Node* node) {
......
...@@ -2815,7 +2815,7 @@ void InstructionSelector::VisitS128Const(Node* node) { ...@@ -2815,7 +2815,7 @@ void InstructionSelector::VisitS128Const(Node* node) {
uint32_t val[kUint32Immediates]; uint32_t val[kUint32Immediates];
memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size); memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size);
// If all bytes are zeros or ones, avoid emitting code for generic constants // If all bytes are zeros or ones, avoid emitting code for generic constants
bool all_zeros = !(val[0] && val[1] && val[2] && val[3]); bool all_zeros = !(val[0] || val[1] || val[2] || val[3]);
bool all_ones = val[0] == UINT32_MAX && val[1] == UINT32_MAX && bool all_ones = val[0] == UINT32_MAX && val[1] == UINT32_MAX &&
val[2] == UINT32_MAX && val[3] == UINT32_MAX; val[2] == UINT32_MAX && val[3] == UINT32_MAX;
InstructionOperand dst = g.DefineAsRegister(node); InstructionOperand dst = g.DefineAsRegister(node);
......
...@@ -3688,8 +3688,6 @@ void RunSimdConstTest(ExecutionTier execution_tier, LowerSimd lower_simd, ...@@ -3688,8 +3688,6 @@ void RunSimdConstTest(ExecutionTier execution_tier, LowerSimd lower_simd,
} }
} }
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X || \
V8_TARGET_ARCH_IA32
WASM_SIMD_TEST_NO_LOWERING(S128Const) { WASM_SIMD_TEST_NO_LOWERING(S128Const) {
std::array<uint8_t, kSimd128Size> expected; std::array<uint8_t, kSimd128Size> expected;
// Test for generic constant // Test for generic constant
...@@ -3706,6 +3704,12 @@ WASM_SIMD_TEST_NO_LOWERING(S128ConstAllZero) { ...@@ -3706,6 +3704,12 @@ WASM_SIMD_TEST_NO_LOWERING(S128ConstAllZero) {
expected[i] = 0; expected[i] = 0;
} }
RunSimdConstTest(execution_tier, lower_simd, expected); RunSimdConstTest(execution_tier, lower_simd, expected);
// Keep the first 4 lanes as 0, set the remaining ones.
for (int i = 4; i < kSimd128Size; i++) {
expected[i] = i;
}
RunSimdConstTest(execution_tier, lower_simd, expected);
} }
WASM_SIMD_TEST_NO_LOWERING(S128ConstAllOnes) { WASM_SIMD_TEST_NO_LOWERING(S128ConstAllOnes) {
...@@ -3716,8 +3720,6 @@ WASM_SIMD_TEST_NO_LOWERING(S128ConstAllOnes) { ...@@ -3716,8 +3720,6 @@ WASM_SIMD_TEST_NO_LOWERING(S128ConstAllOnes) {
} }
RunSimdConstTest(execution_tier, lower_simd, expected); RunSimdConstTest(execution_tier, lower_simd, expected);
} }
#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X ||
// V8_TARGET_ARCH_IA32
void RunI8x16MixedRelationalOpTest(ExecutionTier execution_tier, void RunI8x16MixedRelationalOpTest(ExecutionTier execution_tier,
LowerSimd lower_simd, WasmOpcode opcode, LowerSimd lower_simd, WasmOpcode opcode,
......
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