⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 278846 in webkit


Ignore:
Timestamp:
Jun 14, 2021, 12:44:02 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Add Air opcode sub32/64(Reg, Imm, Reg) form for ARM64 and select this instruction in Air
​https://bugs.webkit.org/show_bug.cgi?id=226937

Patch by Yijia Huang <Yijia Huang> on 2021-06-14
Reviewed by Saam Barati.

Previously, Air arm64 sub32/64 utilize sub(Imm, Tmp) at optlevel = 0 and
add(Tmp, -Imm) at optlevel > 0 to perform and optimize sub(Tmp, Imm, Tmp).
The issue with this is that we were not eliding redundant operations.

For example:
B3 IR
@0 = Trunc(ArgumentReg(0))
@1 = Const
@2 = Sub(@0, @1)
@3 = Return(@2)

Old optimized Air IR
OptLevel = 0
Move %x0, %tmp1, @0
Move $Const, %tmp2, @1
Move %tmp1, %tmp0, @2 Redundant
Sub $Const, %tmp0, @2
Move %tmp0, %x0, @3
Ret32 %x0, @3

To remove those redundant instructions, Air arm64 sub32/64 opcode should
indicate a new form sub(Tmp, Imm, Tmp).

New optimized Air IR
OptLevel = 0
Move %x0, %tmp1, @0
Move $Const, %tmp2, @1
Sub %tmp1, $Const, %tmp0, @2
Move %tmp0, %x0, @3
Ret32 %x0, @3

  • assembler/MacroAssemblerARM64.h:

(JSC::MacroAssemblerARM64::sub32):
(JSC::MacroAssemblerARM64::sub64):

  • assembler/testmasm.cpp:

(JSC::testSub32Args):
(JSC::testSub32Imm):
(JSC::testSub32ArgImm):
(JSC::testSub64Imm32):
(JSC::testSub64ArgImm32):
(JSC::testSub64Imm64):
(JSC::testSub64ArgImm64):

  • b3/B3ReduceStrength.cpp:
  • b3/air/AirOpcode.opcodes:
  • b3/testb3.h:
  • b3/testb3_2.cpp:

(testSubArgs32ZeroExtend):

  • b3/testb3_3.cpp:

