Ignore:
Timestamp:
Mar 13, 2022, 7:34:17 AM (3 years ago)
Author:
Angelos Oikonomopoulos
Message:

[JSC] Use addressTempRegister in loadValue(void *) on 32 bits
https://bugs.webkit.org/show_bug.cgi?id=237773

Reviewed by Žan Doberšek.

Instead of using one of the destination registers as an address
temporary, use addressTempRegister instead. This allows reusing
the value in addressTempRegister (with an appropriate offset) if
possible, which results in a >25% size reduction for DFGOSRExit
(JS2) on ARMv7 (though not a significant size reduction overall).
Technically, this change could be killing some address reuse that
was previously possible because loadValue was not clobbering
addressTempRegister but, if so, this seems to be balanced out for
JS2.

  • assembler/MacroAssemblerARMv7.h:

(JSC::MacroAssemblerARMv7::BoundsNonDoubleWordOffset::within):
(JSC::MacroAssemblerARMv7::BoundsDoubleWordOffset::within):
(JSC::MacroAssemblerARMv7::loadPair32):
(JSC::MacroAssemblerARMv7::setupArmAddress):
(JSC::MacroAssemblerARMv7::absoluteAddressWithinShortOffset):

  • assembler/MacroAssemblerMIPS.h:

(JSC::MacroAssemblerMIPS::loadPair32):

  • jit/AssemblyHelpers.h:

(JSC::AssemblyHelpers::loadValue):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r290907 r291217  
    6161        friend void JSC::MacroAssemblerHelpers::load16OnCondition(MacroAssemblerType&, Condition, Args...);
    6262
     63    struct BoundsNonDoubleWordOffset {
     64        static bool within(intptr_t value)
     65        {
     66            return (value >= -0xff) && (value <= 0xfff);
     67        }
     68    };
     69    struct BoundsDoubleWordOffset {
     70        static bool within(intptr_t value)
     71        {
     72            if (value < 0)
     73                value = -value;
     74            return !(value & ~0x3fc);
     75        }
     76    };
    6377#define DUMMY_REGISTER_VALUE(id, name, r, cs) 0,
    6478    static constexpr unsigned numGPRs = std::initializer_list<int>({ FOR_EACH_GP_REGISTER(DUMMY_REGISTER_VALUE) }).size();
     
    898912    }
    899913
     914    void loadPair32(ArmAddress address, RegisterID dest1, RegisterID dest2)
     915    {
     916        if (address.type == ArmAddress::HasIndex) {
     917            // Using r0-r7 can often be encoded with a shorter (16-bit vs 32-bit) instruction, so use
     918            // whichever destination register is in that range (if any) as the address temp register
     919            RegisterID scratch = dest1;
     920            if (dest1 >= ARMRegisters::r8)
     921                scratch = dest2;
     922            if (address.u.scale == TimesOne)
     923                m_assembler.add(scratch, address.base, address.u.index);
     924            else {
     925                ShiftTypeAndAmount shift { ARMShiftType::SRType_LSL, static_cast<unsigned>(address.u.scale) };
     926                m_assembler.add(scratch, address.base, address.u.index, shift);
     927            }
     928            loadPair32(Address(scratch), dest1, dest2);
     929        } else {
     930            ASSERT(dest1 != dest2); // If it is the same, ldp becomes illegal instruction.
     931            int32_t absOffset = address.u.offset;
     932            if (absOffset < 0)
     933                absOffset = -absOffset;
     934            if (!(absOffset & ~0x3fc)) {
     935                if ((dest1 == addressTempRegister) || (dest2 == addressTempRegister))
     936                    cachedAddressTempRegister().invalidate();
     937                if ((dest1 == dataTempRegister) || (dest2 == dataTempRegister))
     938                    cachedDataTempRegister().invalidate();
     939                m_assembler.ldrd(dest1, dest2, address.base, address.u.offset, /* index: */ true, /* wback: */ false);
     940            } else if (address.base == dest1) {
     941                ArmAddress highAddress(address.base, address.u.offset + 4);
     942                load32(highAddress, dest2);
     943                load32(address, dest1);
     944            } else {
     945                load32(address, dest1);
     946                ArmAddress highAddress(address.base, address.u.offset + 4);
     947                load32(highAddress, dest2);
     948            }
     949        }
     950    }
     951
    900952    void loadPair32(Address address, RegisterID dest1, RegisterID dest2)
    901953    {
    902         ASSERT(dest1 != dest2); // If it is the same, ldp becomes illegal instruction.
    903         int32_t absOffset = address.offset;
    904         if (absOffset < 0)
    905             absOffset = -absOffset;
    906         if (!(absOffset & ~0x3fc)) {
    907             if ((dest1 == addressTempRegister) || (dest2 == addressTempRegister))
    908                 cachedAddressTempRegister().invalidate();
    909             if ((dest1 == dataTempRegister) || (dest2 == dataTempRegister))
    910                 cachedDataTempRegister().invalidate();
    911             m_assembler.ldrd(dest1, dest2, address.base, address.offset, /* index: */ true, /* wback: */ false);
    912         } else if (address.base == dest1) {
    913             load32(address.withOffset(4), dest2);
    914             load32(address, dest1);
    915         } else {
    916             load32(address, dest1);
    917             load32(address.withOffset(4), dest2);
    918         }
     954        loadPair32(setupArmAddress(address), dest1, dest2);
    919955    }
    920956
     
    960996            storeDouble(src2, Address(dest, offset.m_value + 8));
    961997        }
     998    }
     999
     1000    void loadPair32(AbsoluteAddress address, RegisterID dest1, RegisterID dest2)
     1001    {
     1002        loadPair32(setupArmAddress<BoundsDoubleWordOffset>(address), dest1, dest2);
    9621003    }
    9631004
     
    25002541    ArmAddress setupArmAddress(Address address)
    25012542    {
    2502         if ((address.offset >= -0xff) && (address.offset <= 0xfff))
     2543        if (BoundsNonDoubleWordOffset::within(address.offset))
    25032544            return ArmAddress(address.base, address.offset);
    25042545
     
    25072548    }
    25082549
     2550    template <class Bounds>
    25092551    std::optional<int32_t> absoluteAddressWithinShortOffset(AbsoluteAddress address, CachedTempRegister &cachedRegister)
    25102552    {
     
    25132555        if (cachedRegister.value(currentRegisterContents)) {
    25142556            intptr_t addressDelta = addressAsInt - currentRegisterContents;
    2515             if ((addressDelta >= -0xff) && (addressDelta <= 0xfff))
     2557            if (Bounds::within(addressDelta))
    25162558                return reinterpret_cast<int32_t>(addressDelta);
    25172559        }
     
    25192561    }
    25202562
     2563    template<class Bounds = BoundsNonDoubleWordOffset>
    25212564    ArmAddress setupArmAddress(AbsoluteAddress address, RegisterID scratch = addressTempRegister)
    25222565    {
    2523         if (auto offset = absoluteAddressWithinShortOffset(address, cachedAddressTempRegister()))
     2566        if (auto offset = absoluteAddressWithinShortOffset<Bounds>(address, cachedAddressTempRegister()))
    25242567            return ArmAddress(addressTempRegister, *offset);
    2525         if (auto offset = absoluteAddressWithinShortOffset(address, cachedDataTempRegister()))
     2568        if (auto offset = absoluteAddressWithinShortOffset<Bounds>(address, cachedDataTempRegister()))
    25262569            return ArmAddress(dataTempRegister, *offset);
    25272570        move(TrustedImmPtr(address.m_ptr), scratch);
Note: See TracChangeset for help on using the changeset viewer.