Commit 6fd3109d authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Implement i64x2 splat extract replace for ia32

This introduces 2 new machine operators that are variants of I64x2Splat
and I64x2ReplaceLane that takes two int32 operands instead of one i64
operand.

Bug: v8:9728
Change-Id: I6675f991e6c56821c84d183dacfda96961c1a708
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1841242Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64337}
parent 0d1c4dca
......@@ -1994,6 +1994,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
i.InputOperand(1));
break;
}
case kIA32I64x2SplatI32Pair: {
XMMRegister dst = i.OutputSimd128Register();
__ Pinsrd(dst, i.InputRegister(0), 0);
__ Pinsrd(dst, i.InputOperand(1), 1);
__ Pshufd(dst, dst, 0x44);
break;
}
case kIA32I64x2ReplaceLaneI32Pair: {
int8_t lane = i.InputInt8(1);
__ Pinsrd(i.OutputSimd128Register(), i.InputOperand(2), lane * 2);
__ Pinsrd(i.OutputSimd128Register(), i.InputOperand(3), lane * 2 + 1);
break;
}
case kSSEF32x4Splat: {
DCHECK_EQ(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
XMMRegister dst = i.OutputSimd128Register();
......
......@@ -133,6 +133,8 @@ namespace compiler {
V(IA32F64x2Ne) \
V(IA32F64x2Lt) \
V(IA32F64x2Le) \
V(IA32I64x2SplatI32Pair) \
V(IA32I64x2ReplaceLaneI32Pair) \
V(SSEF32x4Splat) \
V(AVXF32x4Splat) \
V(SSEF32x4ExtractLane) \
......
......@@ -114,6 +114,8 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kIA32F64x2Ne:
case kIA32F64x2Lt:
case kIA32F64x2Le:
case kIA32I64x2SplatI32Pair:
case kIA32I64x2ReplaceLaneI32Pair:
case kSSEF32x4Splat:
case kAVXF32x4Splat:
case kSSEF32x4ExtractLane:
......
......@@ -2085,6 +2085,32 @@ void InstructionSelector::VisitF64x2ExtractLane(Node* node) {
VisitRRISimd(this, node, kAVXF64x2ExtractLane, kSSEF64x2ExtractLane);
}
void InstructionSelector::VisitI64x2SplatI32Pair(Node* node) {
IA32OperandGenerator g(this);
InstructionOperand operand0 = g.UseRegister(node->InputAt(0));
InstructionOperand operand1 = g.Use(node->InputAt(1));
if (IsSupported(AVX)) {
Emit(kIA32I64x2SplatI32Pair, g.DefineAsRegister(node), operand0, operand1);
} else {
Emit(kIA32I64x2SplatI32Pair, g.DefineSameAsFirst(node), operand0, operand1);
}
}
void InstructionSelector::VisitI64x2ReplaceLaneI32Pair(Node* node) {
IA32OperandGenerator g(this);
InstructionOperand operand = g.UseRegister(node->InputAt(0));
InstructionOperand lane = g.UseImmediate(OpParameter<int32_t>(node->op()));
InstructionOperand low = g.Use(node->InputAt(1));
InstructionOperand high = g.Use(node->InputAt(2));
if (IsSupported(AVX)) {
Emit(kIA32I64x2ReplaceLaneI32Pair, g.DefineSameAsFirst(node), operand, lane,
low, high);
} else {
Emit(kIA32I64x2ReplaceLaneI32Pair, g.DefineSameAsFirst(node), operand, lane,
low, high);
}
}
void InstructionSelector::VisitF32x4Splat(Node* node) {
VisitRRSimd(this, node, kAVXF32x4Splat, kSSEF32x4Splat);
}
......
......@@ -1933,10 +1933,14 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsSimd128(node), VisitF32x4Qfms(node);
case IrOpcode::kI64x2Splat:
return MarkAsSimd128(node), VisitI64x2Splat(node);
case IrOpcode::kI64x2SplatI32Pair:
return MarkAsSimd128(node), VisitI64x2SplatI32Pair(node);
case IrOpcode::kI64x2ExtractLane:
return MarkAsWord64(node), VisitI64x2ExtractLane(node);
case IrOpcode::kI64x2ReplaceLane:
return MarkAsSimd128(node), VisitI64x2ReplaceLane(node);
case IrOpcode::kI64x2ReplaceLaneI32Pair:
return MarkAsSimd128(node), VisitI64x2ReplaceLaneI32Pair(node);
case IrOpcode::kI64x2Neg:
return MarkAsSimd128(node), VisitI64x2Neg(node);
case IrOpcode::kI64x2Shl:
......@@ -2621,6 +2625,16 @@ void InstructionSelector::VisitWord64AtomicCompareExchange(Node* node) {
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_PPC
// !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_S390
#if !V8_TARGET_ARCH_IA32
// This is only needed on 32-bit to split the 64-bit value into two operands.
void InstructionSelector::VisitI64x2SplatI32Pair(Node* node) {
UNIMPLEMENTED();
}
void InstructionSelector::VisitI64x2ReplaceLaneI32Pair(Node* node) {
UNIMPLEMENTED();
}
#endif // !V8_TARGET_ARCH_IA32
#if !V8_TARGET_ARCH_X64
#if !V8_TARGET_ARCH_ARM64
#if !V8_TARGET_ARCH_IA32
......
......@@ -957,6 +957,32 @@ void Int64Lowering::LowerNode(Node* node) {
}
break;
}
case IrOpcode::kI64x2Splat: {
DCHECK_EQ(1, node->InputCount());
Node* input = node->InputAt(0);
node->ReplaceInput(0, GetReplacementLow(input));
node->AppendInput(zone(), GetReplacementHigh(input));
NodeProperties::ChangeOp(node, machine()->I64x2SplatI32Pair());
break;
}
case IrOpcode::kI64x2ExtractLane: {
DCHECK_EQ(1, node->InputCount());
Node* input = node->InputAt(0);
int32_t lane = OpParameter<int32_t>(node->op());
ReplaceNode(
node, graph()->NewNode(machine()->I32x4ExtractLane(lane * 2), input),
graph()->NewNode(machine()->I32x4ExtractLane(lane * 2 + 1), input));
break;
}
case IrOpcode::kI64x2ReplaceLane: {
DCHECK_EQ(2, node->InputCount());
int32_t lane = OpParameter<int32_t>(node->op());
Node* input = node->InputAt(1);
node->ReplaceInput(1, GetReplacementLow(input));
node->AppendInput(zone(), GetReplacementHigh(input));
NodeProperties::ChangeOp(node, machine()->I64x2ReplaceLaneI32Pair(lane));
break;
}
default: { DefaultLowering(node); }
}
......
......@@ -291,6 +291,7 @@ MachineType AtomicOpType(Operator const* op) {
V(F32x4Qfma, Operator::kNoProperties, 3, 0, 1) \
V(F32x4Qfms, Operator::kNoProperties, 3, 0, 1) \
V(I64x2Splat, Operator::kNoProperties, 1, 0, 1) \
V(I64x2SplatI32Pair, Operator::kNoProperties, 2, 0, 1) \
V(I64x2Neg, Operator::kNoProperties, 1, 0, 1) \
V(I64x2Shl, Operator::kNoProperties, 2, 0, 1) \
V(I64x2ShrS, Operator::kNoProperties, 2, 0, 1) \
......@@ -1342,6 +1343,14 @@ const Operator* MachineOperatorBuilder::Word64PoisonOnSpeculation() {
SIMD_LANE_OP_LIST(SIMD_LANE_OPS)
#undef SIMD_LANE_OPS
const Operator* MachineOperatorBuilder::I64x2ReplaceLaneI32Pair(
int32_t lane_index) {
DCHECK(0 <= lane_index && lane_index < 2);
return new (zone_)
Operator1<int32_t>(IrOpcode::kI64x2ReplaceLaneI32Pair, Operator::kPure,
"Replace lane", 3, 0, 0, 1, 0, 0, lane_index);
}
const Operator* MachineOperatorBuilder::S8x16Shuffle(
const uint8_t shuffle[16]) {
uint8_t* array = zone_->NewArray<uint8_t>(16);
......
......@@ -524,8 +524,10 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
const Operator* F32x4Qfms();
const Operator* I64x2Splat();
const Operator* I64x2SplatI32Pair();
const Operator* I64x2ExtractLane(int32_t);
const Operator* I64x2ReplaceLane(int32_t);
const Operator* I64x2ReplaceLaneI32Pair(int32_t);
const Operator* I64x2Neg();
const Operator* I64x2Shl();
const Operator* I64x2ShrS();
......
......@@ -794,8 +794,10 @@
V(F32x4Qfma) \
V(F32x4Qfms) \
V(I64x2Splat) \
V(I64x2SplatI32Pair) \
V(I64x2ExtractLane) \
V(I64x2ReplaceLane) \
V(I64x2ReplaceLaneI32Pair) \
V(I64x2Neg) \
V(I64x2Shl) \
V(I64x2ShrS) \
......
......@@ -892,7 +892,6 @@ WASM_SIMD_TEST_NO_LOWERING(F32x4Qfms) {
#endif // V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_IA32
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
WASM_SIMD_TEST_NO_LOWERING(I64x2Splat) {
WasmRunner<int32_t, int64_t> r(execution_tier, lower_simd);
// Set up a global to hold output vector.
......@@ -943,6 +942,7 @@ WASM_SIMD_TEST_NO_LOWERING(I64x2ReplaceLane) {
}
}
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64
void RunI64x2UnOpTest(ExecutionTier execution_tier, LowerSimd lower_simd,
WasmOpcode opcode, Int64UnOp expected_op) {
WasmRunner<int32_t, int64_t> r(execution_tier, lower_simd);
......
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