Commit 9ffb4829 authored by Ng Zhi An's avatar Ng Zhi An Committed by V8 LUCI CQ

[wasm-relaxed-simd][x64] Prototype i8x16 relaxed swizzle

Bug: v8:12284
Change-Id: I3519dfa3302c5851585c7430a9930ccd81507090
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3206502
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77327}
parent a57d9aab
......@@ -3687,13 +3687,18 @@ void InstructionSelector::VisitI8x16Shuffle(Node* node) { UNREACHABLE(); }
void InstructionSelector::VisitI8x16Swizzle(Node* node) {
InstructionCode op = kX64I8x16Swizzle;
auto m = V128ConstMatcher(node->InputAt(1));
if (m.HasResolvedValue()) {
// If the indices vector is a const, check if they are in range, or if the
// top bit is set, then we can avoid the paddusb in the codegen and simply
// emit a pshufb
auto imms = m.ResolvedValue().immediate();
op |= MiscField::encode(wasm::SimdSwizzle::AllInRangeOrTopBitSet(imms));
bool relaxed = OpParameter<bool>(node->op());
if (relaxed) {
op |= MiscField::encode(true);
} else {
auto m = V128ConstMatcher(node->InputAt(1));
if (m.HasResolvedValue()) {
// If the indices vector is a const, check if they are in range, or if the
// top bit is set, then we can avoid the paddusb in the codegen and simply
// emit a pshufb.
auto imms = m.ResolvedValue().immediate();
op |= MiscField::encode(wasm::SimdSwizzle::AllInRangeOrTopBitSet(imms));
}
}
X64OperandGenerator g(this);
......
......@@ -597,8 +597,7 @@ std::ostream& operator<<(std::ostream& os, TruncateKind kind) {
V(I64x2AllTrue, Operator::kNoProperties, 1, 0, 1) \
V(I32x4AllTrue, Operator::kNoProperties, 1, 0, 1) \
V(I16x8AllTrue, Operator::kNoProperties, 1, 0, 1) \
V(I8x16AllTrue, Operator::kNoProperties, 1, 0, 1) \
V(I8x16Swizzle, Operator::kNoProperties, 2, 0, 1)
V(I8x16AllTrue, Operator::kNoProperties, 1, 0, 1)
// The format is:
// V(Name, properties, value_input_count, control_input_count, output_count)
......@@ -1282,6 +1281,19 @@ struct MachineOperatorGlobalCache {
STACK_POINTER_GREATER_THAN(CodeStubAssembler)
STACK_POINTER_GREATER_THAN(Wasm)
#undef STACK_POINTER_GREATER_THAN
struct I8x16SwizzleOperator final : public Operator1<bool> {
I8x16SwizzleOperator()
: Operator1<bool>(IrOpcode::kI8x16Swizzle, Operator::kPure,
"I8x16Swizzle", 2, 0, 0, 1, 0, 0, false) {}
};
I8x16SwizzleOperator kI8x16Swizzle;
struct I8x16RelaxedSwizzleOperator final : public Operator1<bool> {
I8x16RelaxedSwizzleOperator()
: Operator1<bool>(IrOpcode::kI8x16Swizzle, Operator::kPure,
"I8x16RelaxedSwizzle", 2, 0, 0, 1, 0, 0, true) {}
};
I8x16RelaxedSwizzleOperator kI8x16RelaxedSwizzle;
};
struct CommentOperator : public Operator1<const char*> {
......@@ -2003,6 +2015,14 @@ const Operator* MachineOperatorBuilder::I8x16Shuffle(
S128ImmediateParameter(shuffle));
}
const Operator* MachineOperatorBuilder::I8x16Swizzle(bool relaxed) {
if (relaxed) {
return &cache_.kI8x16RelaxedSwizzle;
} else {
return &cache_.kI8x16Swizzle;
}
}
StackCheckKind StackCheckKindOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kStackPointerGreaterThan, op->opcode());
return OpParameter<StackCheckKind>(op);
......
......@@ -905,7 +905,7 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
const Operator* S128Select();
const Operator* S128AndNot();
const Operator* I8x16Swizzle();
const Operator* I8x16Swizzle(bool relaxed = false);
const Operator* I8x16Shuffle(const uint8_t shuffle[16]);
const Operator* V128AnyTrue();
......
......@@ -5111,8 +5111,11 @@ Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* const* inputs) {
case wasm::kExprI8x16AllTrue:
return graph()->NewNode(mcgraph()->machine()->I8x16AllTrue(), inputs[0]);
case wasm::kExprI8x16Swizzle:
return graph()->NewNode(mcgraph()->machine()->I8x16Swizzle(), inputs[0],
inputs[1]);
return graph()->NewNode(mcgraph()->machine()->I8x16Swizzle(false),
inputs[0], inputs[1]);
case wasm::kExprI8x16RelaxedSwizzle:
return graph()->NewNode(mcgraph()->machine()->I8x16Swizzle(true),
inputs[0], inputs[1]);
default:
FATAL_UNSUPPORTED_OPCODE(opcode);
}
......
......@@ -259,8 +259,6 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_SIMDF_OP(Gt, "gt")
CASE_SIMDF_OP(Ge, "ge")
CASE_SIMDF_OP(Abs, "abs")
CASE_F32x4_OP(RecipApprox, "recip_approx")
CASE_F32x4_OP(RecipSqrtApprox, "recip_sqrt_approx")
CASE_SIMDF_OP(Min, "min")
CASE_SIMDF_OP(Max, "max")
CASE_CONVERT_OP(Convert, F32x4, I32x4, "i32x4", "convert")
......@@ -306,8 +304,6 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_I8x16_OP(Shuffle, "shuffle")
CASE_V128_OP(AnyTrue, "any_true")
CASE_SIMDI_OP(AllTrue, "all_true")
CASE_SIMDF_OP(Qfma, "qfma")
CASE_SIMDF_OP(Qfms, "qfms")
CASE_S128_OP(Load32Zero, "load32_zero")
CASE_S128_OP(Load64Zero, "load64_zero")
......@@ -366,6 +362,13 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_F32x4_OP(DemoteF64x2Zero, "demote_f64x2_zero")
CASE_F64x2_OP(PromoteLowF32x4, "promote_low_f32x4")
// Relaxed SIMD opcodes.
CASE_F32x4_OP(RecipApprox, "recip_approx")
CASE_F32x4_OP(RecipSqrtApprox, "recip_sqrt_approx")
CASE_SIMDF_OP(Qfma, "qfma")
CASE_SIMDF_OP(Qfms, "qfms")
CASE_I8x16_OP(RelaxedSwizzle, "relaxed_swizzle");
// Atomic operations.
CASE_OP(AtomicNotify, "atomic.notify")
CASE_INT_OP(AtomicWait, "atomic.wait")
......
......@@ -515,6 +515,7 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(F64x2ConvertLowI32x4U, 0xfdff, s_s)
#define FOREACH_RELAXED_SIMD_OPCODE(V) \
V(I8x16RelaxedSwizzle, 0xfda2, s_ss) \
V(F32x4Qfma, 0xfdaf, s_sss) \
V(F32x4Qfms, 0xfdb0, s_sss) \
V(F64x2Qfma, 0xfdcf, s_sss) \
......
......@@ -230,6 +230,30 @@ WASM_RELAXED_SIMD_TEST(F32x4RecipSqrtApprox) {
false /* !exact */);
}
#if V8_TARGET_ARCH_X64
WASM_RELAXED_SIMD_TEST(I8x16RelaxedSwizzle) {
// Output is only defined for indices in the range [0,15].
WasmRunner<int32_t> r(execution_tier);
static const int kElems = kSimd128Size / sizeof(uint8_t);
uint8_t* dst = r.builder().AddGlobal<uint8_t>(kWasmS128);
uint8_t* src = r.builder().AddGlobal<uint8_t>(kWasmS128);
uint8_t* indices = r.builder().AddGlobal<uint8_t>(kWasmS128);
BUILD(r,
WASM_GLOBAL_SET(
0, WASM_SIMD_BINOP(kExprI8x16RelaxedSwizzle, WASM_GLOBAL_GET(1),
WASM_GLOBAL_GET(2))),
WASM_ONE);
for (int i = 0; i < kElems; i++) {
LANE(src, i) = kElems - i - 1;
LANE(indices, i) = kElems - i - 1;
}
CHECK_EQ(1, r.Call());
for (int i = 0; i < kElems; i++) {
CHECK_EQ(LANE(dst, i), i);
}
}
#endif // V8_TARGET_ARCH_X64
#undef WASM_RELAXED_SIMD_TEST
} // namespace test_run_wasm_relaxed_simd
} // namespace wasm
......
......@@ -2761,6 +2761,7 @@ class WasmInterpreterInternals {
*len += 16;
return true;
}
case kExprI8x16RelaxedSwizzle:
case kExprI8x16Swizzle: {
int16 v2 = Pop().to_s128().to_i8x16();
int16 v1 = Pop().to_s128().to_i8x16();
......
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