Changeset 194062 in webkit


Ignore:
Timestamp:
Dec 14, 2015 2:44:22 PM (8 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC] Add ceil() support for x86 and expose it to B3
https://bugs.webkit.org/show_bug.cgi?id=152231

Patch by Benjamin Poulain <bpoulain@apple.com> on 2015-12-14
Reviewed by Geoffrey Garen.

Most x86 CPUs we care about support ceil() natively
with the round instruction.

This patch expose that behind a runtime flag, use it
in the Math.ceil() thunk and expose it to B3.

  • assembler/MacroAssemblerARM64.h:

(JSC::MacroAssemblerARM64::supportsFloatingPointCeil):

  • assembler/MacroAssemblerARMv7.h:

(JSC::MacroAssemblerARMv7::supportsFloatingPointCeil):

  • assembler/MacroAssemblerMIPS.h:

(JSC::MacroAssemblerMIPS::supportsFloatingPointCeil):

  • assembler/MacroAssemblerSH4.h:

(JSC::MacroAssemblerSH4::supportsFloatingPointCeil):

  • assembler/MacroAssemblerX86Common.cpp:
  • assembler/MacroAssemblerX86Common.h:

(JSC::MacroAssemblerX86Common::ceilDouble):
(JSC::MacroAssemblerX86Common::ceilFloat):
(JSC::MacroAssemblerX86Common::supportsFloatingPointCeil):
(JSC::MacroAssemblerX86Common::supportsLZCNT):

  • assembler/X86Assembler.h:

(JSC::X86Assembler::roundss_rr):
(JSC::X86Assembler::roundss_mr):
(JSC::X86Assembler::roundsd_rr):
(JSC::X86Assembler::roundsd_mr):
(JSC::X86Assembler::mfence):
(JSC::X86Assembler::X86InstructionFormatter::threeByteOp):

  • b3/B3ConstDoubleValue.cpp:

(JSC::B3::ConstDoubleValue::ceilConstant):

  • b3/B3ConstDoubleValue.h:
  • b3/B3ConstFloatValue.cpp:

(JSC::B3::ConstFloatValue::ceilConstant):

  • b3/B3ConstFloatValue.h:
  • b3/B3LowerMacrosAfterOptimizations.cpp:
  • b3/B3LowerToAir.cpp:

(JSC::B3::Air::LowerToAir::lower):

  • b3/B3Opcode.cpp:

(WTF::printInternal):

  • b3/B3Opcode.h:
  • b3/B3ReduceDoubleToFloat.cpp:
  • b3/B3ReduceStrength.cpp:
  • b3/B3Validate.cpp:
  • b3/B3Value.cpp:

(JSC::B3::Value::ceilConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):

  • b3/B3Value.h:
  • b3/air/AirOpcode.opcodes:
  • b3/testb3.cpp:

(JSC::B3::testCeilArg):
(JSC::B3::testCeilImm):
(JSC::B3::testCeilMem):
(JSC::B3::testCeilCeilArg):
(JSC::B3::testCeilIToD64):
(JSC::B3::testCeilIToD32):
(JSC::B3::testCeilArgWithUselessDoubleConversion):
(JSC::B3::testCeilArgWithEffectfulDoubleConversion):
(JSC::B3::populateWithInterestingValues):
(JSC::B3::run):

  • ftl/FTLB3Output.h:

(JSC::FTL::Output::ceil64):

  • jit/ThunkGenerators.cpp:

(JSC::ceilThunkGenerator):

