Title: [279075] trunk/Source/_javascript_Core
Revision
279075
Author
commit-qu...@webkit.org
Date
2021-06-21 11:55:59 -0700 (Mon, 21 Jun 2021)

Log Message

Add a new pattern to instruction selector to utilize SMSUBL supported by ARM64
https://bugs.webkit.org/show_bug.cgi?id=227195

Patch by Yijia Huang <yijia_hu...@apple.com> on 2021-06-21
Reviewed by Keith Miller.

Signed Multiply-Subtract Long(SMSUBL), supported by ARM64, multiplies two
32-bit register values, subtracts the product from a 64-bit register value,
and writes the result 64-bit destination register. The instruction selector
can utilize this to lowering certain patterns in B3 IR before further Air
optimization. Given the operation:

smsubl d, n, m, a

The equivalent pattern would be:

d = a - SExt32(n) * SExt32(m)

Given B3 IR:
Int @0 = ArgumentReg(%x0)
Int @1 = SExt32(Trunc(ArgumentReg(%x1)))
Int @2 = SExt32(Trunc(ArgumentReg(%x2)))
Int @3 = Mul(@1, @2)
Int @4 = Sub(@0, @3)
Void@5 = Return(@4, Terminal)

Before Adding SMSUBL:
// Old optimized AIR
SignExtend32ToPtr  %x1, %x1,           @1
SignExtend32ToPtr  %x2, %x2,           @2
MultiplySub64      %x1, %x2, %x0, %x0, @4
Ret64              %x0,                @5

After Adding SMSUBL:
// New optimized AIR
MultiplySubSignExtend32 %x1, %x2, %x0, %x0, @4
Ret64                   %x0,                @5

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::multiplySubSignExtend32):
* assembler/testmasm.cpp:
(JSC::testMulSubSignExtend32):
* b3/B3LowerToAir.cpp:
* b3/air/AirOpcode.opcodes:
* b3/testb3.h:
* b3/testb3_2.cpp:
(testMulSubArgsLeft):
(testMulSubArgsRight):
(testMulSubArgsLeft32):
(testMulSubArgsRight32):
(testMulSubSignExtend32Args):
* b3/testb3_3.cpp:
(addArgTests):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (279074 => 279075)


--- trunk/Source/_javascript_Core/ChangeLog	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-06-21 18:55:59 UTC (rev 279075)
@@ -1,3 +1,58 @@
+2021-06-21  Yijia Huang  <yijia_hu...@apple.com>
+
+        Add a new pattern to instruction selector to utilize SMSUBL supported by ARM64
+        https://bugs.webkit.org/show_bug.cgi?id=227195
+
+        Reviewed by Keith Miller.
+
+        Signed Multiply-Subtract Long(SMSUBL), supported by ARM64, multiplies two 
+        32-bit register values, subtracts the product from a 64-bit register value, 
+        and writes the result 64-bit destination register. The instruction selector 
+        can utilize this to lowering certain patterns in B3 IR before further Air 
+        optimization. Given the operation:
+
+        smsubl d, n, m, a
+
+        The equivalent pattern would be:
+
+        d = a - SExt32(n) * SExt32(m)
+
+        Given B3 IR:
+        Int @0 = ArgumentReg(%x0)
+        Int @1 = SExt32(Trunc(ArgumentReg(%x1)))
+        Int @2 = SExt32(Trunc(ArgumentReg(%x2)))
+        Int @3 = Mul(@1, @2)
+        Int @4 = Sub(@0, @3)
+        Void@5 = Return(@4, Terminal)
+
+        Before Adding SMSUBL:
+        // Old optimized AIR
+        SignExtend32ToPtr  %x1, %x1,           @1
+        SignExtend32ToPtr  %x2, %x2,           @2
+        MultiplySub64      %x1, %x2, %x0, %x0, @4
+        Ret64              %x0,                @5
+
+        After Adding SMSUBL:
+        // New optimized AIR
+        MultiplySubSignExtend32 %x1, %x2, %x0, %x0, @4
+        Ret64                   %x0,                @5
+
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::multiplySubSignExtend32):
+        * assembler/testmasm.cpp:
+        (JSC::testMulSubSignExtend32):
+        * b3/B3LowerToAir.cpp:
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.h:
+        * b3/testb3_2.cpp:
+        (testMulSubArgsLeft):
+        (testMulSubArgsRight):
+        (testMulSubArgsLeft32):
+        (testMulSubArgsRight32):
+        (testMulSubSignExtend32Args):
+        * b3/testb3_3.cpp:
+        (addArgTests):
+
 2021-06-21  Kimmo Kinnunen  <kkinnu...@apple.com>
 
         makeUnique cannot be used to instantiate function-local classes

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (279074 => 279075)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2021-06-21 18:55:59 UTC (rev 279075)
@@ -632,6 +632,11 @@
         m_assembler.msub<64>(dest, mulLeft, mulRight, minuend);
     }
 
