Title: [290907] trunk/Source/_javascript_Core
Revision
290907
Author
[email protected]
Date
2022-03-07 13:55:08 -0800 (Mon, 07 Mar 2022)

Log Message

AssemblyHelpersSpoolers: use load/store pair on ARMv7
https://bugs.webkit.org/show_bug.cgi?id=235112

Reviewed by Žan Doberšek.

Save ~1% code size for baseline JIT on JS2 by emitting load/store pair
instructions on 32-bit ARM.

* assembler/ARMv7Assembler.h:
(JSC::ARMv6Assembler::vldmia):
(JSC::ARMv7Assembler::vstmia):
* assembler/CPU.h:
(JSC::isARM):
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::loadPair64):
(JSC::MacroAssemblerARMv7::storePair64):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::copyLLIntBaselineCalleeSavesFromFrameOrRegisterToEntryFrameCalleeSavesBuffer):
* jit/AssemblyHelpersSpoolers.h:
(JSC::AssemblyHelpers::LoadRegSpooler::executePair):
(JSC::AssemblyHelpers::StoreRegSpooler::executePair):
(JSC::AssemblyHelpers::CopySpooler::CopySpooler):
(JSC::AssemblyHelpers::CopySpooler::loadPair):
(JSC::AssemblyHelpers::CopySpooler::storePair):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (290906 => 290907)


--- trunk/Source/_javascript_Core/ChangeLog	2022-03-07 21:19:40 UTC (rev 290906)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-03-07 21:55:08 UTC (rev 290907)
@@ -1,3 +1,30 @@
+2022-03-07  Angelos Oikonomopoulos  <[email protected]>
+
+        AssemblyHelpersSpoolers: use load/store pair on ARMv7
+        https://bugs.webkit.org/show_bug.cgi?id=235112
+
+        Reviewed by Žan Doberšek.
+
+        Save ~1% code size for baseline JIT on JS2 by emitting load/store pair
+        instructions on 32-bit ARM.
+
+        * assembler/ARMv7Assembler.h:
+        (JSC::ARMv6Assembler::vldmia):
+        (JSC::ARMv7Assembler::vstmia):
+        * assembler/CPU.h:
+        (JSC::isARM):
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::loadPair64):
+        (JSC::MacroAssemblerARMv7::storePair64):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::copyLLIntBaselineCalleeSavesFromFrameOrRegisterToEntryFrameCalleeSavesBuffer):
+        * jit/AssemblyHelpersSpoolers.h:
+        (JSC::AssemblyHelpers::LoadRegSpooler::executePair):
+        (JSC::AssemblyHelpers::StoreRegSpooler::executePair):
+        (JSC::AssemblyHelpers::CopySpooler::CopySpooler):
+        (JSC::AssemblyHelpers::CopySpooler::loadPair):
+        (JSC::AssemblyHelpers::CopySpooler::storePair):
+
 2022-03-07  Zan Dobersek  <[email protected]>
 
         [JSC] Add missing CPU(RISCV64) guards in CTI thunk prologue, epilogue generators

Modified: trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h (290906 => 290907)


--- trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2022-03-07 21:19:40 UTC (rev 290906)
+++ trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2022-03-07 21:55:08 UTC (rev 290907)
@@ -583,6 +583,8 @@
         OP_CMP_reg_T2   = 0xEBB0,
         OP_VMOV_CtoD    = 0xEC00,
         OP_VMOV_DtoC    = 0xEC10,
+        OP_VSTMIA       = 0xEC80,
+        OP_VLDMIA       = 0xEC90,
         OP_FSTS         = 0xED00,
         OP_VSTR         = 0xED00,
         OP_FLDS         = 0xED10,
@@ -688,6 +690,8 @@
         OP_VSQRT_T1b     = 0x0A40,
         OP_VCVTSD_T1b    = 0x0A40,
         OP_VCVTDS_T1b    = 0x0A40,
+        OP_VSTMIAb       = 0x0B00,
+        OP_VLDMIAb       = 0x0B00,
         OP_NOP_T2b       = 0x8000,
         OP_DMB_SY_T1b    = 0x8F5F,
         OP_DMB_ISHST_T1b = 0x8F5A,
@@ -1926,6 +1930,18 @@
     }
 #endif
 
