Skip to content
Permalink
Browse files
[WebAssembly SIMD] Support bitwise operations on Intel
https://bugs.webkit.org/show_bug.cgi?id=248639
rdar://103089683

Reviewed by Yusuke Suzuki.

Adds support for SIMD bitwise operations (AND, OR, XOR, ANDN, NOT, shifts, any/all_true,
bitmask/select) to the Intel macro assembler. Currently omits shifts and popcnt for i8x16
vectors, since they aren't supported natively on Intel and are pretty involved to emulate.

* Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::compareIntegerVectorWithZero):
(JSC::MacroAssemblerX86_64::vectorAnd):
(JSC::MacroAssemblerX86_64::vectorAndnot):
(JSC::MacroAssemblerX86_64::vectorOr):
(JSC::MacroAssemblerX86_64::vectorXor):
(JSC::MacroAssemblerX86_64::vectorUshl):
(JSC::MacroAssemblerX86_64::vectorUshr):
(JSC::MacroAssemblerX86_64::vectorSshr):
(JSC::MacroAssemblerX86_64::vectorAnyTrue):
(JSC::MacroAssemblerX86_64::vectorAllTrue):
(JSC::MacroAssemblerX86_64::vectorNot): Deleted.
* Source/JavaScriptCore/assembler/X86Assembler.h:
(JSC::X86Assembler::vandps_rrr):
(JSC::X86Assembler::vandpd_rrr):
(JSC::X86Assembler::vorps_rrr):
(JSC::X86Assembler::vorpd_rrr):
(JSC::X86Assembler::vxorps_rrr):
(JSC::X86Assembler::vxorpd_rrr):
(JSC::X86Assembler::vandnps_rrr):
(JSC::X86Assembler::vandnpd_rrr):
(JSC::X86Assembler::vpmovmskb_rr):
(JSC::X86Assembler::vmovmskps_rr):
(JSC::X86Assembler::vmovmskpd_rr):
(JSC::X86Assembler::vptest_rr):
(JSC::X86Assembler::vpsllw_rrr):
(JSC::X86Assembler::vpslld_rrr):
(JSC::X86Assembler::vpsllq_rrr):
(JSC::X86Assembler::vpsrlw_rrr):
(JSC::X86Assembler::vpsrld_rrr):
(JSC::X86Assembler::vpsrlq_rrr):
(JSC::X86Assembler::vpsraw_rrr):
(JSC::X86Assembler::vpsrad_rrr):
(JSC::X86Assembler::vpsraq_rrr):
(JSC::X86Assembler::andps_rr):
(JSC::X86Assembler::orps_rr):
* Source/JavaScriptCore/b3/air/AirLowerMacros.cpp:
(JSC::B3::Air::lowerMacros):
* Source/JavaScriptCore/b3/air/AirOpcode.opcodes:
* Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp:
(JSC::Wasm::AirIRGenerator::addSIMDI_V):
(JSC::Wasm::AirIRGenerator::addSIMDV_V):
(JSC::Wasm::AirIRGenerator::addConstant):
(JSC::Wasm::AirIRGenerator::addSIMDShift):

Canonical link: https://commits.webkit.org/257640@main
  • Loading branch information
David Degazio committed Dec 9, 2022
1 parent 13d943d commit 4dea5d54cd4a77e83dbf3fb6de01cc7c81d23d22
Show file tree
Hide file tree
Showing 6 changed files with 367 additions and 69 deletions.
@@ -5137,7 +5137,7 @@ class MacroAssemblerARM64 : public AbstractMacroAssembler<Assembler> {
m_assembler.sshl(dest, input, shift, simdInfo.lane);
}

void vectorSshr(SIMDInfo simdInfo, FPRegisterID input, TrustedImm32 shift, FPRegisterID dest)
void vectorSshr8(SIMDInfo simdInfo, FPRegisterID input, TrustedImm32 shift, FPRegisterID dest)
{
ASSERT(scalarTypeIsIntegral(simdInfo.lane));
m_assembler.sshr_vi(dest, input, shift.m_value, simdInfo.lane);
@@ -2473,10 +2473,15 @@ class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
}
}

void compareIntegerVectorWithZero(RelationalCondition cond, SIMDInfo simdInfo, FPRegisterID vector, FPRegisterID dest)
void compareIntegerVectorWithZero(RelationalCondition cond, SIMDInfo simdInfo, FPRegisterID vector, FPRegisterID dest, RegisterID scratch)
{
RELEASE_ASSERT(scalarTypeIsIntegral(simdInfo.lane));
UNUSED_PARAM(cond); UNUSED_PARAM(vector); UNUSED_PARAM(dest);
RELEASE_ASSERT(supportsAVXForSIMD());
RELEASE_ASSERT(cond == RelationalCondition::Equal || cond == RelationalCondition::NotEqual);

m_assembler.vptest_rr(vector, vector);
m_assembler.setCC_r(x86Condition(cond), scratch);
vectorSplat8(scratch, dest);
}

