Skip to content

Commit aa596dd

Browse files
committed
[JSC] Add constant materialization JIT code for x64
https://bugs.webkit.org/show_bug.cgi?id=305532 rdar://168193277 Reviewed by Sosuke Suzuki. This patch adds more wide variety of constants for move128ToVector / move64ToDouble / move32ToFloat in x64. This is a preparation for SIMD optimization in x64 in YarrJIT where it needs these constant materializations for masks. Test: Source/JavaScriptCore/assembler/testmasm.cpp * Source/JavaScriptCore/assembler/AssemblerCommon.h: (JSC::X86ContiguousBitPattern32::create): (JSC::X86ContiguousBitPattern32::isValid const): (JSC::X86ContiguousBitPattern32::leftShift const): (JSC::X86ContiguousBitPattern32::rightShift const): (JSC::X86ContiguousBitPattern32::X86ContiguousBitPattern32): (JSC::X86ContiguousBitPattern64::create): (JSC::X86ContiguousBitPattern64::isValid const): (JSC::X86ContiguousBitPattern64::leftShift const): (JSC::X86ContiguousBitPattern64::rightShift const): (JSC::X86ContiguousBitPattern64::X86ContiguousBitPattern64): * Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h: (JSC::MacroAssemblerX86_64::moveAllOnesToVector): (JSC::MacroAssemblerX86_64::move32ToFloat): (JSC::MacroAssemblerX86_64::move64ToDouble): (JSC::MacroAssemblerX86_64::move128ToVector): * Source/JavaScriptCore/assembler/X86Assembler.h: (JSC::X86Assembler::punpcklbw_rr): (JSC::X86Assembler::punpcklwd_rr): (JSC::X86Assembler::pcmpeqd_rr): (JSC::X86Assembler::pcmpeqq_rr): (JSC::X86Assembler::movlhps_rr): (JSC::X86Assembler::vbroadcastss_rr): (JSC::X86Assembler::vpbroadcastb_rr): (JSC::X86Assembler::vpbroadcastw_rr): (JSC::X86Assembler::vpbroadcastd_rr): (JSC::X86Assembler::vpbroadcastq_rr): * Source/JavaScriptCore/assembler/testmasm.cpp: (JSC::testMove128ToVectorMovi): (JSC::testMove32ToFloatComprehensive): (JSC::testMove64ToDoubleComprehensive): (JSC::testMove128ToVectorComprehensive): (JSC::testFMovHalfPrecisionEncoding): (JSC::testMove32ToFloatX64): (JSC::testMove64ToDoubleX64): * Source/JavaScriptCore/b3/air/AirArg.h: (JSC::B3::Air::Arg::isValidFPImm32Form): (JSC::B3::Air::Arg::isValidFPImm64Form): (JSC::B3::Air::Arg::isValidFPImm128Form): * Source/JavaScriptCore/b3/air/AirOpcode.opcodes: * Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp: (JSC::Wasm::BBQJITImpl::BBQJIT::materializeVectorConstant): Canonical link: https://commits.webkit.org/306399@main
1 parent 9389120 commit aa596dd

7 files changed

Lines changed: 1137 additions & 108 deletions

File tree

‎Source/JavaScriptCore/assembler/AssemblerCommon.h‎

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,116 @@ class ARM64ShiftedImmediate16 {
550550
uint8_t m_shift { 0 };
551551
};
552552