+    void vldmia(RegisterID rn, FPDoubleRegisterID rs, uint32_t count)
+    {
+        ASSERT(count < 16);
+        m_formatter.vfpMemOp(OP_VLDMIA, OP_VLDMIAb, true, rn, rs, count << 3);
+    }
+
+    void vstmia(RegisterID rn, FPDoubleRegisterID rs, uint32_t count)
+    {
+        ASSERT(count < 16);
+        m_formatter.vfpMemOp(OP_VSTMIA, OP_VSTMIAb, true, rn, rs, count << 3);
+    }
+
     void vand(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm)
     {
         m_formatter.vfpOp(OP_VAND_T1, OP_VAND_T1b, true, rn, rd, rm);

Modified: trunk/Source/_javascript_Core/assembler/CPU.h (290906 => 290907)


--- trunk/Source/_javascript_Core/assembler/CPU.h	2022-03-07 21:19:40 UTC (rev 290906)
+++ trunk/Source/_javascript_Core/assembler/CPU.h	2022-03-07 21:55:08 UTC (rev 290907)
@@ -42,6 +42,15 @@
 #endif
 }
 
+constexpr bool isARM()
+{
+#if CPU(ARM)
+    return true;
+#else
+    return false;
+#endif
+}
+
 constexpr bool isARM64()
 {
 #if CPU(ARM64)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (290906 => 290907)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2022-03-07 21:19:40 UTC (rev 290906)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2022-03-07 21:55:08 UTC (rev 290907)
@@ -934,6 +934,33 @@
         loadPair32(Address(scratch, address.offset), dest1, dest2);
     }
 
+    void loadPair64(RegisterID src, TrustedImm32 offset, FPRegisterID dest1, FPRegisterID dest2)
+    {
+        ASSERT(dest1 != dest2);
+        if ((dest2 == (dest1 + 1)) && !offset.m_value) {
+            // Only emit a VLDMIA if the registers happen to be consecutive and
+            // in the proper order and the offset happens to be zero. Otherwise,
+            // the extra instructions to adjust things mean there are no space
+            // savings and the VLDM itself might be a performance loss.
+            m_assembler.vldmia(src, dest1, 2);
+        } else {
+            loadDouble(Address(src, offset.m_value), dest1);
+            loadDouble(Address(src, offset.m_value + 8), dest2);
+        }
+    }
+
+    void storePair64(FPRegisterID src1, FPRegisterID src2, RegisterID dest, TrustedImm32 offset)
+    {
+        if ((src2 == (src1 + 1)) && !offset.m_value) {
+            // Only emit a VSTMIA under a narrow set of conditions. See
+            // loadPair64 for the rationale.
+            m_assembler.vstmia(dest, src1, 2);
+        } else {
+            storeDouble(src1, Address(dest, offset.m_value));
+            storeDouble(src2, Address(dest, offset.m_value + 8));
+        }
+    }
+
     void store32(RegisterID src, Address address)
     {
         store32(src, setupArmAddress(address));

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (290906 => 290907)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2022-03-07 21:19:40 UTC (rev 290906)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2022-03-07 21:55:08 UTC (rev 290907)
@@ -1289,8 +1289,8 @@
     GPRReg destBufferGPR = usedRegisters.getFreeGPR(0);
     GPRReg temp1 = usedRegisters.getFreeGPR(1);
     FPRReg fpTemp1 = usedRegisters.getFreeFPR(0);
-    GPRReg temp2 = isARM64() ? usedRegisters.getFreeGPR(2) : InvalidGPRReg;
-    FPRReg fpTemp2 = isARM64() ? usedRegisters.getFreeFPR(1) : InvalidFPRReg;
+    GPRReg temp2 = usedRegisters.getFreeGPR(2);
+    FPRReg fpTemp2 = usedRegisters.getFreeFPR(1);
 
     loadPtr(&topEntryFrame, destBufferGPR);
     addPtr(TrustedImm32(EntryFrame::calleeSaveRegistersBufferOffset()), destBufferGPR);

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpersSpoolers.h (290906 => 290907)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpersSpoolers.h	2022-03-07 21:19:40 UTC (rev 290906)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpersSpoolers.h	2022-03-07 21:55:08 UTC (rev 290907)
@@ -136,11 +136,7 @@
     }
 
 private:
-#if CPU(ARM64)
-    static constexpr bool hasPairOp = true;
-#else
-    static constexpr bool hasPairOp = false;
-#endif
+    static constexpr bool hasPairOp = isARM() || isARM64();
 
     Op& op() { return *reinterpret_cast<Op*>(this); }
 
@@ -164,12 +160,19 @@
     ALWAYS_INLINE void finalizeFPR() { finalize<FPRReg>(); }
 
 private:
-#if CPU(ARM64)
-    template<typename RegType>
-    ALWAYS_INLINE void executePair(ptrdiff_t offset, RegType reg1, RegType reg2)
+#if CPU(ARM64) || CPU(ARM)
+    ALWAYS_INLINE void executePair(ptrdiff_t offset, GPRReg reg1, GPRReg reg2)
     {
+#if USE(JSVALUE64)
         m_jit.loadPair64(m_baseGPR, TrustedImm32(offset), reg1, reg2);
+#else
+        m_jit.loadPair32(m_baseGPR, TrustedImm32(offset), reg1, reg2);
+#endif
     }
+    ALWAYS_INLINE void executePair(ptrdiff_t offset, FPRReg reg1, FPRReg reg2)
+    {
+        m_jit.loadPair64(m_baseGPR, TrustedImm32(offset), reg1, reg2);
+    }
 #else
     template<typename RegType>
     ALWAYS_INLINE void executePair(ptrdiff_t, RegType, RegType) { }
@@ -206,12 +209,19 @@
     ALWAYS_INLINE void finalizeFPR() { finalize<FPRReg>(); }
 
 private:
-#if CPU(ARM64)
-    template<typename RegType>
-    ALWAYS_INLINE void executePair(ptrdiff_t offset, RegType reg1, RegType reg2)
+#if CPU(ARM64) || CPU(ARM)
+    ALWAYS_INLINE void executePair(ptrdiff_t offset, GPRReg reg1, GPRReg reg2)
     {
+#if USE(JSVALUE64)
         m_jit.storePair64(reg1, reg2, m_baseGPR, TrustedImm32(offset));
+#else
+        m_jit.storePair32(reg1, reg2, m_baseGPR, TrustedImm32(offset));
+#endif
     }
+    ALWAYS_INLINE void executePair(ptrdiff_t offset, FPRReg reg1, FPRReg reg2)
+    {
+        m_jit.storePair64(reg1, reg2, m_baseGPR, TrustedImm32(offset));
+    }
 #else
     template<typename RegType>
     ALWAYS_INLINE void executePair(ptrdiff_t, RegType, RegType) { }
@@ -263,8 +273,8 @@
         , m_temp1FPR(fpTemp1)
         , m_temp2FPR(fpTemp2)
         , m_bufferRegsAttr(attribute)
-    {
-        if constexpr (hasPairOp && !isARM64())
+        {
+        if constexpr (hasPairOp && !(isARM() || isARM64()))
             RELEASE_ASSERT_NOT_REACHED(); // unsupported architecture.
     }
 
@@ -522,19 +532,35 @@
         m_jit.storeDouble(src, Address(m_dstBufferGPR, offset));
     }
 
-#if CPU(ARM64)
-    template<typename RegType>
-    ALWAYS_INLINE void loadPair(int offset, RegType dest1, RegType dest2)
+#if CPU(ARM64) || CPU(ARM)
+    ALWAYS_INLINE void loadPair(int offset, GPRReg dest1, GPRReg dest2)
     {
+#if USE(JSVALUE64)
         m_jit.loadPair64(m_srcBufferGPR, TrustedImm32(offset), dest1, dest2);
+#else
+        m_jit.loadPair32(m_srcBufferGPR, TrustedImm32(offset), dest1, dest2);
+#endif
     }
 
-    template<typename RegType>
-    ALWAYS_INLINE void storePair(RegType src1, RegType src2, int offset)
+    ALWAYS_INLINE void loadPair(int offset, FPRReg dest1, FPRReg dest2)
     {
+        m_jit.loadPair64(m_srcBufferGPR, TrustedImm32(offset), dest1, dest2);
+    }
+
+    ALWAYS_INLINE void storePair(GPRReg src1, GPRReg src2, int offset)
+    {
+#if USE(JSVALUE64)
         m_jit.storePair64(src1, src2, m_dstBufferGPR, TrustedImm32(offset));
+#else
+        m_jit.storePair32(src1, src2, m_dstBufferGPR, TrustedImm32(offset));
+#endif
     }
 
+    ALWAYS_INLINE void storePair(FPRReg src1, FPRReg src2, int offset)
+    {
+        m_jit.storePair64(src1, src2, m_dstBufferGPR, TrustedImm32(offset));
+    }
+
     static constexpr bool hasPairOp = true;
 #else
     template<typename RegType> ALWAYS_INLINE void loadPair(int, RegType, RegType) { }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to