void vectorAdd(SIMDInfo simdInfo, FPRegisterID left, FPRegisterID right, FPRegisterID dest)
@@ -2725,34 +2730,32 @@ class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
UNUSED_PARAM(left); UNUSED_PARAM(right); UNUSED_PARAM(inputBitsAndDest);
}

void vectorNot(SIMDInfo simdInfo, FPRegisterID input, FPRegisterID dest)
{
ASSERT_UNUSED(simdInfo, simdInfo.lane == SIMDLane::v128);
UNUSED_PARAM(input); UNUSED_PARAM(dest);
}

void vectorAnd(SIMDInfo simdInfo, FPRegisterID left, FPRegisterID right, FPRegisterID dest)
{
ASSERT_UNUSED(simdInfo, simdInfo.lane == SIMDLane::v128);
UNUSED_PARAM(left); UNUSED_PARAM(right); UNUSED_PARAM(dest);
RELEASE_ASSERT(supportsAVXForSIMD());
RELEASE_ASSERT(simdInfo.lane == SIMDLane::v128);
m_assembler.vandps_rrr(left, right, dest);
}

void vectorAndnot(SIMDInfo simdInfo, FPRegisterID left, FPRegisterID right, FPRegisterID dest)
{
ASSERT_UNUSED(simdInfo, simdInfo.lane == SIMDLane::v128);
UNUSED_PARAM(left); UNUSED_PARAM(right); UNUSED_PARAM(dest);
RELEASE_ASSERT(supportsAVXForSIMD());
RELEASE_ASSERT(simdInfo.lane == SIMDLane::v128);
m_assembler.vandnps_rrr(left, right, dest);
}

void vectorOr(SIMDInfo simdInfo, FPRegisterID left, FPRegisterID right, FPRegisterID dest)
{
ASSERT_UNUSED(simdInfo, simdInfo.lane == SIMDLane::v128);
UNUSED_PARAM(left); UNUSED_PARAM(right); UNUSED_PARAM(dest);
RELEASE_ASSERT(supportsAVXForSIMD());
RELEASE_ASSERT(simdInfo.lane == SIMDLane::v128);
m_assembler.vorps_rrr(left, right, dest);
}

void vectorXor(SIMDInfo simdInfo, FPRegisterID left, FPRegisterID right, FPRegisterID dest)
{
ASSERT_UNUSED(simdInfo, simdInfo.lane == SIMDLane::v128);
UNUSED_PARAM(left); UNUSED_PARAM(right); UNUSED_PARAM(dest);
RELEASE_ASSERT(supportsAVXForSIMD());
RELEASE_ASSERT(simdInfo.lane == SIMDLane::v128);
m_assembler.vxorps_rrr(left, right, dest);
}

void moveZeroToVector(FPRegisterID dest)
@@ -3072,6 +3075,72 @@ class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
}
}

void vectorUshl(SIMDInfo simdInfo, FPRegisterID input, FPRegisterID shift, FPRegisterID dest)
{
ASSERT(scalarTypeIsIntegral(simdInfo.lane));
RELEASE_ASSERT(supportsAVXForSIMD());
switch (simdInfo.lane) {
case SIMDLane::i8x16:
// FIXME: 8-bit shift is awful on intel.
break;
case SIMDLane::i16x8:
m_assembler.vpsllw_rrr(shift, input, dest);
break;
case SIMDLane::i32x4:
m_assembler.vpslld_rrr(shift, input, dest);
break;
case SIMDLane::i64x2:
m_assembler.vpsllq_rrr(shift, input, dest);
break;
default:
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid lane kind for unsigned vector left shift.");
}
}

void vectorUshr(SIMDInfo simdInfo, FPRegisterID input, FPRegisterID shift, FPRegisterID dest)
{
ASSERT(scalarTypeIsIntegral(simdInfo.lane));
RELEASE_ASSERT(supportsAVXForSIMD());
switch (simdInfo.lane) {
case SIMDLane::i8x16:
// FIXME: 8-bit shift is awful on intel.
break;
case SIMDLane::i16x8:
m_assembler.vpsrlw_rrr(shift, input, dest);
break;
case SIMDLane::i32x4:
m_assembler.vpsrld_rrr(shift, input, dest);
break;
case SIMDLane::i64x2:
m_assembler.vpsrlq_rrr(shift, input, dest);
break;
default:
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid lane kind for unsigned vector right shift.");
}
}

