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

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

This is a follow up change to https://crrev.com/c/2499294.

SSE instructions require memory operands to be 16-byte aligned, which we
cannot guarantee yet. So we force the operands to be registers in the
instruction selector.

AVX instructiosn (VEX-encoded) support unaligned memory operands, but
can have performance reductions if it crosses cache lines. For
simplicity we also force the operands to be registers.

In the codegen we can remove the case where the operand is not a
register, and also for SSE assert that dst == src.

Bug: v8:9198
Change-Id: Ibee33896dc9cc4e97d792c5b7bdf5e66ce34de9c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2500924Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70814}
parent 38cdb5d1
......@@ -2207,18 +2207,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
case kSSEF32x4Abs: {
XMMRegister dst = i.OutputSimd128Register();
Operand src = i.InputOperand(0);
if (src.is_reg(dst)) {
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ psrld(kScratchDoubleReg, 1);
__ andps(dst, kScratchDoubleReg);
} else {
// TODO(zhin) Improve codegen for this case.
__ pcmpeqd(dst, dst);
__ movups(kScratchDoubleReg, src);
__ psrld(dst, 1);
__ andps(dst, kScratchDoubleReg);
}
DCHECK_EQ(i.InputSimd128Register(0), dst);
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ psrld(kScratchDoubleReg, 1);
__ andps(dst, kScratchDoubleReg);
break;
}
case kAVXF32x4Abs: {
......@@ -2231,18 +2223,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
case kSSEF32x4Neg: {
XMMRegister dst = i.OutputSimd128Register();
Operand src = i.InputOperand(0);
if (src.is_reg(dst)) {
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ pslld(kScratchDoubleReg, 31);
__ xorps(dst, kScratchDoubleReg);
} else {
// TODO(zhin) Improve codegen for this case.
__ pcmpeqd(dst, dst);
__ movups(kScratchDoubleReg, src);
__ pslld(dst, 31);
__ xorps(dst, kScratchDoubleReg);
}
DCHECK_EQ(dst, i.InputSimd128Register(0));
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ pslld(kScratchDoubleReg, 31);
__ xorps(dst, kScratchDoubleReg);
break;
}
case kAVXF32x4Neg: {
......@@ -2254,9 +2238,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
break;
}
case kSSEF32x4Sqrt: {
// TODO(zhin) Improve codegen for this case.
__ movups(kScratchDoubleReg, i.InputOperand(0));
__ sqrtps(i.OutputSimd128Register(), kScratchDoubleReg);
__ sqrtps(i.OutputSimd128Register(), i.InputSimd128Register(0));
break;
}
case kAVXF32x4Sqrt: {
......@@ -3644,16 +3626,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
}
case kSSES128Not: {
XMMRegister dst = i.OutputSimd128Register();
Operand src = i.InputOperand(0);
if (src.is_reg(dst)) {
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ pxor(dst, kScratchDoubleReg);
} else {
// TODO(zhin) Improve codegen for this case.
__ pcmpeqd(dst, dst);
__ movups(kScratchDoubleReg, src);
__ pxor(dst, kScratchDoubleReg);
}
DCHECK_EQ(dst, i.InputSimd128Register(0));
__ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
__ pxor(dst, kScratchDoubleReg);
break;
}
case kAVXS128Not: {
......
......@@ -2433,11 +2433,20 @@ SIMD_UNOP_LIST(VISIT_SIMD_UNOP)
#undef VISIT_SIMD_UNOP
#undef SIMD_UNOP_LIST
// TODO(v8:9198): SSE instructions that read 16 bytes from memory require the
// operand to be 16-byte aligned. AVX instructions relax this requirement, but
// might have reduced performance if the memory crosses cache line. But since we
// have limited xmm registers, this might be okay to alleviate register
// pressure.
#define VISIT_SIMD_UNOP_PREFIX(Opcode) \
void InstructionSelector::Visit##Opcode(Node* node) { \
IA32OperandGenerator g(this); \
InstructionCode opcode = IsSupported(AVX) ? kAVX##Opcode : kSSE##Opcode; \
Emit(opcode, g.DefineAsRegister(node), g.Use(node->InputAt(0))); \
if (IsSupported(AVX)) { \
Emit(kAVX##Opcode, g.DefineAsRegister(node), g.Use(node->InputAt(0))); \
} else { \
Emit(kSSE##Opcode, g.DefineSameAsFirst(node), \
g.UseRegister(node->InputAt(0))); \
} \
}
SIMD_UNOP_PREFIX_LIST(VISIT_SIMD_UNOP_PREFIX)
#undef VISIT_SIMD_UNOP_PREFIX
......
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