553+
// X86ContiguousBitPattern32 detects 32-bit values with contiguous set bits that can be
554+
// synthesized using pcmpeqd (all-ones) + shifts on x86/x64.
555+
//
556+
// Pattern: a sequence of contiguous '1' bits surrounded by '0' bits
557+
//
558+
// Examples of encodable patterns:
559+
// 0x80000000 → pcmpeqd + pslld #31 (shift left to isolate sign bit)
560+
// 0xFF000000 → pcmpeqd + pslld #24 (shift left to isolate top byte)
561+
// 0x00FFFFFF → pcmpeqd + psrld #8 (shift right to clear top byte)
562+
// 0x7FFFFFFF → pcmpeqd + pslld #31 + psrld #1 (all ones except sign bit)
563+
//
564+
// Non-encodable patterns:
565+
// 0x80000001 → non-contiguous bits
566+
// 0xFF00FF00 → multiple separate ranges
567+
//
568+
// Usage: pcmpeqd xmm, xmm → pslld xmm, #leftShift → psrld xmm, #rightShift
569+
class X86ContiguousBitPattern32 {
570+
public:
571+
static X86ContiguousBitPattern32 create(uint32_t value)
572+
{
573+
if (!value || value == 0xFFFFFFFFU)
574+
return { }; // Zero and all-ones handled separately
575+
576+
// Use bit manipulation to detect contiguous pattern
577+
// Technique: clz + ctz + popcount == 32 for contiguous bits
578+
unsigned leadingZeros = WTF::clz(value);
579+
unsigned trailingZeros = WTF::ctz(value);
580+
unsigned setBits = std::popcount(value);
581+
582+
if (leadingZeros + trailingZeros + setBits != 32)
583+
return { }; // Not a contiguous pattern
584+
585+
// Calculate shifts needed: shift left to position bits at top, then shift right
586+
uint8_t leftShift = static_cast<uint8_t>(32 - setBits);
587+
uint8_t rightShift = static_cast<uint8_t>(leadingZeros);
588+
589+
return X86ContiguousBitPattern32(leftShift, rightShift);
590+
}
591+
592+
bool isValid() const { return m_leftShift.has_value(); }
593+
uint8_t leftShift() const
594+
{
595+
ASSERT(isValid());
596+
return m_leftShift.value();
597+
}
598+
uint8_t rightShift() const
599+
{
600+
ASSERT(isValid());
601+
return m_rightShift;
602+
}
603+
604+
private:
605+
X86ContiguousBitPattern32() = default;
606+
607+
X86ContiguousBitPattern32(uint8_t leftShift, uint8_t rightShift)
608+
: m_leftShift(leftShift)
609+
, m_rightShift(rightShift)
610+
{
611+
}
612+
613+
std::optional<uint8_t> m_leftShift;
614+
uint8_t m_rightShift { 0 };
615+
};
616+
617+
// X86ContiguousBitPattern64 - 64-bit version of contiguous bit pattern detection
618+
class X86ContiguousBitPattern64 {
619+
public:
620+
static X86ContiguousBitPattern64 create(uint64_t value)
621+
{
622+
if (!value || value == 0xFFFFFFFFFFFFFFFFULL)
623+
return { };
624+
625+
unsigned leadingZeros = WTF::clz(value);
626+
unsigned trailingZeros = WTF::ctz(value);
627+
unsigned setBits = std::popcount(value);
628+
629+
if (leadingZeros + trailingZeros + setBits != 64)
630+
return { };
631+
632+
uint8_t leftShift = static_cast<uint8_t>(64 - setBits);
633+
uint8_t rightShift = static_cast<uint8_t>(leadingZeros);
634+
635+
return X86ContiguousBitPattern64(leftShift, rightShift);
636+
}
637+
638+
bool isValid() const { return m_leftShift.has_value(); }
639+
uint8_t leftShift() const
640+
{
641+
ASSERT(isValid());
642+
return m_leftShift.value();
643+
}
644+
uint8_t rightShift() const
645+
{
646+
ASSERT(isValid());
647+
return m_rightShift;
648+
}
649+
650+
private:
651+
X86ContiguousBitPattern64() = default;
652+
653+
X86ContiguousBitPattern64(uint8_t leftShift, uint8_t rightShift)
654+
: m_leftShift(leftShift)
655+
, m_rightShift(rightShift)
656+
{
657+
}
658+
659+
std::optional<uint8_t> m_leftShift;
660+
uint8_t m_rightShift { 0 };
661+
};
662+
553663
ALWAYS_INLINE bool isValidARMThumb2Immediate(int64_t value)
554664
{
555665
if (value < 0)

0 commit comments

Comments
 (0)