Location:
trunk/Source/JavaScriptCore
Files:
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r194057 r194062  
     12015-12-14  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        [JSC] Add ceil() support for x86 and expose it to B3
     4        https://bugs.webkit.org/show_bug.cgi?id=152231
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        Most x86 CPUs we care about support ceil() natively
     9        with the round instruction.
     10
     11        This patch expose that behind a runtime flag, use it
     12        in the Math.ceil() thunk and expose it to B3.
     13
     14        * assembler/MacroAssemblerARM64.h:
     15        (JSC::MacroAssemblerARM64::supportsFloatingPointCeil):
     16        * assembler/MacroAssemblerARMv7.h:
     17        (JSC::MacroAssemblerARMv7::supportsFloatingPointCeil):
     18        * assembler/MacroAssemblerMIPS.h:
     19        (JSC::MacroAssemblerMIPS::supportsFloatingPointCeil):
     20        * assembler/MacroAssemblerSH4.h:
     21        (JSC::MacroAssemblerSH4::supportsFloatingPointCeil):
     22        * assembler/MacroAssemblerX86Common.cpp:
     23        * assembler/MacroAssemblerX86Common.h:
     24        (JSC::MacroAssemblerX86Common::ceilDouble):
     25        (JSC::MacroAssemblerX86Common::ceilFloat):
     26        (JSC::MacroAssemblerX86Common::supportsFloatingPointCeil):
     27        (JSC::MacroAssemblerX86Common::supportsLZCNT):
     28        * assembler/X86Assembler.h:
     29        (JSC::X86Assembler::roundss_rr):
     30        (JSC::X86Assembler::roundss_mr):
     31        (JSC::X86Assembler::roundsd_rr):
     32        (JSC::X86Assembler::roundsd_mr):
     33        (JSC::X86Assembler::mfence):
     34        (JSC::X86Assembler::X86InstructionFormatter::threeByteOp):
     35        * b3/B3ConstDoubleValue.cpp:
     36        (JSC::B3::ConstDoubleValue::ceilConstant):
     37        * b3/B3ConstDoubleValue.h:
     38        * b3/B3ConstFloatValue.cpp:
     39        (JSC::B3::ConstFloatValue::ceilConstant):
     40        * b3/B3ConstFloatValue.h:
     41        * b3/B3LowerMacrosAfterOptimizations.cpp:
     42        * b3/B3LowerToAir.cpp:
     43        (JSC::B3::Air::LowerToAir::lower):
     44        * b3/B3Opcode.cpp:
     45        (WTF::printInternal):
     46        * b3/B3Opcode.h:
     47        * b3/B3ReduceDoubleToFloat.cpp:
     48        * b3/B3ReduceStrength.cpp:
     49        * b3/B3Validate.cpp:
     50        * b3/B3Value.cpp:
     51        (JSC::B3::Value::ceilConstant):
     52        (JSC::B3::Value::effects):
     53        (JSC::B3::Value::key):
     54        (JSC::B3::Value::typeFor):
     55        * b3/B3Value.h:
     56        * b3/air/AirOpcode.opcodes:
     57        * b3/testb3.cpp:
     58        (JSC::B3::testCeilArg):
     59        (JSC::B3::testCeilImm):
     60        (JSC::B3::testCeilMem):
     61        (JSC::B3::testCeilCeilArg):
     62        (JSC::B3::testCeilIToD64):
     63        (JSC::B3::testCeilIToD32):
     64        (JSC::B3::testCeilArgWithUselessDoubleConversion):
     65        (JSC::B3::testCeilArgWithEffectfulDoubleConversion):
     66        (JSC::B3::populateWithInterestingValues):
     67        (JSC::B3::run):
     68        * ftl/FTLB3Output.h:
     69        (JSC::FTL::Output::ceil64):
     70        * jit/ThunkGenerators.cpp:
     71        (JSC::ceilThunkGenerator):
     72
    1732015-12-14  Andreas Kling  <akling@apple.com>
    274
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h

    r192535 r194062  
    12001200    static bool supportsFloatingPointSqrt() { return true; }
    12011201    static bool supportsFloatingPointAbs() { return true; }
     1202    static bool supportsFloatingPointCeil() { return true; }
    12021203
    12031204    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r192535 r194062  
    857857    static bool supportsFloatingPointSqrt() { return true; }
    858858    static bool supportsFloatingPointAbs() { return true; }
     859    static bool supportsFloatingPointCeil() { return false; }
    859860
    860861    void loadDouble(ImplicitAddress address, FPRegisterID dest)
     
    10451046    {
    10461047        m_assembler.vneg(dest, src);
     1048    }
     1049
     1050    NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
     1051    {
     1052        ASSERT(!supportsFloatingPointCeil());
     1053        CRASH();
    10471054    }
    10481055
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h

    r192535 r194062  
    626626    }
    627627
     628    NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
     629    {
     630        ASSERT(!supportsFloatingPointCeil());
     631        CRASH();
     632    }
     633
    628634    ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
    629635    {
     
    12101216    }
    12111217    static bool supportsFloatingPointAbs() { return false; }
     1218    static bool supportsFloatingPointCeil() { return false; }
    12121219
    12131220    // Stack manipulation operations:
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h

    r192535 r194062  
    10921092    static bool supportsFloatingPointSqrt() { return true; }
    10931093    static bool supportsFloatingPointAbs() { return true; }
     1094    static bool supportsFloatingPointCeil() { return false; }
    10941095
    10951096    void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
     
    15731574        moveDouble(src, dest);
    15741575        m_assembler.dabs(dest);
     1576    }
     1577
     1578    NO_RETURN_DUE_TO_CRASH void ceilDouble(FPRegisterID, FPRegisterID)
     1579    {
     1580        ASSERT(!supportsFloatingPointCeil());
     1581        CRASH();
    15751582    }
    15761583
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.cpp

    r193125 r194062  
    553553#endif
    554554
    555 MacroAssemblerX86Common::LZCNTCheckState MacroAssemblerX86Common::s_lzcntCheckState = LZCNTCheckState::NotChecked;
     555MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_sse4_1CheckState = CPUIDCheckState::NotChecked;
     556MacroAssemblerX86Common::CPUIDCheckState MacroAssemblerX86Common::s_lzcntCheckState = CPUIDCheckState::NotChecked;
    556557
    557558} // namespace JSC
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r194039 r194062  
    571571    }
    572572
     573    void ceilDouble(FPRegisterID src, FPRegisterID dst)
     574    {
     575        m_assembler.roundsd_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
     576    }
     577
     578    void ceilDouble(Address src, FPRegisterID dst)
     579    {
     580        m_assembler.roundsd_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
     581    }
     582
     583    void ceilFloat(FPRegisterID src, FPRegisterID dst)
     584    {
     585        m_assembler.roundss_rr(src, dst, X86Assembler::RoundingType::TowardInfiniti);
     586    }
     587
     588    void ceilFloat(Address src, FPRegisterID dst)
     589    {
     590        m_assembler.roundss_mr(src.offset, src.base, dst, X86Assembler::RoundingType::TowardInfiniti);
     591    }
    573592
    574593    // Memory access operations:
     
    17981817    }
    17991818
     1819    static bool supportsFloatingPointCeil()
     1820    {
     1821        if (s_sse4_1CheckState == CPUIDCheckState::NotChecked) {
     1822            int flags = 0;
     1823#if COMPILER(MSVC)
     1824            int cpuInfo[4];
     1825            __cpuid(cpuInfo, 0x1);
     1826            flags = cpuInfo[2];
     1827#elif COMPILER(GCC_OR_CLANG)
     1828#if CPU(X86_64)
     1829            asm (
     1830                "movl $0x1, %%eax;"
     1831                "cpuid;"
     1832                "movl %%ecx, %0;"
     1833                : "=g" (flags)
     1834                :
     1835                : "%eax", "%ebx", "%ecx", "%edx"
     1836                );
     1837#else
     1838            asm (
     1839                "movl $0x1, %%eax;"
     1840                "pushl %%ebx;"
     1841                "cpuid;"
     1842                "popl %%ebx;"
     1843                "movl %%ecx, %0;"
     1844                : "=g" (flags)
     1845                :
     1846                : "%eax", "%ecx", "%edx"
     1847                );
     1848#endif
     1849#endif // COMPILER(GCC_OR_CLANG)
     1850            s_sse4_1CheckState = (flags & (1 << 19)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
     1851        }
     1852        return s_sse4_1CheckState == CPUIDCheckState::Set;
     1853    }
     1854
    18001855#if ENABLE(MASM_PROBE)
    18011856    void probe(ProbeFunction, void* arg1, void* arg2);
     
    18381893#endif
    18391894    }
    1840    
     1895
    18411896    static bool supportsLZCNT()
    18421897    {
    1843         if (s_lzcntCheckState == LZCNTCheckState::NotChecked) {
     1898        if (s_lzcntCheckState == CPUIDCheckState::NotChecked) {
    18441899            int flags = 0;
    18451900#if COMPILER(MSVC)
     
    18701925#endif
    18711926#endif // COMPILER(GCC_OR_CLANG)
    1872             s_lzcntCheckState = (flags & 0x20) ? LZCNTCheckState::Set : LZCNTCheckState::Clear;
    1873         }
    1874         return s_lzcntCheckState == LZCNTCheckState::Set;
     1927            s_lzcntCheckState = (flags & 0x20) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
     1928        }
     1929        return s_lzcntCheckState == CPUIDCheckState::Set;
    18751930    }
    18761931
     
    20422097#endif
    20432098
    2044     enum class LZCNTCheckState {
     2099    enum class CPUIDCheckState {
    20452100        NotChecked,
    20462101        Clear,
    20472102        Set
    20482103    };
    2049     static LZCNTCheckState s_lzcntCheckState;
     2104    static CPUIDCheckState s_sse4_1CheckState;
     2105    static CPUIDCheckState s_lzcntCheckState;
    20502106};
    20512107
  • trunk/Source/JavaScriptCore/assembler/X86Assembler.h

    r194039 r194062  
    265265        OP2_CVTTSD2SI_GdWsd = 0x2C,
    266266        OP2_UCOMISD_VsdWsd  = 0x2E,
     267        OP2_3BYTE_ESCAPE_3A = 0x3A,
    267268        OP2_CMOVCC          = 0x40,
    268269        OP2_ADDSD_VsdWsd    = 0x58,
     
    281282        OP2_JCC_rel32       = 0x80,
    282283        OP_SETCC            = 0x90,
    283         OP2_3BYTE_ESCAPE    = 0xAE,
     284        OP2_3BYTE_ESCAPE_AE = 0xAE,
    284285        OP2_IMUL_GvEv       = 0xAF,
    285286        OP2_MOVZX_GvEb      = 0xB6,
     
    296297   
    297298    typedef enum {
    298         OP3_MFENCE          = 0xF0,
     299        OP3_ROUNDSS_VssWssIb = 0x0A,
     300        OP3_ROUNDSD_VsdWsdIb = 0x0B,
     301        OP3_MFENCE           = 0xF0,
    299302    } ThreeByteOpcodeID;
    300303
     
    23502353    }
    23512354
     2355    enum class RoundingType : uint8_t {
     2356        ToNearestWithTiesToEven = 0,
     2357        TowardNegativeInfiniti = 1,
     2358        TowardInfiniti = 2,
     2359        TowardZero = 3
     2360    };
     2361
     2362    void roundss_rr(XMMRegisterID src, XMMRegisterID dst, RoundingType rounding)
     2363    {
     2364        m_formatter.prefix(PRE_SSE_66);
     2365        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSS_VssWssIb, (RegisterID)dst, (RegisterID)src);
     2366        m_formatter.immediate8(static_cast<uint8_t>(rounding));
     2367    }
     2368
     2369    void roundss_mr(int offset, RegisterID base, XMMRegisterID dst, RoundingType rounding)
     2370    {
     2371        m_formatter.prefix(PRE_SSE_66);
     2372        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSS_VssWssIb, (RegisterID)dst, base, offset);
     2373        m_formatter.immediate8(static_cast<uint8_t>(rounding));
     2374    }
     2375
     2376    void roundsd_rr(XMMRegisterID src, XMMRegisterID dst, RoundingType rounding)
     2377    {
     2378        m_formatter.prefix(PRE_SSE_66);
     2379        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSD_VsdWsdIb, (RegisterID)dst, (RegisterID)src);
     2380        m_formatter.immediate8(static_cast<uint8_t>(rounding));
     2381    }
     2382
     2383    void roundsd_mr(int offset, RegisterID base, XMMRegisterID dst, RoundingType rounding)
     2384    {
     2385        m_formatter.prefix(PRE_SSE_66);
     2386        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_3A, OP3_ROUNDSD_VsdWsdIb, (RegisterID)dst, base, offset);
     2387        m_formatter.immediate8(static_cast<uint8_t>(rounding));
     2388    }
     2389
    23522390    // Misc instructions:
    23532391
     
    23692407    void mfence()
    23702408    {
    2371         m_formatter.threeByteOp(OP3_MFENCE);
     2409        m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_AE, OP3_MFENCE);
    23722410    }
    23732411
     
    28482886#endif
    28492887
    2850         void threeByteOp(ThreeByteOpcodeID opcode)
     2888        void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode)
    28512889        {
    28522890            m_buffer.ensureSpace(maxInstructionSize);
    28532891            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
    2854             m_buffer.putByteUnchecked(OP2_3BYTE_ESCAPE);
     2892            m_buffer.putByteUnchecked(twoBytePrefix);
    28552893            m_buffer.putByteUnchecked(opcode);
     2894        }
     2895
     2896        void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode, int reg, RegisterID rm)
     2897        {
     2898            m_buffer.ensureSpace(maxInstructionSize);
     2899            emitRexIfNeeded(reg, 0, rm);
     2900            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
     2901            m_buffer.putByteUnchecked(twoBytePrefix);
     2902            m_buffer.putByteUnchecked(opcode);
     2903            registerModRM(reg, rm);
     2904        }
     2905
     2906        void threeByteOp(TwoByteOpcodeID twoBytePrefix, ThreeByteOpcodeID opcode, int reg, RegisterID base, int displacement)
     2907        {
     2908            m_buffer.ensureSpace(maxInstructionSize);
     2909            emitRexIfNeeded(reg, 0, base);
     2910            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
     2911            m_buffer.putByteUnchecked(twoBytePrefix);
     2912            m_buffer.putByteUnchecked(opcode);
     2913            memoryModRM(reg, base, displacement);
    28562914        }
    28572915
  • trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.cpp

    r194003 r194062  
    9393}
    9494
     95Value* ConstDoubleValue::ceilConstant(Procedure& proc) const
     96{
     97    return proc.add<ConstDoubleValue>(origin(), ceil(m_value));
     98}
     99
    95100Value* ConstDoubleValue::sqrtConstant(Procedure& proc) const
    96101{
  • trunk/Source/JavaScriptCore/b3/B3ConstDoubleValue.h

    r194003 r194062  
    5252    Value* doubleToFloatConstant(Procedure&) const override;
    5353    Value* absConstant(Procedure&) const override;
     54    Value* ceilConstant(Procedure&) const override;
    5455    Value* sqrtConstant(Procedure&) const override;
    5556
  • trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.cpp

    r194003 r194062  
    9393}
    9494
     95Value* ConstFloatValue::ceilConstant(Procedure& proc) const
     96{
     97    return proc.add<ConstFloatValue>(origin(), ceilf(m_value));
     98}
     99
    95100Value* ConstFloatValue::sqrtConstant(Procedure& proc) const
    96101{
  • trunk/Source/JavaScriptCore/b3/B3ConstFloatValue.h

    r194003 r194062  
    5151    Value* floatToDoubleConstant(Procedure&) const override;
    5252    Value* absConstant(Procedure&) const override;
     53    Value* ceilConstant(Procedure&) const override;
    5354    Value* sqrtConstant(Procedure&) const override;
    5455
  • trunk/Source/JavaScriptCore/b3/B3LowerMacrosAfterOptimizations.cpp

    r194003 r194062  
    3131#include "B3BasicBlockInlines.h"
    3232#include "B3BlockInsertionSet.h"
     33#include "B3CCallValue.h"
    3334#include "B3ConstDoubleValue.h"
    3435#include "B3ConstFloatValue.h"
     36#include "B3ConstPtrValue.h"
    3537#include "B3InsertionSetInlines.h"
    3638#include "B3PhaseScope.h"
     
    8688                break;
    8789            }
     90            case Ceil: {
     91                if (MacroAssembler::supportsFloatingPointCeil())
     92                    break;
     93
     94                Value* functionAddress = nullptr;
     95                if (m_value->type() == Double)
     96                    functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, ceil);
     97                else if (m_value->type() == Float)
     98                    functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, ceilf);
     99                else
     100                    RELEASE_ASSERT_NOT_REACHED();
     101
     102                Value* result = m_insertionSet.insert<CCallValue>(m_index,
     103                    m_value->type(),
     104                    m_origin,
     105                    Effects::none(),
     106                    functionAddress,
     107                    m_value->child(0));
     108                m_value->replaceWithIdentity(result);
     109                break;
     110            }
    88111            default:
    89112                break;
  • trunk/Source/JavaScriptCore/b3/B3LowerToAir.cpp

    r194039 r194062  
    16551655        }
    16561656
     1657        case Ceil: {
     1658            appendUnOp<Air::Oops, Air::Oops, CeilDouble, CeilFloat>(m_value->child(0));
     1659            return;
     1660        }
     1661
    16571662        case Sqrt: {
    16581663            appendUnOp<Air::Oops, Air::Oops, SqrtDouble, SqrtFloat>(m_value->child(0));
  • trunk/Source/JavaScriptCore/b3/B3Opcode.cpp

    r194003 r194062  
    150150        out.print("Abs");
    151151        return;
     152    case Ceil:
     153        out.print("Ceil");
     154        return;
    152155    case Sqrt:
    153156        out.print("Sqrt");
  • trunk/Source/JavaScriptCore/b3/B3Opcode.h

    r194048 r194062  
    8787    // Floating point math.
    8888    Abs,
     89    Ceil,
    8990    Sqrt,
    9091
  • trunk/Source/JavaScriptCore/b3/B3ReduceDoubleToFloat.cpp

    r194003 r194062  
    5050        break;
    5151    case Abs:
     52    case Ceil:
    5253    case Sqrt:
    5354        if (candidate->child(0)->opcode() == FloatToDouble) {
  • trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp

    r194039 r194062  
    565565            break;
    566566
     567        case Ceil:
     568            // Turn this: Ceil(constant)
     569            // Into this: ceil<value->type()>(constant)
     570            if (Value* constant = m_value->child(0)->ceilConstant(m_proc)) {
     571                replaceWithNewValue(constant);
     572                break;
     573            }
     574
     575            // Turn this: Ceil(Ceil(value))
     576            // Into this: Ceil(value)
     577            if (m_value->child(0)->opcode() == Ceil) {
     578                m_value->replaceWithIdentity(m_value->child(0));
     579                break;
     580            }
     581
     582            // Turn this: Ceil(IToD(value))
     583            // Into this: IToD(value)
     584            //
     585            // That works for Int64 because both ARM64 and x86_64
     586            // perform rounding when converting a 64bit integer to double.
     587            if (m_value->child(0)->opcode() == IToD) {
     588                m_value->replaceWithIdentity(m_value->child(0));
     589                break;
     590            }
     591            break;
     592
    567593        case Sqrt:
    568594            // Turn this: Sqrt(constant)
  • trunk/Source/JavaScriptCore/b3/B3Validate.cpp

    r194003 r194062  
    211211                break;
    212212            case Abs:
     213            case Ceil:
    213214            case Sqrt:
    214215                VALIDATE(value->numChildren() == 1, ("At ", *value));
  • trunk/Source/JavaScriptCore/b3/B3Value.cpp

    r194048 r194062  
    223223
    224224Value* Value::absConstant(Procedure&) const
     225{
     226    return nullptr;
     227}
     228
     229Value* Value::ceilConstant(Procedure&) const
    225230{
    226231    return nullptr;
     
    364369    case Clz:
    365370    case Abs:
     371    case Ceil:
    366372    case Sqrt:
    367373    case BitwiseCast:
     
    443449    case Identity:
    444450    case Abs:
     451    case Ceil:
    445452    case Sqrt:
    446453    case SExt8:
     
    550557    case Clz:
    551558    case Abs:
     559    case Ceil:
    552560    case Sqrt:
    553561    case CheckAdd:
  • trunk/Source/JavaScriptCore/b3/B3Value.h

    r194003 r194062  
    133133    virtual Value* floatToDoubleConstant(Procedure&) const;
    134134    virtual Value* absConstant(Procedure&) const;
     135    virtual Value* ceilConstant(Procedure&) const;
    135136    virtual Value* sqrtConstant(Procedure&) const;
    136137
  • trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes

    r194045 r194062  
    276276    x86: Addr
    277277
     278CeilDouble U:F, UD:F
     279    Tmp, Tmp
     280    Addr, Tmp
     281
     282CeilFloat U:F, UD:F
     283    Tmp, Tmp
     284    Addr, Tmp
     285
    278286SqrtDouble U:F, UD:F
    279287    Tmp, Tmp
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r194050 r194062  
    32363236}
    32373237
     3238void testCeilArg(double a)
     3239{
     3240    Procedure proc;
     3241    BasicBlock* root = proc.addBlock();
     3242    root->appendNew<ControlValue>(
     3243        proc, Return, Origin(),
     3244        root->appendNew<Value>(
     3245            proc, Ceil, Origin(),
     3246                root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0)));
     3247
     3248    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
     3249}
     3250
     3251void testCeilImm(double a)
     3252{
     3253    Procedure proc;
     3254    BasicBlock* root = proc.addBlock();
     3255    Value* argument = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
     3256    root->appendNew<ControlValue>(
     3257        proc, Return, Origin(),
     3258        root->appendNew<Value>(proc, Ceil, Origin(), argument));
     3259
     3260    CHECK(isIdentical(compileAndRun<double>(proc), ceil(a)));
     3261}
     3262
     3263void testCeilMem(double a)
     3264{
     3265    Procedure proc;
     3266    BasicBlock* root = proc.addBlock();
     3267    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
     3268    MemoryValue* loadDouble = root->appendNew<MemoryValue>(proc, Load, Double, Origin(), address);
     3269    root->appendNew<ControlValue>(
     3270        proc, Return, Origin(),
     3271        root->appendNew<Value>(proc, Ceil, Origin(), loadDouble));
     3272
     3273    CHECK(isIdentical(compileAndRun<double>(proc, &a), ceil(a)));
     3274}
     3275
     3276void testCeilCeilArg(double a)
     3277{
     3278    Procedure proc;
     3279    BasicBlock* root = proc.addBlock();
     3280    Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(),
     3281        root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0));
     3282    Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
     3283    root->appendNew<ControlValue>(proc, Return, Origin(), secondCeil);
     3284
     3285    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(a)));
     3286}
     3287
     3288void testCeilIToD64(int64_t a)
     3289{
     3290    Procedure proc;
     3291    BasicBlock* root = proc.addBlock();
     3292    Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
     3293    Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
     3294
     3295    root->appendNew<ControlValue>(
     3296        proc, Return, Origin(),
     3297        root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
     3298
     3299    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
     3300}
     3301
     3302void testCeilIToD32(int64_t a)
     3303{
     3304    Procedure proc;
     3305    BasicBlock* root = proc.addBlock();
     3306    Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
     3307        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3308    Value* argumentAsDouble = root->appendNew<Value>(proc, IToD, Origin(), argument);
     3309
     3310    root->appendNew<ControlValue>(
     3311        proc, Return, Origin(),
     3312        root->appendNew<Value>(proc, Ceil, Origin(), argumentAsDouble));
     3313
     3314    CHECK(isIdentical(compileAndRun<double>(proc, a), ceil(static_cast<double>(a))));
     3315}
     3316
     3317void testCeilArg(float a)
     3318{
     3319    Procedure proc;
     3320    BasicBlock* root = proc.addBlock();
     3321    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
     3322        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3323    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
     3324    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
     3325    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
     3326    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
     3327
     3328    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
     3329}
     3330
     3331void testCeilImm(float a)
     3332{
     3333    Procedure proc;
     3334    BasicBlock* root = proc.addBlock();
     3335    Value* argument = root->appendNew<ConstFloatValue>(proc, Origin(), a);
     3336    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), argument);
     3337    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
     3338    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
     3339
     3340    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
     3341}
     3342
     3343void testCeilMem(float a)
     3344{
     3345    Procedure proc;
     3346    BasicBlock* root = proc.addBlock();
     3347    Value* address = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
     3348    MemoryValue* loadFloat = root->appendNew<MemoryValue>(proc, Load, Float, Origin(), address);
     3349    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), loadFloat);
     3350    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
     3351    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
     3352
     3353    CHECK(isIdentical(compileAndRun<int32_t>(proc, &a), bitwise_cast<int32_t>(ceilf(a))));
     3354}
     3355
     3356void testCeilCeilArg(float a)
     3357{
     3358    Procedure proc;
     3359    BasicBlock* root = proc.addBlock();
     3360    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
     3361        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3362    Value* argument = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
     3363    Value* firstCeil = root->appendNew<Value>(proc, Ceil, Origin(), argument);
     3364    Value* secondCeil = root->appendNew<Value>(proc, Ceil, Origin(), firstCeil);
     3365    root->appendNew<ControlValue>(proc, Return, Origin(), secondCeil);
     3366
     3367    CHECK(isIdentical(compileAndRun<float>(proc, bitwise_cast<int32_t>(a)), ceilf(a)));
     3368}
     3369
     3370void testCeilArgWithUselessDoubleConversion(float a)
     3371{
     3372    Procedure proc;
     3373    BasicBlock* root = proc.addBlock();
     3374    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
     3375        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3376    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
     3377    Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
     3378    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
     3379    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
     3380    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
     3381    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
     3382
     3383    CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(ceilf(a))));
     3384}
     3385
     3386void testCeilArgWithEffectfulDoubleConversion(float a)
     3387{
     3388    Procedure proc;
     3389    BasicBlock* root = proc.addBlock();
     3390    Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
     3391        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
     3392    Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
     3393    Value* asDouble = root->appendNew<Value>(proc, FloatToDouble, Origin(), floatValue);
     3394    Value* result = root->appendNew<Value>(proc, Ceil, Origin(), asDouble);
     3395    Value* floatResult = root->appendNew<Value>(proc, DoubleToFloat, Origin(), result);
     3396    Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), floatResult);
     3397    Value* doubleAddress = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
     3398    root->appendNew<MemoryValue>(proc, Store, Origin(), result, doubleAddress);
     3399    root->appendNew<ControlValue>(proc, Return, Origin(), result32);
     3400
     3401    double effect = 0;
     3402    int32_t resultValue = compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), &effect);
     3403    CHECK(isIdentical(resultValue, bitwise_cast<int32_t>(ceilf(a))));
     3404    CHECK(isIdentical(effect, ceilf(a)));
     3405}
     3406
    32383407void testSqrtArg(double a)
    32393408{
     
    80098178    operands.append({ "0.", static_cast<FloatType>(0.) });
    80108179    operands.append({ "-0.", static_cast<FloatType>(-0.) });
     8180    operands.append({ "0.4", static_cast<FloatType>(0.5) });
     8181    operands.append({ "-0.4", static_cast<FloatType>(-0.5) });
     8182    operands.append({ "0.5", static_cast<FloatType>(0.5) });
     8183    operands.append({ "-0.5", static_cast<FloatType>(-0.5) });
     8184    operands.append({ "0.6", static_cast<FloatType>(0.5) });
     8185    operands.append({ "-0.6", static_cast<FloatType>(-0.5) });
    80118186    operands.append({ "1.", static_cast<FloatType>(1.) });
    80128187    operands.append({ "-1.", static_cast<FloatType>(-1.) });
     
    86388813    RUN_UNARY(testAbsArgWithUselessDoubleConversion, floatingPointOperands<float>());
    86398814    RUN_UNARY(testAbsArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
     8815
     8816    RUN_UNARY(testCeilArg, floatingPointOperands<double>());
     8817    RUN_UNARY(testCeilImm, floatingPointOperands<double>());
     8818    RUN_UNARY(testCeilMem, floatingPointOperands<double>());
     8819    RUN_UNARY(testCeilCeilArg, floatingPointOperands<double>());
     8820    RUN_UNARY(testCeilIToD64, int64Operands());
     8821    RUN_UNARY(testCeilIToD32, int32Operands());
     8822    RUN_UNARY(testCeilArg, floatingPointOperands<float>());
     8823    RUN_UNARY(testCeilImm, floatingPointOperands<float>());
     8824    RUN_UNARY(testCeilMem, floatingPointOperands<float>());
     8825    RUN_UNARY(testCeilCeilArg, floatingPointOperands<float>());
     8826    RUN_UNARY(testCeilArgWithUselessDoubleConversion, floatingPointOperands<float>());
     8827    RUN_UNARY(testCeilArgWithEffectfulDoubleConversion, floatingPointOperands<float>());
    86408828
    86418829    RUN_UNARY(testSqrtArg, floatingPointOperands<double>());
  • trunk/Source/JavaScriptCore/ftl/FTLB3Output.h

    r194024 r194062  
    155155    LValue bitNot(LValue);
    156156
    157     LValue ceil64(LValue operand) { CRASH(); }
     157    LValue ceil64(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Ceil, origin(), value); }
    158158    LValue ctlz32(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand); }
    159159    LValue addWithOverflow32(LValue left, LValue right) { CRASH(); }
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r191937 r194062  
    829829    nonIntJump.link(&jit);
    830830    jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
    831 #if CPU(ARM64)
    832     jit.ceilDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
    833 #else
    834     jit.callDoubleToDoublePreservingReturn(UnaryDoubleOpWrapper(ceil));
    835 #endif // CPU(ARM64)
     831    if (jit.supportsFloatingPointCeil())
     832        jit.ceilDouble(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::fpRegT0);
     833    else
     834        jit.callDoubleToDoublePreservingReturn(UnaryDoubleOpWrapper(ceil));
     835
    836836    SpecializedThunkJIT::JumpList doubleResult;
    837837    jit.branchConvertDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, doubleResult, SpecializedThunkJIT::fpRegT1);
Note: See TracChangeset for help on using the changeset viewer.