+    void multiplySubSignExtend32(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
+    {
+        m_assembler.smsubl(dest, mulLeft, mulRight, minuend);
+    }
+
     void multiplyNeg64(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
     {
         m_assembler.msub<64>(dest, mulLeft, mulRight, ARM64Registers::zr);

Modified: trunk/Source/_javascript_Core/assembler/testmasm.cpp (279074 => 279075)


--- trunk/Source/_javascript_Core/assembler/testmasm.cpp	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/assembler/testmasm.cpp	2021-06-21 18:55:59 UTC (rev 279075)
@@ -1067,6 +1067,29 @@
     }
 }
 
+void testMulSubSignExtend32()
+{
+    // d = a - SExt32(n) *  SExt32(m)
+    auto sub = compile([=] (CCallHelpers& jit) {
+        emitFunctionPrologue(jit);
+
+        jit.multiplySubSignExtend32(GPRInfo::argumentGPR1, 
+            GPRInfo::argumentGPR2,
+            GPRInfo::argumentGPR0, 
+            GPRInfo::returnValueGPR);
+
+        emitFunctionEpilogue(jit);
+        jit.ret();
+    });
+
+    for (auto a : int64Operands()) {
+        for (auto n : int32Operands()) {
+            for (auto m : int32Operands())
+                CHECK_EQ(invoke<int64_t>(sub, a, n, m), a - static_cast<int64_t>(n) * static_cast<int64_t>(m));
+        }
+    }
+}
+
 void testUbfx64()
 {
     uint64_t src = ""
@@ -3254,6 +3277,7 @@
     RUN(testSub64ArgImm32());
     RUN(testSub64Imm64());
     RUN(testSub64ArgImm64());
+    RUN(testMulSubSignExtend32());
     RUN(testUbfx32());
     RUN(testUbfx64());
 #endif

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (279074 => 279075)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2021-06-21 18:55:59 UTC (rev 279075)
@@ -2583,24 +2583,51 @@
                 && isValidForm(multiplySubOpcode, Arg::Tmp, Arg::Tmp, Arg::Tmp, Arg::Tmp)) {
                 Value* left = m_value->child(0);
                 Value* right = m_value->child(1);
-                if (!imm(right) || m_valueToTmp[right]) {
-                    auto tryAppendMultiplySub = [&] () -> bool {
-                        if (right->opcode() != Mul || !canBeInternal(right))
-                            return false;
+                auto tryMultiply = [&] (Value* v) -> bool {
+                    if (v->opcode() != Mul || !canBeInternal(v))
+                        return false;
+                    if (m_locked.contains(v->child(0)) || m_locked.contains(v->child(1)))
+                        return false;
+                    return true;
+                };
 
-                        Value* multiplyLeft = right->child(0);
-                        Value* multiplyRight = right->child(1);
-                        if (m_locked.contains(multiplyLeft) || m_locked.contains(multiplyRight))
-                            return false;
+                // MSUB: d = a - n * m
+                if ((!imm(right) || m_valueToTmp[right]) && tryMultiply(right)) {
+                    Value* multiplyLeft = right->child(0);
+                    Value* multiplyRight = right->child(1);
 
-                        append(multiplySubOpcode, tmp(multiplyLeft), tmp(multiplyRight), tmp(left), tmp(m_value));
-                        commitInternal(right);
+                    // SMSUBL: d = a - SExt32(n) *  SExt32(m)
+                    if (multiplySubOpcode == MultiplySub64
+                        && isValidForm(MultiplySubSignExtend32, Arg::Tmp, Arg::Tmp, Arg::Tmp, Arg::Tmp)) {
+                        auto trySExt32 = [&] (Value* v) {
+                            if (v->opcode() != SExt32 || !canBeInternal(v))
+                                return false;
+                            if (m_locked.contains(v->child(0)))
+                                return false;
+                            return true;
+                        };
 
-                        return true;
-                    };
+                        auto tryAppendMultiplySubSignExtend32 = [&] () -> bool {
+                            if (!trySExt32(multiplyLeft) || !trySExt32(multiplyRight))
+                                return false;
+                            append(MultiplySubSignExtend32, 
+                                tmp(multiplyLeft->child(0)), 
+                                tmp(multiplyRight->child(0)), 
+                                tmp(left), 
+                                tmp(m_value));
+                            commitInternal(right);
+                            commitInternal(multiplyLeft);
+                            commitInternal(multiplyRight);
+                            return true;
+                        };
 
-                    if (tryAppendMultiplySub())
-                        return;
+                        if (tryAppendMultiplySubSignExtend32())
+                            return;
+                    }
+
+                    append(multiplySubOpcode, tmp(multiplyLeft), tmp(multiplyRight), tmp(left), tmp(m_value));
+                    commitInternal(right);
+                    return;
                 }
             }
 

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (279074 => 279075)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2021-06-21 18:55:59 UTC (rev 279075)
@@ -257,6 +257,9 @@
 arm64: MultiplySub64 U:G:64, U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp, Tmp
 
+arm64: MultiplySubSignExtend32 U:G:32, U:G:32, U:G:64, D:G:64
+    Tmp, Tmp, Tmp, Tmp
+
 arm64: MultiplyNeg32 U:G:32, U:G:32, ZD:G:32
     Tmp, Tmp, Tmp
 

Modified: trunk/Source/_javascript_Core/b3/testb3.h (279074 => 279075)


--- trunk/Source/_javascript_Core/b3/testb3.h	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/b3/testb3.h	2021-06-21 18:55:59 UTC (rev 279075)
@@ -876,6 +876,7 @@
 void testMulSubArgsRight();
 void testMulSubArgsLeft32();
 void testMulSubArgsRight32();
+void testMulSubSignExtend32Args();
 void testMulNegArgs();
 void testMulNegArgs32();
 void testMulArgDouble(double);

Modified: trunk/Source/_javascript_Core/b3/testb3_2.cpp (279074 => 279075)


--- trunk/Source/_javascript_Core/b3/testb3_2.cpp	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/b3/testb3_2.cpp	2021-06-21 18:55:59 UTC (rev 279075)
@@ -1102,17 +1102,18 @@
     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
-    Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
-    root->appendNewControlValue(proc, Return, Origin(), added);
+    Value* subtracted = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
+    root->appendNewControlValue(proc, Return, Origin(), subtracted);
 
     auto code = compileProc(proc);
+    if (isARM64())
+        checkDoesNotUseInstruction(*code, "msub");
 
     auto testValues = int64Operands();
     for (auto a : testValues) {
         for (auto b : testValues) {
-            for (auto c : testValues) {
+            for (auto c : testValues)
                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
-            }
         }
     }
 }
@@ -1126,17 +1127,18 @@
     Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
     Value* arg2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
-    Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
-    root->appendNewControlValue(proc, Return, Origin(), added);
+    Value* subtracted = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
+    root->appendNewControlValue(proc, Return, Origin(), subtracted);
 
     auto code = compileProc(proc);
+    if (isARM64())
+        checkUsesInstruction(*code, "msub");
 
     auto testValues = int64Operands();
     for (auto a : testValues) {
         for (auto b : testValues) {
-            for (auto c : testValues) {
+            for (auto c : testValues)
                 CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
-            }
         }
     }
 }
