Changeset 258038 in webkit


Ignore:
Timestamp:
Mar 6, 2020 5:16:14 PM (4 years ago)
Author:
mark.lam@apple.com
Message:

Fix some issues in the ARM64 moveConditionallyAfterFloatingPointCompare() and moveDoubleConditionallyAfterFloatingPointCompare().
https://bugs.webkit.org/show_bug.cgi?id=208731
<rdar://problem/59222568>

Reviewed by Saam Barati.

Both the ARM64 moveConditionallyAfterFloatingPointCompare() and
moveDoubleConditionallyAfterFloatingPointCompare() had the following issues:

  1. For the DoubleNotEqual condition, they fail to set the result register if one or both of the comparison operands is a NaN.
  1. For the DoubleEqualOrUnordered condition, they can clobber the else case input register if one of the comparison operands is a NaN.

This patch fixes both of these, and exhaustive testmasm test cases for affected
MacroAssembler instruction emitters using these functions.

  • assembler/MacroAssemblerARM64.h:

(JSC::MacroAssemblerARM64::moveConditionallyAfterFloatingPointCompare):
(JSC::MacroAssemblerARM64::moveDoubleConditionallyAfterFloatingPointCompare):

  • assembler/testmasm.cpp:

(JSC::testCompareDouble):
(JSC::testCompareDoubleSameArg):
(JSC::testMoveConditionallyFloatingPoint):
(JSC::testMoveConditionallyDouble2):
(JSC::testMoveConditionallyDouble3):
(JSC::testMoveConditionallyDouble3DestSameAsThenCase):
(JSC::testMoveConditionallyDouble3DestSameAsElseCase):
(JSC::testMoveConditionallyFloat2):
(JSC::testMoveConditionallyFloat3):
(JSC::testMoveConditionallyFloat3DestSameAsThenCase):
(JSC::testMoveConditionallyFloat3DestSameAsElseCase):
(JSC::testMoveDoubleConditionallyDouble):
(JSC::testMoveDoubleConditionallyDoubleDestSameAsThenCase):
(JSC::testMoveDoubleConditionallyDoubleDestSameAsElseCase):
(JSC::testMoveDoubleConditionallyFloat):
(JSC::testMoveDoubleConditionallyFloatDestSameAsThenCase):
(JSC::testMoveDoubleConditionallyFloatDestSameAsElseCase):
(JSC::testMoveConditionallyFloatingPointSameArg):
(JSC::testMoveConditionallyDouble2SameArg):
(JSC::testMoveConditionallyDouble3SameArg):
(JSC::testMoveConditionallyFloat2SameArg):
(JSC::testMoveConditionallyFloat3SameArg):
(JSC::testMoveDoubleConditionallyDoubleSameArg):
(JSC::testMoveDoubleConditionallyFloatSameArg):
(JSC::run):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r257908 r258038  
     12020-03-06  Mark Lam  <mark.lam@apple.com>
     2
     3        Fix some issues in the ARM64 moveConditionallyAfterFloatingPointCompare() and moveDoubleConditionallyAfterFloatingPointCompare().
     4        https://bugs.webkit.org/show_bug.cgi?id=208731
     5        <rdar://problem/59222568>
     6
     7        Reviewed by Saam Barati.
     8
     9        Both the ARM64 moveConditionallyAfterFloatingPointCompare() and
     10        moveDoubleConditionallyAfterFloatingPointCompare() had the following issues:
     11
     12        1. For the DoubleNotEqual condition, they fail to set the result register if
     13           one or both of the comparison operands is a NaN.
     14
     15        2. For the DoubleEqualOrUnordered condition, they can clobber the else case
     16           input register if one of the comparison operands is a NaN.
     17
     18        This patch fixes both of these, and exhaustive testmasm test cases for affected
     19        MacroAssembler instruction emitters using these functions.
     20
     21        * assembler/MacroAssemblerARM64.h:
     22        (JSC::MacroAssemblerARM64::moveConditionallyAfterFloatingPointCompare):
     23        (JSC::MacroAssemblerARM64::moveDoubleConditionallyAfterFloatingPointCompare):
     24        * assembler/testmasm.cpp:
     25        (JSC::testCompareDouble):
     26        (JSC::testCompareDoubleSameArg):
     27        (JSC::testMoveConditionallyFloatingPoint):
     28        (JSC::testMoveConditionallyDouble2):
     29        (JSC::testMoveConditionallyDouble3):
     30        (JSC::testMoveConditionallyDouble3DestSameAsThenCase):
     31        (JSC::testMoveConditionallyDouble3DestSameAsElseCase):
     32        (JSC::testMoveConditionallyFloat2):
     33        (JSC::testMoveConditionallyFloat3):
     34        (JSC::testMoveConditionallyFloat3DestSameAsThenCase):
     35        (JSC::testMoveConditionallyFloat3DestSameAsElseCase):
     36        (JSC::testMoveDoubleConditionallyDouble):
     37        (JSC::testMoveDoubleConditionallyDoubleDestSameAsThenCase):
     38        (JSC::testMoveDoubleConditionallyDoubleDestSameAsElseCase):
     39        (JSC::testMoveDoubleConditionallyFloat):
     40        (JSC::testMoveDoubleConditionallyFloatDestSameAsThenCase):
     41        (JSC::testMoveDoubleConditionallyFloatDestSameAsElseCase):
     42        (JSC::testMoveConditionallyFloatingPointSameArg):
     43        (JSC::testMoveConditionallyDouble2SameArg):
     44        (JSC::testMoveConditionallyDouble3SameArg):
     45        (JSC::testMoveConditionallyFloat2SameArg):
     46        (JSC::testMoveConditionallyFloat3SameArg):
     47        (JSC::testMoveDoubleConditionallyDoubleSameArg):
     48        (JSC::testMoveDoubleConditionallyFloatSameArg):
     49        (JSC::run):
     50
    1512020-03-05  Paulo Matos  <pmatos@igalia.com>
    252
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h

    r252728 r258038  
    20292029    {
    20302030        if (cond == DoubleNotEqual) {
    2031             Jump unordered = makeBranch(Assembler::ConditionVS);
    2032             m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
    2033             unordered.link(this);
     2031            if (dest == thenCase) {
     2032                // If the compare is unordered, elseCase is copied to thenCase and the
     2033                // next csel has all arguments equal to elseCase.
     2034                // If the compare is ordered, dest is unchanged and NE decides
     2035                // what value to set.
     2036                m_assembler.csel<datasize>(thenCase, elseCase, thenCase, Assembler::ConditionNE);
     2037                m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
     2038            } else {
     2039                move(elseCase, dest);
     2040                Jump unordered = makeBranch(Assembler::ConditionVS);
     2041                m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
     2042                unordered.link(this);
     2043            }
    20342044            return;
    20352045        }
    20362046        if (cond == DoubleEqualOrUnordered) {
    2037             // If the compare is unordered, thenCase is copied to elseCase and the
    2038             // next csel has all arguments equal to thenCase.
    2039             // If the compare is ordered, dest is unchanged and EQ decides
    2040             // what value to set.
    2041             m_assembler.csel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
    2042             m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
     2047            if (dest == elseCase) {
     2048                // If the compare is unordered, thenCase is copied to elseCase and the
     2049                // next csel has all arguments equal to thenCase.
     2050                // If the compare is ordered, dest is unchanged and EQ decides
     2051                // what value to set.
     2052                m_assembler.csel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
     2053                m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
     2054            } else {
     2055                move(thenCase, dest);
     2056                Jump unordered = makeBranch(Assembler::ConditionVS);
     2057                m_assembler.csel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
     2058                unordered.link(this);
     2059            }
    20432060            return;
    20442061        }
     
    20502067    {
    20512068        if (cond == DoubleNotEqual) {
    2052             Jump unordered = makeBranch(Assembler::ConditionVS);
    2053             m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
    2054             unordered.link(this);
     2069            if (dest == thenCase) {
     2070                // If the compare is unordered, elseCase is copied to thenCase and the
     2071                // next fcsel has all arguments equal to elseCase.
     2072                // If the compare is ordered, dest is unchanged and NE decides
     2073                // what value to set.
     2074                m_assembler.fcsel<datasize>(thenCase, elseCase, thenCase, Assembler::ConditionVS);
     2075                m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
     2076            } else {
     2077                m_assembler.fmov<64>(dest, elseCase);
     2078                Jump unordered = makeBranch(Assembler::ConditionVS);
     2079                m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionNE);
     2080                unordered.link(this);
     2081            }
    20552082            return;
    20562083        }
    20572084        if (cond == DoubleEqualOrUnordered) {
    2058             // If the compare is unordered, thenCase is copied to elseCase and the
    2059             // next csel has all arguments equal to thenCase.
    2060             // If the compare is ordered, dest is unchanged and EQ decides
    2061             // what value to set.
    2062             m_assembler.fcsel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
    2063             m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
     2085            if (dest == elseCase) {
     2086                // If the compare is unordered, thenCase is copied to elseCase and the
     2087                // next csel has all arguments equal to thenCase.
     2088                // If the compare is ordered, dest is unchanged and EQ decides
     2089                // what value to set.
     2090                m_assembler.fcsel<datasize>(elseCase, thenCase, elseCase, Assembler::ConditionVS);
     2091                m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
     2092            } else {
     2093                m_assembler.fmov<64>(dest, thenCase);
     2094                Jump unordered = makeBranch(Assembler::ConditionVS);
     2095                m_assembler.fcsel<datasize>(dest, thenCase, elseCase, Assembler::ConditionEQ);
     2096                unordered.link(this);
     2097            }
    20642098            return;
    20652099        }
  • trunk/Source/JavaScriptCore/assembler/testmasm.cpp

    r252728 r258038  
    500500    });
    501501
     502    auto expectedResult = [&, condition] (double a, double b) -> int {
     503        auto isUnordered = [] (double x) {
     504            return x != x;
     505        };
     506        switch (condition) {
     507        case MacroAssembler::DoubleEqual:
     508            return !isUnordered(a) && !isUnordered(b) && (a == b);
     509        case MacroAssembler::DoubleNotEqual:
     510            return !isUnordered(a) && !isUnordered(b) && (a != b);
     511        case MacroAssembler::DoubleGreaterThan:
     512            return !isUnordered(a) && !isUnordered(b) && (a > b);
     513        case MacroAssembler::DoubleGreaterThanOrEqual:
     514            return !isUnordered(a) && !isUnordered(b) && (a >= b);
     515        case MacroAssembler::DoubleLessThan:
     516            return !isUnordered(a) && !isUnordered(b) && (a < b);
     517        case MacroAssembler::DoubleLessThanOrEqual:
     518            return !isUnordered(a) && !isUnordered(b) && (a <= b);
     519        case MacroAssembler::DoubleEqualOrUnordered:
     520            return isUnordered(a) || isUnordered(b) || (a == b);
     521        case MacroAssembler::DoubleNotEqualOrUnordered:
     522            return isUnordered(a) || isUnordered(b) || (a != b);
     523        case MacroAssembler::DoubleGreaterThanOrUnordered:
     524            return isUnordered(a) || isUnordered(b) || (a > b);
     525        case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
     526            return isUnordered(a) || isUnordered(b) || (a >= b);
     527        case MacroAssembler::DoubleLessThanOrUnordered:
     528            return isUnordered(a) || isUnordered(b) || (a < b);
     529        case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
     530            return isUnordered(a) || isUnordered(b) || (a <= b);
     531        } // switch
     532    };
     533
    502534    auto operands = doubleOperands();
    503535    for (auto a : operands) {
     
    505537            arg1 = a;
    506538            arg2 = b;
    507             CHECK_EQ(invoke<int>(compareDouble), invoke<int>(compareDoubleGeneric));
     539            CHECK_EQ(invoke<int>(compareDouble), expectedResult(a, b));
     540            CHECK_EQ(invoke<int>(compareDoubleGeneric), expectedResult(a, b));
    508541        }
     542    }
     543}
     544
     545void testCompareDoubleSameArg(MacroAssembler::DoubleCondition condition)
     546{
     547    double arg1 = 0;
     548
     549    auto compareDouble = compile([&, condition] (CCallHelpers& jit) {
     550        emitFunctionPrologue(jit);
     551
     552        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     553        jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
     554        jit.compareDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, GPRInfo::returnValueGPR);
     555
     556        emitFunctionEpilogue(jit);
     557        jit.ret();
     558    });
     559
     560    auto compareDoubleGeneric = compile([&, condition] (CCallHelpers& jit) {
     561        emitFunctionPrologue(jit);
     562
     563        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     564        jit.move(CCallHelpers::TrustedImm32(1), GPRInfo::returnValueGPR);
     565        auto jump = jit.branchDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0);
     566        jit.move(CCallHelpers::TrustedImm32(0), GPRInfo::returnValueGPR);
     567        jump.link(&jit);
     568
     569        emitFunctionEpilogue(jit);
     570        jit.ret();
     571    });
     572
     573    auto expectedResult = [&, condition] (double a) -> int {
     574        auto isUnordered = [] (double x) {
     575            return x != x;
     576        };
     577        switch (condition) {
     578        case MacroAssembler::DoubleEqual:
     579            return !isUnordered(a) && (a == a);
     580        case MacroAssembler::DoubleNotEqual:
     581            return !isUnordered(a) && (a != a);
     582        case MacroAssembler::DoubleGreaterThan:
     583            return !isUnordered(a) && (a > a);
     584        case MacroAssembler::DoubleGreaterThanOrEqual:
     585            return !isUnordered(a) && (a >= a);
     586        case MacroAssembler::DoubleLessThan:
     587            return !isUnordered(a) && (a < a);
     588        case MacroAssembler::DoubleLessThanOrEqual:
     589            return !isUnordered(a) && (a <= a);
     590        case MacroAssembler::DoubleEqualOrUnordered:
     591            return isUnordered(a) || (a == a);
     592        case MacroAssembler::DoubleNotEqualOrUnordered:
     593            return isUnordered(a) || (a != a);
     594        case MacroAssembler::DoubleGreaterThanOrUnordered:
     595            return isUnordered(a) || (a > a);
     596        case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
     597            return isUnordered(a) || (a >= a);
     598        case MacroAssembler::DoubleLessThanOrUnordered:
     599            return isUnordered(a) || (a < a);
     600        case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
     601            return isUnordered(a) || (a <= a);
     602        } // switch
     603    };
     604
     605    auto operands = doubleOperands();
     606    for (auto a : operands) {
     607        arg1 = a;
     608        CHECK_EQ(invoke<int>(compareDouble), expectedResult(a));
     609        CHECK_EQ(invoke<int>(compareDoubleGeneric), expectedResult(a));
    509610    }
    510611}
     
    587688    }
    588689}
    589 #endif
     690#endif // CPU(X86) || CPU(X86_64) || CPU(ARM64)
     691
     692#if CPU(X86_64) || CPU(ARM64)
     693
     694template<typename T, typename SelectionType>
     695void testMoveConditionallyFloatingPoint(MacroAssembler::DoubleCondition condition, const MacroAssemblerCodeRef<JSEntryPtrTag>& testCode, T& arg1, T& arg2, const Vector<T> operands, SelectionType selectionA, SelectionType selectionB)
     696{
     697    auto expectedResult = [&, condition] (T a, T b) -> SelectionType {
     698        auto isUnordered = [] (double x) {
     699            return x != x;
     700        };
     701        switch (condition) {
     702        case MacroAssembler::DoubleEqual:
     703            return !isUnordered(a) && !isUnordered(b) && (a == b) ? selectionA : selectionB;
     704        case MacroAssembler::DoubleNotEqual:
     705            return !isUnordered(a) && !isUnordered(b) && (a != b) ? selectionA : selectionB;
     706        case MacroAssembler::DoubleGreaterThan:
     707            return !isUnordered(a) && !isUnordered(b) && (a > b) ? selectionA : selectionB;
     708        case MacroAssembler::DoubleGreaterThanOrEqual:
     709            return !isUnordered(a) && !isUnordered(b) && (a >= b) ? selectionA : selectionB;
     710        case MacroAssembler::DoubleLessThan:
     711            return !isUnordered(a) && !isUnordered(b) && (a < b) ? selectionA : selectionB;
     712        case MacroAssembler::DoubleLessThanOrEqual:
     713            return !isUnordered(a) && !isUnordered(b) && (a <= b) ? selectionA : selectionB;
     714        case MacroAssembler::DoubleEqualOrUnordered:
     715            return isUnordered(a) || isUnordered(b) || (a == b) ? selectionA : selectionB;
     716        case MacroAssembler::DoubleNotEqualOrUnordered:
     717            return isUnordered(a) || isUnordered(b) || (a != b) ? selectionA : selectionB;
     718        case MacroAssembler::DoubleGreaterThanOrUnordered:
     719            return isUnordered(a) || isUnordered(b) || (a > b) ? selectionA : selectionB;
     720        case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
     721            return isUnordered(a) || isUnordered(b) || (a >= b) ? selectionA : selectionB;
     722        case MacroAssembler::DoubleLessThanOrUnordered:
     723            return isUnordered(a) || isUnordered(b) || (a < b) ? selectionA : selectionB;
     724        case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
     725            return isUnordered(a) || isUnordered(b) || (a <= b) ? selectionA : selectionB;
     726        } // switch
     727    };
     728
     729    for (auto a : operands) {
     730        for (auto b : operands) {
     731            arg1 = a;
     732            arg2 = b;
     733            CHECK_EQ(invoke<SelectionType>(testCode), expectedResult(a, b));
     734        }
     735    }
     736}
     737
     738void testMoveConditionallyDouble2(MacroAssembler::DoubleCondition condition)
     739{
     740    double arg1 = 0;
     741    double arg2 = 0;
     742    unsigned selectionA = 42;
     743    unsigned selectionB = 17;
     744
     745    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     746        emitFunctionPrologue(jit);
     747
     748        GPRReg destGPR = GPRInfo::returnValueGPR;
     749        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     750        RELEASE_ASSERT(destGPR != selectionAGPR);
     751        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     752        jit.move(CCallHelpers::TrustedImm32(selectionB), destGPR);
     753
     754        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     755        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     756        jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, destGPR);
     757
     758        emitFunctionEpilogue(jit);
     759        jit.ret();
     760    });
     761
     762    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     763}
     764
     765void testMoveConditionallyDouble3(MacroAssembler::DoubleCondition condition)
     766{
     767    double arg1 = 0;
     768    double arg2 = 0;
     769    unsigned selectionA = 42;
     770    unsigned selectionB = 17;
     771    unsigned corruptedSelectionA = 0xbbad000a;
     772    unsigned corruptedSelectionB = 0xbbad000b;
     773
     774    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     775        emitFunctionPrologue(jit);
     776
     777        GPRReg destGPR = GPRInfo::returnValueGPR;
     778        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     779        GPRReg selectionBGPR = GPRInfo::argumentGPR3;
     780        RELEASE_ASSERT(destGPR != selectionAGPR);
     781        RELEASE_ASSERT(destGPR != selectionBGPR);
     782        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     783        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     784        jit.move(CCallHelpers::TrustedImm32(-1), destGPR);
     785
     786        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     787        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     788        jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
     789
     790        auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
     791        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
     792        aIsUnchanged.link(&jit);
     793
     794        auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
     795        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
     796        bIsUnchanged.link(&jit);
     797
     798        emitFunctionEpilogue(jit);
     799        jit.ret();
     800    });
     801
     802    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     803}
     804
     805void testMoveConditionallyDouble3DestSameAsThenCase(MacroAssembler::DoubleCondition condition)
     806{
     807    double arg1 = 0;
     808    double arg2 = 0;
     809    unsigned selectionA = 42;
     810    unsigned selectionB = 17;
     811    unsigned corruptedSelectionB = 0xbbad000b;
     812
     813    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     814        emitFunctionPrologue(jit);
     815
     816        GPRReg destGPR = GPRInfo::returnValueGPR;
     817        GPRReg selectionAGPR = destGPR;
     818        GPRReg selectionBGPR = GPRInfo::argumentGPR3;
     819        RELEASE_ASSERT(destGPR == selectionAGPR);
     820        RELEASE_ASSERT(destGPR != selectionBGPR);
     821        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     822        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     823
     824        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     825        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     826        jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
     827
     828        auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
     829        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
     830        bIsUnchanged.link(&jit);
     831
     832        emitFunctionEpilogue(jit);
     833        jit.ret();
     834    });
     835
     836    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     837}
     838
     839void testMoveConditionallyDouble3DestSameAsElseCase(MacroAssembler::DoubleCondition condition)
     840{
     841    double arg1 = 0;
     842    double arg2 = 0;
     843    unsigned selectionA = 42;
     844    unsigned selectionB = 17;
     845    unsigned corruptedSelectionA = 0xbbad000a;
     846
     847    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     848        emitFunctionPrologue(jit);
     849
     850        GPRReg destGPR = GPRInfo::returnValueGPR;
     851        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     852        GPRReg selectionBGPR = destGPR;
     853        RELEASE_ASSERT(destGPR != selectionAGPR);
     854        RELEASE_ASSERT(destGPR == selectionBGPR);
     855        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     856        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     857
     858        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     859        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     860        jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
     861
     862        auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
     863        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
     864        aIsUnchanged.link(&jit);
     865
     866        emitFunctionEpilogue(jit);
     867        jit.ret();
     868    });
     869
     870    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     871}
     872
     873void testMoveConditionallyFloat2(MacroAssembler::DoubleCondition condition)
     874{
     875    float arg1 = 0;
     876    float arg2 = 0;
     877    unsigned selectionA = 42;
     878    unsigned selectionB = 17;
     879
     880    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     881        emitFunctionPrologue(jit);
     882
     883        GPRReg destGPR = GPRInfo::returnValueGPR;
     884        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     885        RELEASE_ASSERT(destGPR != selectionAGPR);
     886        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     887        jit.move(CCallHelpers::TrustedImm32(selectionB), GPRInfo::returnValueGPR);
     888
     889        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     890        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     891        jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, destGPR);
     892
     893        emitFunctionEpilogue(jit);
     894        jit.ret();
     895    });
     896
     897    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     898}
     899
     900void testMoveConditionallyFloat3(MacroAssembler::DoubleCondition condition)
     901{
     902    float arg1 = 0;
     903    float arg2 = 0;
     904    unsigned selectionA = 42;
     905    unsigned selectionB = 17;
     906    unsigned corruptedSelectionA = 0xbbad000a;
     907    unsigned corruptedSelectionB = 0xbbad000b;
     908
     909    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     910        emitFunctionPrologue(jit);
     911
     912        GPRReg destGPR = GPRInfo::returnValueGPR;
     913        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     914        GPRReg selectionBGPR = GPRInfo::argumentGPR3;
     915        RELEASE_ASSERT(destGPR != selectionAGPR);
     916        RELEASE_ASSERT(destGPR != selectionBGPR);
     917        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     918        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     919        jit.move(CCallHelpers::TrustedImm32(-1), destGPR);
     920
     921        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     922        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     923        jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
     924
     925        auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
     926        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
     927        aIsUnchanged.link(&jit);
     928
     929        auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
     930        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
     931        bIsUnchanged.link(&jit);
     932
     933        emitFunctionEpilogue(jit);
     934        jit.ret();
     935    });
     936
     937    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     938}
     939
     940void testMoveConditionallyFloat3DestSameAsThenCase(MacroAssembler::DoubleCondition condition)
     941{
     942    float arg1 = 0;
     943    float arg2 = 0;
     944    unsigned selectionA = 42;
     945    unsigned selectionB = 17;
     946    unsigned corruptedSelectionB = 0xbbad000b;
     947
     948    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     949        emitFunctionPrologue(jit);
     950
     951        GPRReg destGPR = GPRInfo::returnValueGPR;
     952        GPRReg selectionAGPR = destGPR;
     953        GPRReg selectionBGPR = GPRInfo::argumentGPR3;
     954        RELEASE_ASSERT(destGPR == selectionAGPR);
     955        RELEASE_ASSERT(destGPR != selectionBGPR);
     956        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     957        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     958
     959        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     960        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     961        jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
     962
     963        auto bIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionBGPR, CCallHelpers::TrustedImm32(selectionB));
     964        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionB), destGPR);
     965        bIsUnchanged.link(&jit);
     966
     967        emitFunctionEpilogue(jit);
     968        jit.ret();
     969    });
     970
     971    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     972}
     973
     974void testMoveConditionallyFloat3DestSameAsElseCase(MacroAssembler::DoubleCondition condition)
     975{
     976    float arg1 = 0;
     977    float arg2 = 0;
     978    unsigned selectionA = 42;
     979    unsigned selectionB = 17;
     980    unsigned corruptedSelectionA = 0xbbad000a;
     981
     982    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     983        emitFunctionPrologue(jit);
     984
     985        GPRReg destGPR = GPRInfo::returnValueGPR;
     986        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     987        GPRReg selectionBGPR = destGPR;
     988        RELEASE_ASSERT(destGPR != selectionAGPR);
     989        RELEASE_ASSERT(destGPR == selectionBGPR);
     990        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     991        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     992
     993        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     994        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), FPRInfo::fpRegT1);
     995        jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT1, selectionAGPR, selectionBGPR, destGPR);
     996
     997        auto aIsUnchanged = jit.branch32(CCallHelpers::Equal, selectionAGPR, CCallHelpers::TrustedImm32(selectionA));
     998        jit.move(CCallHelpers::TrustedImm32(corruptedSelectionA), destGPR);
     999        aIsUnchanged.link(&jit);
     1000
     1001        emitFunctionEpilogue(jit);
     1002        jit.ret();
     1003    });
     1004
     1005    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     1006}
     1007
     1008void testMoveDoubleConditionallyDouble(MacroAssembler::DoubleCondition condition)
     1009{
     1010    double arg1 = 0;
     1011    double arg2 = 0;
     1012    double selectionA = 42.0;
     1013    double selectionB = 17.0;
     1014    double corruptedSelectionA = 55555;
     1015    double corruptedSelectionB = 66666;
     1016
     1017    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1018        emitFunctionPrologue(jit);
     1019
     1020        FPRReg destFPR = FPRInfo::returnValueFPR;
     1021        FPRReg selectionAFPR = FPRInfo::fpRegT1;
     1022        FPRReg selectionBFPR = FPRInfo::fpRegT2;
     1023        FPRReg arg1FPR = FPRInfo::fpRegT3;
     1024        FPRReg arg2FPR = FPRInfo::fpRegT4;
     1025
     1026        RELEASE_ASSERT(destFPR != selectionAFPR);
     1027        RELEASE_ASSERT(destFPR != selectionBFPR);
     1028        RELEASE_ASSERT(destFPR != arg1FPR);
     1029        RELEASE_ASSERT(destFPR != arg2FPR);
     1030
     1031        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
     1032        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
     1033        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
     1034        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
     1035        jit.moveDoubleConditionallyDouble(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
     1036
     1037        FPRReg tempFPR = FPRInfo::fpRegT5;
     1038        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
     1039        auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
     1040        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
     1041        aIsUnchanged.link(&jit);
     1042
     1043        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
     1044        auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
     1045        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
     1046        bIsUnchanged.link(&jit);
     1047
     1048        emitFunctionEpilogue(jit);
     1049        jit.ret();
     1050    });
     1051
     1052    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     1053}
     1054
     1055void testMoveDoubleConditionallyDoubleDestSameAsThenCase(MacroAssembler::DoubleCondition condition)
     1056{
     1057    double arg1 = 0;
     1058    double arg2 = 0;
     1059    double selectionA = 42.0;
     1060    double selectionB = 17.0;
     1061    double corruptedSelectionB = 66666;
     1062
     1063    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1064        emitFunctionPrologue(jit);
     1065
     1066        FPRReg destFPR = FPRInfo::returnValueFPR;
     1067        FPRReg selectionAFPR = destFPR;
     1068        FPRReg selectionBFPR = FPRInfo::fpRegT2;
     1069        FPRReg arg1FPR = FPRInfo::fpRegT3;
     1070        FPRReg arg2FPR = FPRInfo::fpRegT4;
     1071
     1072        RELEASE_ASSERT(destFPR == selectionAFPR);
     1073        RELEASE_ASSERT(destFPR != selectionBFPR);
     1074        RELEASE_ASSERT(destFPR != arg1FPR);
     1075        RELEASE_ASSERT(destFPR != arg2FPR);
     1076
     1077        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
     1078        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
     1079        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
     1080        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
     1081        jit.moveDoubleConditionallyDouble(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
     1082
     1083        FPRReg tempFPR = FPRInfo::fpRegT5;
     1084        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
     1085        auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
     1086        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
     1087        bIsUnchanged.link(&jit);
     1088
     1089        emitFunctionEpilogue(jit);
     1090        jit.ret();
     1091    });
     1092
     1093    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     1094}
     1095
     1096void testMoveDoubleConditionallyDoubleDestSameAsElseCase(MacroAssembler::DoubleCondition condition)
     1097{
     1098    double arg1 = 0;
     1099    double arg2 = 0;
     1100    double selectionA = 42.0;
     1101    double selectionB = 17.0;
     1102    double corruptedSelectionA = 55555;
     1103
     1104    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1105        emitFunctionPrologue(jit);
     1106
     1107        FPRReg destFPR = FPRInfo::returnValueFPR;
     1108        FPRReg selectionAFPR = FPRInfo::fpRegT1;
     1109        FPRReg selectionBFPR = destFPR;
     1110        FPRReg arg1FPR = FPRInfo::fpRegT3;
     1111        FPRReg arg2FPR = FPRInfo::fpRegT4;
     1112
     1113        RELEASE_ASSERT(destFPR != selectionAFPR);
     1114        RELEASE_ASSERT(destFPR == selectionBFPR);
     1115        RELEASE_ASSERT(destFPR != arg1FPR);
     1116        RELEASE_ASSERT(destFPR != arg2FPR);
     1117
     1118        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
     1119        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
     1120        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
     1121        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
     1122        jit.moveDoubleConditionallyDouble(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
     1123
     1124        FPRReg tempFPR = FPRInfo::fpRegT5;
     1125        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
     1126        auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
     1127        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
     1128        aIsUnchanged.link(&jit);
     1129
     1130        emitFunctionEpilogue(jit);
     1131        jit.ret();
     1132    });
     1133
     1134    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, doubleOperands(), selectionA, selectionB);
     1135}
     1136
     1137void testMoveDoubleConditionallyFloat(MacroAssembler::DoubleCondition condition)
     1138{
     1139    float arg1 = 0;
     1140    float arg2 = 0;
     1141    double selectionA = 42.0;
     1142    double selectionB = 17.0;
     1143    double corruptedSelectionA = 55555;
     1144    double corruptedSelectionB = 66666;
     1145
     1146    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1147        emitFunctionPrologue(jit);
     1148
     1149        FPRReg destFPR = FPRInfo::returnValueFPR;
     1150        FPRReg selectionAFPR = FPRInfo::fpRegT1;
     1151        FPRReg selectionBFPR = FPRInfo::fpRegT2;
     1152        FPRReg arg1FPR = FPRInfo::fpRegT3;
     1153        FPRReg arg2FPR = FPRInfo::fpRegT4;
     1154
     1155        RELEASE_ASSERT(destFPR != selectionAFPR);
     1156        RELEASE_ASSERT(destFPR != selectionBFPR);
     1157        RELEASE_ASSERT(destFPR != arg1FPR);
     1158        RELEASE_ASSERT(destFPR != arg2FPR);
     1159
     1160        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
     1161        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
     1162        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
     1163        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
     1164        jit.moveDoubleConditionallyFloat(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
     1165
     1166        FPRReg tempFPR = FPRInfo::fpRegT5;
     1167        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
     1168        auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
     1169        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
     1170        aIsUnchanged.link(&jit);
     1171
     1172        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
     1173        auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
     1174        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
     1175        bIsUnchanged.link(&jit);
     1176
     1177        emitFunctionEpilogue(jit);
     1178        jit.ret();
     1179    });
     1180
     1181    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     1182}
     1183
     1184void testMoveDoubleConditionallyFloatDestSameAsThenCase(MacroAssembler::DoubleCondition condition)
     1185{
     1186    float arg1 = 0;
     1187    float arg2 = 0;
     1188    double selectionA = 42.0;
     1189    double selectionB = 17.0;
     1190    double corruptedSelectionB = 66666;
     1191
     1192    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1193        emitFunctionPrologue(jit);
     1194
     1195        FPRReg destFPR = FPRInfo::returnValueFPR;
     1196        FPRReg selectionAFPR = destFPR;
     1197        FPRReg selectionBFPR = FPRInfo::fpRegT2;
     1198        FPRReg arg1FPR = FPRInfo::fpRegT3;
     1199        FPRReg arg2FPR = FPRInfo::fpRegT4;
     1200
     1201        RELEASE_ASSERT(destFPR == selectionAFPR);
     1202        RELEASE_ASSERT(destFPR != selectionBFPR);
     1203        RELEASE_ASSERT(destFPR != arg1FPR);
     1204        RELEASE_ASSERT(destFPR != arg2FPR);
     1205
     1206        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
     1207        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
     1208        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
     1209        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
     1210        jit.moveDoubleConditionallyFloat(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
     1211
     1212        FPRReg tempFPR = FPRInfo::fpRegT5;
     1213        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), tempFPR);
     1214        auto bIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionBFPR, tempFPR);
     1215        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionB), destFPR);
     1216        bIsUnchanged.link(&jit);
     1217
     1218        emitFunctionEpilogue(jit);
     1219        jit.ret();
     1220    });
     1221
     1222    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     1223}
     1224
     1225void testMoveDoubleConditionallyFloatDestSameAsElseCase(MacroAssembler::DoubleCondition condition)
     1226{
     1227    float arg1 = 0;
     1228    float arg2 = 0;
     1229    double selectionA = 42.0;
     1230    double selectionB = 17.0;
     1231    double corruptedSelectionA = 55555;
     1232
     1233    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1234        emitFunctionPrologue(jit);
     1235
     1236        FPRReg destFPR = FPRInfo::returnValueFPR;
     1237        FPRReg selectionAFPR = FPRInfo::fpRegT1;
     1238        FPRReg selectionBFPR = destFPR;
     1239        FPRReg arg1FPR = FPRInfo::fpRegT3;
     1240        FPRReg arg2FPR = FPRInfo::fpRegT4;
     1241
     1242        RELEASE_ASSERT(destFPR != selectionAFPR);
     1243        RELEASE_ASSERT(destFPR == selectionBFPR);
     1244        RELEASE_ASSERT(destFPR != arg1FPR);
     1245        RELEASE_ASSERT(destFPR != arg2FPR);
     1246
     1247        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), arg1FPR);
     1248        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg2), arg2FPR);
     1249        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), selectionAFPR);
     1250        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), selectionBFPR);
     1251        jit.moveDoubleConditionallyFloat(condition, arg1FPR, arg2FPR, selectionAFPR, selectionBFPR, destFPR);
     1252
     1253        FPRReg tempFPR = FPRInfo::fpRegT5;
     1254        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), tempFPR);
     1255        auto aIsUnchanged = jit.branchDouble(CCallHelpers::DoubleEqual, selectionAFPR, tempFPR);
     1256        jit.loadDouble(CCallHelpers::TrustedImmPtr(&corruptedSelectionA), destFPR);
     1257        aIsUnchanged.link(&jit);
     1258
     1259        emitFunctionEpilogue(jit);
     1260        jit.ret();
     1261    });
     1262
     1263    testMoveConditionallyFloatingPoint(condition, testCode, arg1, arg2, floatOperands(), selectionA, selectionB);
     1264}
     1265
     1266template<typename T, typename SelectionType>
     1267void testMoveConditionallyFloatingPointSameArg(MacroAssembler::DoubleCondition condition, const MacroAssemblerCodeRef<JSEntryPtrTag>& testCode, T& arg1, const Vector<T> operands, SelectionType selectionA, SelectionType selectionB)
     1268{
     1269    auto expectedResult = [&, condition] (T a) -> SelectionType {
     1270        auto isUnordered = [] (double x) {
     1271            return x != x;
     1272        };
     1273        switch (condition) {
     1274        case MacroAssembler::DoubleEqual:
     1275            return !isUnordered(a) && (a == a) ? selectionA : selectionB;
     1276        case MacroAssembler::DoubleNotEqual:
     1277            return !isUnordered(a) && (a != a) ? selectionA : selectionB;
     1278        case MacroAssembler::DoubleGreaterThan:
     1279            return !isUnordered(a) && (a > a) ? selectionA : selectionB;
     1280        case MacroAssembler::DoubleGreaterThanOrEqual:
     1281            return !isUnordered(a) && (a >= a) ? selectionA : selectionB;
     1282        case MacroAssembler::DoubleLessThan:
     1283            return !isUnordered(a) && (a < a) ? selectionA : selectionB;
     1284        case MacroAssembler::DoubleLessThanOrEqual:
     1285            return !isUnordered(a) && (a <= a) ? selectionA : selectionB;
     1286        case MacroAssembler::DoubleEqualOrUnordered:
     1287            return isUnordered(a) || (a == a) ? selectionA : selectionB;
     1288        case MacroAssembler::DoubleNotEqualOrUnordered:
     1289            return isUnordered(a) || (a != a) ? selectionA : selectionB;
     1290        case MacroAssembler::DoubleGreaterThanOrUnordered:
     1291            return isUnordered(a) || (a > a) ? selectionA : selectionB;
     1292        case MacroAssembler::DoubleGreaterThanOrEqualOrUnordered:
     1293            return isUnordered(a) || (a >= a) ? selectionA : selectionB;
     1294        case MacroAssembler::DoubleLessThanOrUnordered:
     1295            return isUnordered(a) || (a < a) ? selectionA : selectionB;
     1296        case MacroAssembler::DoubleLessThanOrEqualOrUnordered:
     1297            return isUnordered(a) || (a <= a) ? selectionA : selectionB;
     1298        } // switch
     1299    };
     1300
     1301    for (auto a : operands) {
     1302        arg1 = a;
     1303        CHECK_EQ(invoke<SelectionType>(testCode), expectedResult(a));
     1304    }
     1305}
     1306
     1307void testMoveConditionallyDouble2SameArg(MacroAssembler::DoubleCondition condition)
     1308{
     1309    double arg1 = 0;
     1310    unsigned selectionA = 42;
     1311    unsigned selectionB = 17;
     1312
     1313    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1314        emitFunctionPrologue(jit);
     1315
     1316        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     1317        RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
     1318        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     1319        jit.move(CCallHelpers::TrustedImm32(selectionB), GPRInfo::returnValueGPR);
     1320
     1321        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     1322        jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, GPRInfo::returnValueGPR);
     1323
     1324        emitFunctionEpilogue(jit);
     1325        jit.ret();
     1326    });
     1327
     1328    testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, doubleOperands(), selectionA, selectionB);
     1329}
     1330
     1331void testMoveConditionallyDouble3SameArg(MacroAssembler::DoubleCondition condition)
     1332{
     1333    double arg1 = 0;
     1334    unsigned selectionA = 42;
     1335    unsigned selectionB = 17;
     1336
     1337    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1338        emitFunctionPrologue(jit);
     1339
     1340        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     1341        GPRReg selectionBGPR = GPRInfo::argumentGPR3;
     1342        RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
     1343        RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionBGPR);
     1344        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     1345        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     1346        jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
     1347
     1348        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     1349        jit.moveConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, selectionBGPR, GPRInfo::returnValueGPR);
     1350
     1351        emitFunctionEpilogue(jit);
     1352        jit.ret();
     1353    });
     1354
     1355    testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, doubleOperands(), selectionA, selectionB);
     1356}
     1357
     1358void testMoveConditionallyFloat2SameArg(MacroAssembler::DoubleCondition condition)
     1359{
     1360    float arg1 = 0;
     1361    unsigned selectionA = 42;
     1362    unsigned selectionB = 17;
     1363
     1364    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1365        emitFunctionPrologue(jit);
     1366
     1367        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     1368        RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
     1369        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     1370        jit.move(CCallHelpers::TrustedImm32(selectionB), GPRInfo::returnValueGPR);
     1371
     1372        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     1373        jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, GPRInfo::returnValueGPR);
     1374
     1375        emitFunctionEpilogue(jit);
     1376        jit.ret();
     1377    });
     1378
     1379    testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, floatOperands(), selectionA, selectionB);
     1380}
     1381
     1382void testMoveConditionallyFloat3SameArg(MacroAssembler::DoubleCondition condition)
     1383{
     1384    float arg1 = 0;
     1385    unsigned selectionA = 42;
     1386    unsigned selectionB = 17;
     1387
     1388    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1389        emitFunctionPrologue(jit);
     1390
     1391        GPRReg selectionAGPR = GPRInfo::argumentGPR2;
     1392        GPRReg selectionBGPR = GPRInfo::argumentGPR3;
     1393        RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionAGPR);
     1394        RELEASE_ASSERT(GPRInfo::returnValueGPR != selectionBGPR);
     1395        jit.move(CCallHelpers::TrustedImm32(selectionA), selectionAGPR);
     1396        jit.move(CCallHelpers::TrustedImm32(selectionB), selectionBGPR);
     1397        jit.move(CCallHelpers::TrustedImm32(-1), GPRInfo::returnValueGPR);
     1398
     1399        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     1400        jit.moveConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, selectionAGPR, selectionBGPR, GPRInfo::returnValueGPR);
     1401
     1402        emitFunctionEpilogue(jit);
     1403        jit.ret();
     1404    });
     1405
     1406    testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, floatOperands(), selectionA, selectionB);
     1407}
     1408
     1409void testMoveDoubleConditionallyDoubleSameArg(MacroAssembler::DoubleCondition condition)
     1410{
     1411    double arg1 = 0;
     1412    double selectionA = 42.0;
     1413    double selectionB = 17.0;
     1414
     1415    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1416        emitFunctionPrologue(jit);
     1417
     1418        jit.loadDouble(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     1419        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), FPRInfo::fpRegT2);
     1420        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), FPRInfo::fpRegT3);
     1421        jit.moveDoubleConditionallyDouble(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, FPRInfo::fpRegT2, FPRInfo::fpRegT3, FPRInfo::returnValueFPR);
     1422
     1423        emitFunctionEpilogue(jit);
     1424        jit.ret();
     1425    });
     1426
     1427    testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, doubleOperands(), selectionA, selectionB);
     1428}
     1429
     1430void testMoveDoubleConditionallyFloatSameArg(MacroAssembler::DoubleCondition condition)
     1431{
     1432    float arg1 = 0;
     1433    double selectionA = 42.0;
     1434    double selectionB = 17.0;
     1435
     1436    auto testCode = compile([&, condition] (CCallHelpers& jit) {
     1437        emitFunctionPrologue(jit);
     1438
     1439        jit.loadFloat(CCallHelpers::TrustedImmPtr(&arg1), FPRInfo::fpRegT0);
     1440        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionA), FPRInfo::fpRegT2);
     1441        jit.loadDouble(CCallHelpers::TrustedImmPtr(&selectionB), FPRInfo::fpRegT3);
     1442        jit.moveDoubleConditionallyFloat(condition, FPRInfo::fpRegT0, FPRInfo::fpRegT0, FPRInfo::fpRegT2, FPRInfo::fpRegT3, FPRInfo::returnValueFPR);
     1443
     1444        emitFunctionEpilogue(jit);
     1445        jit.ret();
     1446    });
     1447
     1448    testMoveConditionallyFloatingPointSameArg(condition, testCode, arg1, floatOperands(), selectionA, selectionB);
     1449}
     1450
     1451#endif // CPU(X86_64) || CPU(ARM64)
    5901452
    5911453#if ENABLE(MASM_PROBE)
     
    13382200    RUN(testBranchTruncateDoubleToInt32(123, 123));
    13392201
    1340     RUN(testCompareDouble(MacroAssembler::DoubleEqual));
    1341     RUN(testCompareDouble(MacroAssembler::DoubleNotEqual));
    1342     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThan));
    1343     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqual));
    1344     RUN(testCompareDouble(MacroAssembler::DoubleLessThan));
    1345     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqual));
    1346     RUN(testCompareDouble(MacroAssembler::DoubleEqualOrUnordered));
    1347     RUN(testCompareDouble(MacroAssembler::DoubleNotEqualOrUnordered));
    1348     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrUnordered));
    1349     RUN(testCompareDouble(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
    1350     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrUnordered));
    1351     RUN(testCompareDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
     2202#define FOR_EACH_DOUBLE_CONDITION_RUN(__test) \
     2203    do { \
     2204        RUN(__test(MacroAssembler::DoubleEqual)); \
     2205        RUN(__test(MacroAssembler::DoubleNotEqual)); \
     2206        RUN(__test(MacroAssembler::DoubleGreaterThan)); \
     2207        RUN(__test(MacroAssembler::DoubleGreaterThanOrEqual)); \
     2208        RUN(__test(MacroAssembler::DoubleLessThan)); \
     2209        RUN(__test(MacroAssembler::DoubleLessThanOrEqual)); \
     2210        RUN(__test(MacroAssembler::DoubleEqualOrUnordered)); \
     2211        RUN(__test(MacroAssembler::DoubleNotEqualOrUnordered)); \
     2212        RUN(__test(MacroAssembler::DoubleGreaterThanOrUnordered)); \
     2213        RUN(__test(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered)); \
     2214        RUN(__test(MacroAssembler::DoubleLessThanOrUnordered)); \
     2215        RUN(__test(MacroAssembler::DoubleLessThanOrEqualOrUnordered)); \
     2216    } while (false)
     2217
     2218    FOR_EACH_DOUBLE_CONDITION_RUN(testCompareDouble);
     2219    FOR_EACH_DOUBLE_CONDITION_RUN(testCompareDoubleSameArg);
     2220
    13522221    RUN(testMul32WithImmediates());
    13532222
     
    13662235
    13672236#if CPU(X86) || CPU(X86_64) || CPU(ARM64)
    1368     RUN(testCompareFloat(MacroAssembler::DoubleEqual));
    1369     RUN(testCompareFloat(MacroAssembler::DoubleNotEqual));
    1370     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThan));
    1371     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqual));
    1372     RUN(testCompareFloat(MacroAssembler::DoubleLessThan));
    1373     RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqual));
    1374     RUN(testCompareFloat(MacroAssembler::DoubleEqualOrUnordered));
    1375     RUN(testCompareFloat(MacroAssembler::DoubleNotEqualOrUnordered));
    1376     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrUnordered));
    1377     RUN(testCompareFloat(MacroAssembler::DoubleGreaterThanOrEqualOrUnordered));
    1378     RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrUnordered));
    1379     RUN(testCompareFloat(MacroAssembler::DoubleLessThanOrEqualOrUnordered));
     2237    FOR_EACH_DOUBLE_CONDITION_RUN(testCompareFloat);
     2238#endif
     2239
     2240#if CPU(X86_64) || CPU(ARM64)
     2241    // Comparing 2 different registers.
     2242    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble2);
     2243    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3);
     2244    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3DestSameAsThenCase);
     2245    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3DestSameAsElseCase);
     2246    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat2);
     2247    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3);
     2248    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3DestSameAsThenCase);
     2249    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3DestSameAsElseCase);
     2250    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDouble);
     2251    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDoubleDestSameAsThenCase);
     2252    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDoubleDestSameAsElseCase);
     2253    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloat);
     2254    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloatDestSameAsThenCase);
     2255    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloatDestSameAsElseCase);
     2256
     2257    // Comparing the same register against itself.
     2258    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble2SameArg);
     2259    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyDouble3SameArg);
     2260    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat2SameArg);
     2261    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveConditionallyFloat3SameArg);
     2262    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyDoubleSameArg);
     2263    FOR_EACH_DOUBLE_CONDITION_RUN(testMoveDoubleConditionallyFloatSameArg);
    13802264#endif
    13812265
Note: See TracChangeset for help on using the changeset viewer.