void vectorSshr(SIMDInfo simdInfo, FPRegisterID input, FPRegisterID shift, FPRegisterID dest)
{
ASSERT(scalarTypeIsIntegral(simdInfo.lane));
RELEASE_ASSERT(supportsAVXForSIMD());
switch (simdInfo.lane) {
case SIMDLane::i8x16:
// FIXME: 8-bit shift is awful on intel.
break;
case SIMDLane::i16x8:
m_assembler.vpsraw_rrr(shift, input, dest);
break;
case SIMDLane::i32x4:
m_assembler.vpsrad_rrr(shift, input, dest);
break;
case SIMDLane::i64x2:
m_assembler.vpsraq_rrr(shift, input, dest);
break;
default:
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid lane kind for unsigned vector right shift.");
}
}

void vectorSplat(SIMDLane lane, RegisterID src, FPRegisterID dest)
{
m_assembler.movq_rr(src, dest);
@@ -3221,9 +3290,64 @@ class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
void vectorLoad32Lane(Address address, TrustedImm32 imm, FPRegisterID dest) { UNUSED_PARAM(address); UNUSED_PARAM(imm); UNUSED_PARAM(dest); }
void vectorLoad64Lane(Address address, TrustedImm32 imm, FPRegisterID dest) { UNUSED_PARAM(address); UNUSED_PARAM(imm); UNUSED_PARAM(dest); }

void vectorAnyTrue(FPRegisterID vec, RegisterID dest) { UNUSED_PARAM(vec); UNUSED_PARAM(dest); }
void vectorAllTrue(SIMDInfo simdInfo, FPRegisterID vec, RegisterID dest) { UNUSED_PARAM(simdInfo); UNUSED_PARAM(vec); UNUSED_PARAM(dest); }
void vectorBitmask(SIMDInfo simdInfo, FPRegisterID vec, RegisterID dest) { UNUSED_PARAM(simdInfo); UNUSED_PARAM(vec); UNUSED_PARAM(dest); }
void vectorAnyTrue(FPRegisterID vec, RegisterID dest)
{
RELEASE_ASSERT(supportsAVXForSIMD());
m_assembler.vptest_rr(vec, vec);
m_assembler.setCC_r(x86Condition(NonZero), dest);
m_assembler.movzbl_rr(dest, dest);
}

void vectorAllTrue(SIMDInfo simdInfo, FPRegisterID vec, RegisterID dest, FPRegisterID scratch)
{
RELEASE_ASSERT(supportsAVXForSIMD());

m_assembler.vpxor_rrr(scratch, scratch, scratch); // Zero scratch register.
switch (simdInfo.lane) {
case SIMDLane::i8x16:
m_assembler.vpcmpeqb_rrr(vec, scratch, scratch);
break;
case SIMDLane::i16x8:
m_assembler.vpcmpeqw_rrr(vec, scratch, scratch);
break;
case SIMDLane::i32x4:
m_assembler.vpcmpeqd_rrr(vec, scratch, scratch);
break;
case SIMDLane::i64x2:
m_assembler.vpcmpeqq_rrr(vec, scratch, scratch);
break;
default:
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid SIMD lane for vector all-true.");
}
m_assembler.vptest_rr(scratch, scratch);
m_assembler.setCC_r(x86Condition(RelationalCondition::Equal), dest);
m_assembler.movzbl_rr(dest, dest);
}

void vectorBitmask(SIMDInfo simdInfo, FPRegisterID vec, RegisterID dest, FPRegisterID tmp)
{
RELEASE_ASSERT(supportsAVXForSIMD());

switch (simdInfo.lane) {
case SIMDLane::i8x16:
m_assembler.vpmovmskb_rr(vec, dest);
break;
case SIMDLane::i16x8:
m_assembler.vpxor_rrr(tmp, tmp, tmp);
m_assembler.vpacksswb_rrr(vec, tmp, tmp);
m_assembler.vpmovmskb_rr(vec, dest);
break;
case SIMDLane::i32x4:
m_assembler.vmovmskps_rr(vec, dest);
break;
case SIMDLane::i64x2:
m_assembler.vmovmskpd_rr(vec, dest);
break;
default:
RELEASE_ASSERT_NOT_REACHED_WITH_MESSAGE("Invalid SIMD lane for vector bitmask.");
}
}

void vectorExtaddPairwise(SIMDInfo simdInfo, FPRegisterID vec, FPRegisterID dest) { UNUSED_PARAM(simdInfo); UNUSED_PARAM(vec); UNUSED_PARAM(dest); }

void vectorAvgRound(SIMDInfo simdInfo, FPRegisterID a, FPRegisterID b, FPRegisterID dest)

0 comments on commit 4dea5d5

Please sign in to comment.