@@ -1153,17 +1155,18 @@
     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
-    Value* added = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
-    root->appendNewControlValue(proc, Return, Origin(), added);
+    Value* subtracted = root->appendNew<Value>(proc, Sub, Origin(), multiplied, arg2);
+    root->appendNewControlValue(proc, Return, Origin(), subtracted);
 
     auto code = compileProc(proc);
+    if (isARM64())
+        checkDoesNotUseInstruction(*code, "msub");
 
     auto testValues = int32Operands();
     for (auto a : testValues) {
         for (auto b : testValues) {
-            for (auto c : testValues) {
+            for (auto c : testValues)
                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
-            }
         }
     }
 }
@@ -1180,16 +1183,54 @@
     Value* arg2 = root->appendNew<Value>(proc, Trunc, Origin(),
         root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
     Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg1, arg2);
-    Value* added = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
-    root->appendNewControlValue(proc, Return, Origin(), added);
+    Value* subtracted = root->appendNew<Value>(proc, Sub, Origin(), arg0, multiplied);
+    root->appendNewControlValue(proc, Return, Origin(), subtracted);
 
     auto code = compileProc(proc);
+    if (isARM64())
+        checkUsesInstruction(*code, "msub");
 
     auto testValues = int32Operands();
     for (auto a : testValues) {
         for (auto b : testValues) {
-            for (auto c : testValues) {
+            for (auto c : testValues)
                 CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
+        }
+    }
+}
+
+void testMulSubSignExtend32Args()
+{
+    // d = a - SExt32(n) * SExt32(m)
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* aValue = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* nValue = root->appendNew<Value>(
+        proc, SExt32, Origin(),
+        root->appendNew<Value>(
+            proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1)));
+    Value* mValue = root->appendNew<Value>(
+        proc, SExt32, Origin(),
+        root->appendNew<Value>(
+            proc, Trunc, Origin(),
+            root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2)));
+
+    Value* mulValue = root->appendNew<Value>(proc, Mul, Origin(), nValue, mValue);
+    Value* subValue = root->appendNew<Value>(proc, Sub, Origin(), aValue, mulValue);
+    root->appendNewControlValue(proc, Return, Origin(), subValue);
+
+    auto code = compileProc(proc);
+    if (isARM64())
+        checkUsesInstruction(*code, "smsubl");
+
+    for (auto a : int64Operands()) {
+        for (auto n : int32Operands()) {
+            for (auto m : int32Operands()) {
+                int64_t lhs = invoke<int64_t>(*code, a.value, n.value, m.value);
+                int64_t rhs = a.value - static_cast<int64_t>(n.value) * static_cast<int64_t>(m.value);
+                CHECK(lhs == rhs);
             }
         }
     }

Modified: trunk/Source/_javascript_Core/b3/testb3_3.cpp (279074 => 279075)


--- trunk/Source/_javascript_Core/b3/testb3_3.cpp	2021-06-21 18:50:08 UTC (rev 279074)
+++ trunk/Source/_javascript_Core/b3/testb3_3.cpp	2021-06-21 18:55:59 UTC (rev 279075)
@@ -3200,6 +3200,7 @@
     RUN(testMulSubArgsRight());
     RUN(testMulSubArgsLeft32());
     RUN(testMulSubArgsRight32());
+    RUN(testMulSubSignExtend32Args());
     RUN(testMulNegArgs());
     RUN(testMulNegArgs32());
     
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to