Commit 7ab60001 authored by Zhi An Ng's avatar Zhi An Ng Committed by Commit Bot

[wasm-simd][ia32] Use register operands for more SIMD instructions

SSE instructions which access 16 bytes of data from the memory
requires aligned access. So we force these instructions to be
registers, since we don't have the correct memory alignment yet.

Bug: v8:9198
Change-Id: I0f654efb95da26b1adc27022747ff45c4d6c5d04
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2500934Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70815}
parent f1d7162e
...@@ -2863,13 +2863,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -2863,13 +2863,13 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
} }
case kSSEI16x8SConvertI32x4: { case kSSEI16x8SConvertI32x4: {
DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0)); DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0));
__ packssdw(i.OutputSimd128Register(), i.InputOperand(1)); __ packssdw(i.OutputSimd128Register(), i.InputSimd128Register(1));
break; break;
} }
case kAVXI16x8SConvertI32x4: { case kAVXI16x8SConvertI32x4: {
CpuFeatureScope avx_scope(tasm(), AVX); CpuFeatureScope avx_scope(tasm(), AVX);
__ vpackssdw(i.OutputSimd128Register(), i.InputSimd128Register(0), __ vpackssdw(i.OutputSimd128Register(), i.InputSimd128Register(0),
i.InputOperand(1)); i.InputSimd128Register(1));
break; break;
} }
case kSSEI16x8Add: { case kSSEI16x8Add: {
...@@ -3032,14 +3032,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ...@@ -3032,14 +3032,14 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kSSEI16x8UConvertI32x4: { case kSSEI16x8UConvertI32x4: {
DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0)); DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0));
CpuFeatureScope sse_scope(tasm(), SSE4_1); CpuFeatureScope sse_scope(tasm(), SSE4_1);
__ packusdw(i.OutputSimd128Register(), i.InputOperand(1)); __ packusdw(i.OutputSimd128Register(), i.InputSimd128Register(1));
break; break;
} }
case kAVXI16x8UConvertI32x4: { case kAVXI16x8UConvertI32x4: {
DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0)); DCHECK_EQ(i.OutputSimd128Register(), i.InputSimd128Register(0));
CpuFeatureScope avx_scope(tasm(), AVX); CpuFeatureScope avx_scope(tasm(), AVX);
XMMRegister dst = i.OutputSimd128Register(); XMMRegister dst = i.OutputSimd128Register();
__ vpackusdw(dst, dst, i.InputOperand(1)); __ vpackusdw(dst, dst, i.InputSimd128Register(1));
break; break;
} }
case kSSEI16x8AddSatU: { case kSSEI16x8AddSatU: {
......
...@@ -2335,6 +2335,7 @@ void InstructionSelector::VisitS128Select(Node* node) { ...@@ -2335,6 +2335,7 @@ void InstructionSelector::VisitS128Select(Node* node) {
IA32OperandGenerator g(this); IA32OperandGenerator g(this);
InstructionOperand operand2 = g.UseRegister(node->InputAt(2)); InstructionOperand operand2 = g.UseRegister(node->InputAt(2));
if (IsSupported(AVX)) { if (IsSupported(AVX)) {
// AVX supports unaligned memory operands, so Use here is okay.
Emit(kAVXS128Select, g.DefineAsRegister(node), g.Use(node->InputAt(0)), Emit(kAVXS128Select, g.DefineAsRegister(node), g.Use(node->InputAt(0)),
g.Use(node->InputAt(1)), operand2); g.Use(node->InputAt(1)), operand2);
} else { } else {
...@@ -2490,11 +2491,15 @@ SIMD_BINOP_UNIFIED_SSE_AVX_LIST(VISIT_SIMD_BINOP_UNIFIED_SSE_AVX) ...@@ -2490,11 +2491,15 @@ SIMD_BINOP_UNIFIED_SSE_AVX_LIST(VISIT_SIMD_BINOP_UNIFIED_SSE_AVX)
#undef VISIT_SIMD_BINOP_UNIFIED_SSE_AVX #undef VISIT_SIMD_BINOP_UNIFIED_SSE_AVX
#undef SIMD_BINOP_UNIFIED_SSE_AVX_LIST #undef SIMD_BINOP_UNIFIED_SSE_AVX_LIST
// TODO(v8:9198): SSE requires operand1 to be a register as we don't have memory
// alignment yet. For AVX, memory operands are fine, but can have performance
// issues if not aligned to 16/32 bytes (based on load size), see SDM Vol 1,
// chapter 14.9
void VisitPack(InstructionSelector* selector, Node* node, ArchOpcode avx_opcode, void VisitPack(InstructionSelector* selector, Node* node, ArchOpcode avx_opcode,
ArchOpcode sse_opcode) { ArchOpcode sse_opcode) {
IA32OperandGenerator g(selector); IA32OperandGenerator g(selector);
InstructionOperand operand0 = g.UseRegister(node->InputAt(0)); InstructionOperand operand0 = g.UseRegister(node->InputAt(0));
InstructionOperand operand1 = g.Use(node->InputAt(1)); InstructionOperand operand1 = g.UseRegister(node->InputAt(1));
if (selector->IsSupported(AVX)) { if (selector->IsSupported(AVX)) {
selector->Emit(avx_opcode, g.DefineSameAsFirst(node), operand0, operand1); selector->Emit(avx_opcode, g.DefineSameAsFirst(node), operand0, operand1);
} else { } else {
......
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