(addArgTests):

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r278830 r278846  
     12021-06-14  Yijia Huang  <yijia_huang@apple.com>
     2
     3        Add Air opcode sub32/64(Reg, Imm, Reg) form for ARM64 and select this instruction in Air
     4        https://bugs.webkit.org/show_bug.cgi?id=226937
     5
     6        Reviewed by Saam Barati.
     7
     8        Previously, Air arm64 sub32/64 utilize sub(Imm, Tmp) at optlevel = 0 and
     9        add(Tmp, -Imm) at optlevel > 0 to perform and optimize sub(Tmp, Imm, Tmp).
     10        The issue with this is that we were not eliding redundant operations.
     11
     12        For example:
     13        // B3 IR
     14        @0 = Trunc(ArgumentReg(0))
     15        @1 = Const
     16        @2 = Sub(@0, @1)
     17        @3 = Return(@2)
     18
     19        // Old optimized Air IR
     20        // OptLevel = 0
     21        Move    %x0, %tmp1, @0
     22        Move $Const, %tmp2, @1
     23        Move  %tmp1, %tmp0, @2 // Redundant
     24        Sub  $Const, %tmp0, @2
     25        Move  %tmp0,   %x0, @3
     26        Ret32   %x0,        @3
     27
     28        To remove those redundant instructions, Air arm64 sub32/64 opcode should
     29        indicate a new form sub(Tmp, Imm, Tmp).
     30
     31        // New optimized Air IR
     32        // OptLevel = 0
     33        Move    %x0,  %tmp1,        @0
     34        Move $Const,  %tmp2,        @1
     35        Sub   %tmp1, $Const, %tmp0, @2
     36        Move  %tmp0,    %x0,        @3
     37        Ret32   %x0,                @3
     38
     39        * assembler/MacroAssemblerARM64.h:
     40        (JSC::MacroAssemblerARM64::sub32):
     41        (JSC::MacroAssemblerARM64::sub64):
     42        * assembler/testmasm.cpp:
     43        (JSC::testSub32Args):
     44        (JSC::testSub32Imm):
     45        (JSC::testSub32ArgImm):
     46        (JSC::testSub64Imm32):
     47        (JSC::testSub64ArgImm32):
     48        (JSC::testSub64Imm64):
     49        (JSC::testSub64ArgImm64):
     50        * b3/B3ReduceStrength.cpp:
     51        * b3/air/AirOpcode.opcodes:
     52        * b3/testb3.h:
     53        * b3/testb3_2.cpp:
     54        (testSubArgs32ZeroExtend):
     55        * b3/testb3_3.cpp:
     56        (addArgTests):
     57
    1582021-06-14  Commit Queue  <commit-queue@webkit.org>
    259
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h

    r278340 r278846  
    894894    void sub32(TrustedImm32 imm, RegisterID dest)
    895895    {
    896         if (isUInt12(imm.m_value)) {
    897             m_assembler.sub<32>(dest, dest, UInt12(imm.m_value));
    898             return;
    899         }
    900         if (isUInt12(-imm.m_value)) {
    901             m_assembler.add<32>(dest, dest, UInt12(-imm.m_value));
     896        sub32(dest, imm, dest);
     897    }
     898
     899    void sub32(RegisterID left, TrustedImm32 imm, RegisterID dest)
     900    {
     901        intptr_t immediate = imm.m_value;
     902
     903        if (isUInt12(immediate)) {
     904            m_assembler.sub<32>(dest, left, UInt12(immediate));
     905            return;
     906        }
     907        if (isUInt12(-immediate)) {
     908            m_assembler.add<32>(dest, left, UInt12(-immediate));
    902909            return;
    903910        }
    904911
    905912        move(imm, getCachedDataTempRegisterIDAndInvalidate());
    906         m_assembler.sub<32>(dest, dest, dataTempRegister);
     913        m_assembler.sub<32>(dest, left, dataTempRegister);
    907914    }
    908915
    … …  
    955962    }
    956963
    957     void sub64(RegisterID a, RegisterID b, RegisterID dest)
    958     {
    959         m_assembler.sub<64>(dest, a, b);
    960     }
    961    
     964    void sub64(RegisterID left, RegisterID right, RegisterID dest)
     965    {
     966        m_assembler.sub<64>(dest, left, right);
     967    }
     968
    962969    void sub64(TrustedImm32 imm, RegisterID dest)
    963970    {
    964         if (isUInt12(imm.m_value)) {
    965             m_assembler.sub<64>(dest, dest, UInt12(imm.m_value));
    966             return;
    967         }
    968         if (isUInt12(-imm.m_value)) {
    969             m_assembler.add<64>(dest, dest, UInt12(-imm.m_value));
     971        sub64(dest, imm, dest);
     972    }
     973
     974    void sub64(RegisterID left, TrustedImm32 imm, RegisterID dest)
     975    {
     976        intptr_t immediate = imm.m_value;
     977
     978        if (isUInt12(immediate)) {
     979            m_assembler.sub<64>(dest, left, UInt12(immediate));
     980            return;
     981        }
     982        if (isUInt12(-immediate)) {
     983            m_assembler.add<64>(dest, left, UInt12(-immediate));
    970984            return;
    971985        }
    972986
    973987        signExtend32ToPtr(imm, getCachedDataTempRegisterIDAndInvalidate());
    974         m_assembler.sub<64>(dest, dest, dataTempRegister);
    975     }
    976    
     988        m_assembler.sub<64>(dest, left, dataTempRegister);
     989    }
     990
    977991    void sub64(TrustedImm64 imm, RegisterID dest)
    978992    {
     993        sub64(dest, imm, dest);
     994    }
     995
     996    void sub64(RegisterID left, TrustedImm64 imm, RegisterID dest)
     997    {
    979998        intptr_t immediate = imm.m_value;
    980999
    9811000        if (isUInt12(immediate)) {
    982             m_assembler.sub<64>(dest, dest, UInt12(static_cast<int32_t>(immediate)));
     1001            m_assembler.sub<64>(dest, left, UInt12(static_cast<int32_t>(immediate)));
    9831002            return;
    9841003        }
    9851004        if (isUInt12(-immediate)) {
    986             m_assembler.add<64>(dest, dest, UInt12(static_cast<int32_t>(-immediate)));
     1005            m_assembler.add<64>(dest, left, UInt12(static_cast<int32_t>(-immediate)));
    9871006            return;
    9881007        }
    9891008
    9901009        move(imm, getCachedDataTempRegisterIDAndInvalidate());
    991         m_assembler.sub<64>(dest, dest, dataTempRegister);
     1010        m_assembler.sub<64>(dest, left, dataTempRegister);
    9921011    }
    9931012
  • trunk/Source/JavaScriptCore/assembler/testmasm.cpp

    r278069 r278846  
    921921    }
    922922}
     923
     924void testSub32Args()
     925{
     926    for (auto value : int32Operands()) {
     927        auto sub = compile([=] (CCallHelpers& jit) {
     928            emitFunctionPrologue(jit);
     929
     930            jit.sub32(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::returnValueGPR);
     931
     932            emitFunctionEpilogue(jit);
     933            jit.ret();
     934        });
     935
     936        for (auto value2 : int32Operands())
     937            CHECK_EQ(invoke<uint32_t>(sub, value, value2), static_cast<uint32_t>(value - value2));
     938    }
     939}
     940
     941void testSub32Imm()
     942{
     943    for (auto immediate : int32Operands()) {
     944        for (auto immediate2 : int32Operands()) {
     945            auto sub = compile([=] (CCallHelpers& jit) {
     946                emitFunctionPrologue(jit);
     947
     948                jit.move(CCallHelpers::TrustedImm32(immediate), GPRInfo::returnValueGPR);
     949                jit.sub32(CCallHelpers::TrustedImm32(immediate2), GPRInfo::returnValueGPR);
     950
     951                emitFunctionEpilogue(jit);
     952                jit.ret();
     953            });
     954            CHECK_EQ(invoke<uint32_t>(sub), static_cast<uint32_t>(immediate - immediate2));
     955        }
     956    }
     957}
     958
     959void testSub32ArgImm()
     960{
     961    for (auto immediate : int32Operands()) {
     962        auto sub = compile([=] (CCallHelpers& jit) {
     963            emitFunctionPrologue(jit);
     964
     965            jit.sub32(GPRInfo::argumentGPR0, CCallHelpers::TrustedImm32(immediate), GPRInfo::returnValueGPR);
     966
     967            emitFunctionEpilogue(jit);
     968            jit.ret();
     969        });
     970
     971        for (auto value : int32Operands())
     972            CHECK_EQ(invoke<uint32_t>(sub, value), static_cast<uint32_t>(value - immediate));
     973    }
     974}
     975
     976void testSub64Imm32()
     977{
     978    for (auto immediate : int64Operands()) {
     979        for (auto immediate2 : int32Operands()) {
     980            auto sub = compile([=] (CCallHelpers& jit) {
     981                emitFunctionPrologue(jit);
     982
     983                jit.move(CCallHelpers::TrustedImm64(immediate), GPRInfo::returnValueGPR);
     984                jit.sub64(CCallHelpers::TrustedImm32(immediate2), GPRInfo::returnValueGPR);
     985
     986                emitFunctionEpilogue(jit);
     987                jit.ret();
     988            });
     989            CHECK_EQ(invoke<uint64_t>(sub), static_cast<uint64_t>(immediate - immediate2));
     990        }
     991    }
     992}
     993
     994void testSub64ArgImm32()
     995{
     996    for (auto immediate : int32Operands()) {
     997        auto sub = compile([=] (CCallHelpers& jit) {
     998            emitFunctionPrologue(jit);
     999
     1000            jit.sub64(GPRInfo::argumentGPR0, CCallHelpers::TrustedImm32(immediate), GPRInfo::returnValueGPR);
     1001
     1002            emitFunctionEpilogue(jit);
     1003            jit.ret();
     1004        });
     1005
     1006        for (auto value : int64Operands())
     1007            CHECK_EQ(invoke<int64_t>(sub, value), static_cast<int64_t>(value - immediate));
     1008    }
     1009}
     1010
     1011void testSub64Imm64()
     1012{
     1013    for (auto immediate : int64Operands()) {
     1014        for (auto immediate2 : int64Operands()) {
     1015            auto sub = compile([=] (CCallHelpers& jit) {
     1016                emitFunctionPrologue(jit);
     1017
     1018                jit.move(CCallHelpers::TrustedImm64(immediate), GPRInfo::returnValueGPR);
     1019                jit.sub64(CCallHelpers::TrustedImm64(immediate2), GPRInfo::returnValueGPR);
     1020
     1021                emitFunctionEpilogue(jit);
     1022                jit.ret();
     1023            });
     1024            CHECK_EQ(invoke<uint64_t>(sub), static_cast<uint64_t>(immediate - immediate2));
     1025        }
     1026    }
     1027}
     1028
     1029void testSub64ArgImm64()
     1030{
     1031    for (auto immediate : int64Operands()) {
     1032        auto sub = compile([=] (CCallHelpers& jit) {
     1033            emitFunctionPrologue(jit);
     1034
     1035            jit.sub64(GPRInfo::argumentGPR0, CCallHelpers::TrustedImm64(immediate), GPRInfo::returnValueGPR);
     1036
     1037            emitFunctionEpilogue(jit);
     1038            jit.ret();
     1039        });
     1040
     1041        for (auto value : int64Operands())
     1042            CHECK_EQ(invoke<int64_t>(sub, value), static_cast<int64_t>(value - immediate));
     1043    }
     1044}
    9231045#endif
    9241046
    … …  
    26412763#if CPU(ARM64)
    26422764    RUN(testMul32SignExtend());
     2765    RUN(testSub32Args());
     2766    RUN(testSub32Imm());
     2767    RUN(testSub32ArgImm());
     2768    RUN(testSub64Imm32());
     2769    RUN(testSub64ArgImm32());
     2770    RUN(testSub64Imm64());
     2771    RUN(testSub64ArgImm64());
    26432772#endif
    26442773
  • trunk/Source/JavaScriptCore/b3/B3ReduceStrength.cpp

    r276524 r278846  
    634634                    break;
    635635                }
    636                
     636
    637637                // Turn this: Sub(0, value)
    638638                // Into this: Neg(value)
  • trunk/Source/JavaScriptCore/b3/air/AirOpcode.opcodes

    r278769 r278846  
    180180arm64: Sub32 U:G:32, U:G:32, ZD:G:32
    181181    Tmp, Tmp, Tmp
     182    Tmp, Imm, Tmp
    182183
    18318464: Sub64 U:G:64, UD:G:64
    … …  
    193194arm64: Sub64 U:G:64, U:G:64, D:G:64
    194195    Tmp, Tmp, Tmp
     196    Tmp, Imm, Tmp
    195197
    196198SubDouble U:F:64, U:F:64, D:F:64
  • trunk/Source/JavaScriptCore/b3/testb3.h

    r278381 r278846  
    10281028void testSubMemImm(int64_t, int64_t);
    10291029void testSubArgs32(int, int);
     1030void testSubArgs32ZeroExtend(int, int);
    10301031void testSubArgImm32(int, int);
    10311032void testSubImmArg32(int, int);
  • trunk/Source/JavaScriptCore/b3/testb3_2.cpp

    r249747 r278846  
    20912091
    20922092    CHECK(compileAndRun<int>(proc, a, b) == a - b);
     2093}
     2094
     2095void testSubArgs32ZeroExtend(int a, int b)
     2096{
     2097    Procedure proc;
     2098    if (proc.optLevel() < 1)
     2099        return;
     2100    BasicBlock* root = proc.addBlock();
     2101    root->appendNewControlValue(
     2102        proc, Return, Origin(),
     2103        root->appendNew<Value>(
     2104            proc, ZExt32, Origin(),
     2105            root->appendNew<Value>(
     2106                proc, Sub, Origin(),
     2107                root->appendNew<Value>(
     2108                    proc, Trunc, Origin(),
     2109                    root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0)),
     2110                root->appendNew<Value>(
     2111                    proc, Trunc, Origin(),
     2112                    root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)))));
     2113
     2114    CHECK(compileAndRun<uint64_t>(proc, a, b) == static_cast<uint64_t>(static_cast<uint32_t>(a - b)));
    20932115}
    20942116
  • trunk/Source/JavaScriptCore/b3/testb3_3.cpp

    r275800 r278846  
    33023302    RUN(testSubArgs32(13, -42));
    33033303    RUN(testSubArgs32(-13, 42));
     3304    RUN(testSubArgs32ZeroExtend(1, 1));
     3305    RUN(testSubArgs32ZeroExtend(1, 2));
     3306    RUN(testSubArgs32ZeroExtend(13, -42));
     3307    RUN(testSubArgs32ZeroExtend(-13, 42));
    33043308    RUN(testSubArgImm32(1, 1));
    33053309    RUN(testSubArgImm32(1, 2));
Note: See TracChangeset for help on using the changeset viewer.