Commit 1043f49d authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Implement v128.const for ia32

Drive-by fix for x64 to remove unused temporary register.

Bug: v8:8460
Change-Id: Ib4e83bad4e14670ccd93dd10e16c5483eb0897b8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2283233
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68724}
parent 93c0be4b
......@@ -3613,11 +3613,28 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Pmovmskb(i.OutputRegister(), i.InputSimd128Register(0));
break;
}
case kIA32S128Const: {
XMMRegister dst = i.OutputSimd128Register();
Register tmp = i.TempRegister(0);
uint64_t low_qword =
i.InputUint32(0) | (uint64_t{i.InputUint32(1)} << 32);
__ Move(dst, low_qword);
__ Move(tmp, Immediate(i.InputUint32(2)));
__ Pinsrd(dst, tmp, 2);
__ Move(tmp, Immediate(i.InputUint32(3)));
__ Pinsrd(dst, tmp, 3);
break;
}
case kIA32S128Zero: {
XMMRegister dst = i.OutputSimd128Register();
__ Pxor(dst, dst);
break;
}
case kIA32S128AllOnes: {
XMMRegister dst = i.OutputSimd128Register();
__ Pcmpeqd(dst, dst);
break;
}
case kSSES128Not: {
XMMRegister dst = i.OutputSimd128Register();
Operand src = i.InputOperand(0);
......
......@@ -341,7 +341,9 @@ namespace compiler {
V(IA32I8x16RoundingAverageU) \
V(IA32I8x16Abs) \
V(IA32I8x16BitMask) \
V(IA32S128Const) \
V(IA32S128Zero) \
V(IA32S128AllOnes) \
V(SSES128Not) \
V(AVXS128Not) \
V(SSES128And) \
......
......@@ -322,7 +322,9 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kIA32I8x16RoundingAverageU:
case kIA32I8x16Abs:
case kIA32I8x16BitMask:
case kIA32S128Const:
case kIA32S128Zero:
case kIA32S128AllOnes:
case kSSES128Not:
case kAVXS128Not:
case kSSES128And:
......
......@@ -2181,6 +2181,30 @@ void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) {
V(I16x8ShrS) \
V(I16x8ShrU)
void InstructionSelector::VisitS128Const(Node* node) {
IA32OperandGenerator g(this);
static const int kUint32Immediates = kSimd128Size / sizeof(uint32_t);
uint32_t val[kUint32Immediates];
memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size);
// 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_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(kIA32S128Zero, dst);
} else if (all_ones) {
Emit(kIA32S128AllOnes, dst);
} else {
InstructionOperand inputs[kUint32Immediates];
for (int i = 0; i < kUint32Immediates; ++i) {
inputs[i] = g.UseImmediate(val[i]);
}
InstructionOperand temp(g.TempRegister());
Emit(kIA32S128Const, 1, &dst, kUint32Immediates, inputs, 1, &temp);
}
}
void InstructionSelector::VisitF64x2Min(Node* node) {
IA32OperandGenerator g(this);
InstructionOperand temps[] = {g.TempSimd128Register()};
......
......@@ -2712,9 +2712,11 @@ void InstructionSelector::VisitI32x4DotI16x8S(Node* node) { UNIMPLEMENTED(); }
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM64
// && !V8_TARGET_ARCH_ARM
#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_S390X
#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); }
......
......@@ -2811,9 +2811,8 @@ VISIT_ATOMIC_BINOP(Xor)
void InstructionSelector::VisitS128Const(Node* node) {
X64OperandGenerator g(this);
static const int kUint32Immediates = 4;
static const int kUint32Immediates = kSimd128Size / sizeof(uint32_t);
uint32_t val[kUint32Immediates];
STATIC_ASSERT(sizeof(val) == kSimd128Size);
memcpy(val, S128ImmediateParameterOf(node->op()).data(), kSimd128Size);
// If all bytes are zeros or ones, avoid emitting code for generic constants
bool all_zeros = !(val[0] && val[1] && val[2] && val[3]);
......@@ -2825,12 +2824,8 @@ void InstructionSelector::VisitS128Const(Node* node) {
} else if (all_ones) {
Emit(kX64S128AllOnes, dst);
} else {
InstructionOperand inputs[kUint32Immediates];
for (int i = 0; i < kUint32Immediates; ++i) {
inputs[i] = g.UseImmediate(val[i]);
}
InstructionOperand temp(g.TempSimd128Register());
Emit(kX64S128Const, 1, &dst, kUint32Immediates, inputs, 1, &temp);
Emit(kX64S128Const, dst, g.UseImmediate(val[0]), g.UseImmediate(val[1]),
g.UseImmediate(val[2]), g.UseImmediate(val[3]));
}
}
......
......@@ -3689,7 +3689,8 @@ void RunSimdConstTest(ExecutionTier execution_tier, LowerSimd lower_simd,
}
}
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X || \
V8_TARGET_ARCH_IA32
WASM_SIMD_TEST_NO_LOWERING(S128Const) {
std::array<uint8_t, kSimd128Size> expected;
// Test for generic constant
......@@ -3716,7 +3717,8 @@ WASM_SIMD_TEST_NO_LOWERING(S128ConstAllOnes) {
}
RunSimdConstTest(execution_tier, lower_simd, expected);
}
#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X
#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_S390X ||
// V8_TARGET_ARCH_IA32
void RunI8x16MixedRelationalOpTest(ExecutionTier execution_tier,
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