Title: [197763] releases/WebKitGTK/webkit-2.12/Source/_javascript_Core
Revision
197763
Author
[email protected]
Date
2016-03-08 06:50:15 -0800 (Tue, 08 Mar 2016)

Log Message

Merge r197546 - [JSC] Add support for MADD, MSUB and MNEG to Air
https://bugs.webkit.org/show_bug.cgi?id=154997

Patch by Benjamin Poulain <[email protected]> on 2016-03-03
Reviewed by Filip Pizlo.

ARM64 can do an Add/Sub in the Multiply units.
LLVM was doing so but we lost that when switching to B3.

This patch adds those instructions in Air.

There are more ALUs than multiply units, thus we are more
likely to successfully schedule a Multiply+Add than 2 Multiply.
I am conservative and only emit a multiply-add if the value
can be interned. As far as I can tell from what is generated
by LLVM, that backend had the same rule.

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::multiplyAdd32):
(JSC::MacroAssemblerARM64::multiplySub32):
(JSC::MacroAssemblerARM64::multiplyNeg32):
(JSC::MacroAssemblerARM64::multiplyAdd64):
(JSC::MacroAssemblerARM64::multiplySub64):
(JSC::MacroAssemblerARM64::multiplyNeg64):
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::populateWithInterestingValues):
(JSC::B3::floatingPointOperands):
(JSC::B3::int64Operands):
(JSC::B3::int32Operands):
(JSC::B3::testMulAddArgsLeft):
(JSC::B3::testMulAddArgsRight):
(JSC::B3::testMulAddArgsLeft32):
(JSC::B3::testMulAddArgsRight32):
(JSC::B3::testMulSubArgsLeft):
(JSC::B3::testMulSubArgsRight):
(JSC::B3::testMulSubArgsLeft32):
(JSC::B3::testMulSubArgsRight32):
(JSC::B3::testMulNegArgs):
(JSC::B3::testMulNegArgs32):
(JSC::B3::run):

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/ChangeLog (197762 => 197763)


--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/ChangeLog	2016-03-08 14:28:40 UTC (rev 197762)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/ChangeLog	2016-03-08 14:50:15 UTC (rev 197763)
@@ -1,3 +1,48 @@
+2016-03-03  Benjamin Poulain  <[email protected]>
+
+        [JSC] Add support for MADD, MSUB and MNEG to Air
+        https://bugs.webkit.org/show_bug.cgi?id=154997
+
+        Reviewed by Filip Pizlo.
+
+        ARM64 can do an Add/Sub in the Multiply units.
+        LLVM was doing so but we lost that when switching to B3.
+
+        This patch adds those instructions in Air.
+
+        There are more ALUs than multiply units, thus we are more
+        likely to successfully schedule a Multiply+Add than 2 Multiply.
+        I am conservative and only emit a multiply-add if the value
+        can be interned. As far as I can tell from what is generated
+        by LLVM, that backend had the same rule.
+
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::multiplyAdd32):
+        (JSC::MacroAssemblerARM64::multiplySub32):
+        (JSC::MacroAssemblerARM64::multiplyNeg32):
+        (JSC::MacroAssemblerARM64::multiplyAdd64):
+        (JSC::MacroAssemblerARM64::multiplySub64):
+        (JSC::MacroAssemblerARM64::multiplyNeg64):
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::populateWithInterestingValues):
+        (JSC::B3::floatingPointOperands):
+        (JSC::B3::int64Operands):
+        (JSC::B3::int32Operands):
+        (JSC::B3::testMulAddArgsLeft):
+        (JSC::B3::testMulAddArgsRight):
+        (JSC::B3::testMulAddArgsLeft32):
+        (JSC::B3::testMulAddArgsRight32):
+        (JSC::B3::testMulSubArgsLeft):
+        (JSC::B3::testMulSubArgsRight):
+        (JSC::B3::testMulSubArgsLeft32):
+        (JSC::B3::testMulSubArgsRight32):
+        (JSC::B3::testMulNegArgs):
+        (JSC::B3::testMulNegArgs32):
+        (JSC::B3::run):
+
 2016-03-03  Filip Pizlo  <[email protected]>
 
         Octane/regexp's Exec function should benefit from array length accessor inlining

Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (197762 => 197763)


--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2016-03-08 14:28:40 UTC (rev 197762)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2016-03-08 14:50:15 UTC (rev 197763)
@@ -487,6 +487,36 @@
         m_assembler.mul<64>(dest, left, right);
     }
 
+    void multiplyAdd32(RegisterID mulLeft, RegisterID mulRight, RegisterID summand, RegisterID dest)
+    {
+        m_assembler.madd<32>(dest, mulLeft, mulRight, summand);
+    }
+
+    void multiplySub32(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
+    {
+        m_assembler.msub<32>(dest, mulLeft, mulRight, minuend);
+    }
+
+    void multiplyNeg32(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
+    {
+        m_assembler.msub<32>(dest, mulLeft, mulRight, ARM64Registers::zr);
+    }
+
+    void multiplyAdd64(RegisterID mulLeft, RegisterID mulRight, RegisterID summand, RegisterID dest)
+    {
+        m_assembler.madd<64>(dest, mulLeft, mulRight, summand);
+    }
+
+    void multiplySub64(RegisterID mulLeft, RegisterID mulRight, RegisterID minuend, RegisterID dest)
+    {
+        m_assembler.msub<64>(dest, mulLeft, mulRight, minuend);
+    }
+
+    void multiplyNeg64(RegisterID mulLeft, RegisterID mulRight, RegisterID dest)
+    {
+        m_assembler.msub<64>(dest, mulLeft, mulRight, ARM64Registers::zr);
+    }
+
     void div32(RegisterID dividend, RegisterID divisor, RegisterID dest)
     {
         m_assembler.sdiv<32>(dest, dividend, divisor);

Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/B3LowerToAir.cpp (197762 => 197763)


--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-03-08 14:28:40 UTC (rev 197762)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-03-08 14:50:15 UTC (rev 197763)
@@ -1704,17 +1704,86 @@
         }
 
         case Add: {
+            Air::Opcode multiplyAddOpcode = tryOpcodeForType(MultiplyAdd32, MultiplyAdd64, m_value->type());
+            if (multiplyAddOpcode != Air::Oops
+                && isValidForm(multiplyAddOpcode, 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 tryAppendMultiplyAdd = [&] (Value* left, Value* right) -> bool {
+                        if (left->opcode() != Mul || !canBeInternal(left))
+                            return false;
+
+                        Value* multiplyLeft = left->child(0);
+                        Value* multiplyRight = left->child(1);
+                        if (m_locked.contains(multiplyLeft) || m_locked.contains(multiplyRight))
+                            return false;
+
+                        append(multiplyAddOpcode, tmp(multiplyLeft), tmp(multiplyRight), tmp(right), tmp(m_value));
+                        commitInternal(left);
+
+                        return true;
+                    };
+
+                    if (tryAppendMultiplyAdd(left, right))
+                        return;
+                    if (tryAppendMultiplyAdd(right, left))
+                        return;
+                }
+            }
+
             appendBinOp<Add32, Add64, AddDouble, AddFloat, Commutative>(
                 m_value->child(0), m_value->child(1));
             return;
         }
 
         case Sub: {
+            Air::Opcode multiplySubOpcode = tryOpcodeForType(MultiplySub32, MultiplySub64, m_value->type());
+            if (multiplySubOpcode != Air::Oops
+                && 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;
+
+                        Value* multiplyLeft = right->child(0);
+                        Value* multiplyRight = right->child(1);
+                        if (m_locked.contains(multiplyLeft) || m_locked.contains(multiplyRight))
+                            return false;
+
+                        append(multiplySubOpcode, tmp(multiplyLeft), tmp(multiplyRight), tmp(left), tmp(m_value));
+                        commitInternal(right);
+
+                        return true;
+                    };
+
+                    if (tryAppendMultiplySub())
+                        return;
+                }
+            }
+
             appendBinOp<Sub32, Sub64, SubDouble, SubFloat>(m_value->child(0), m_value->child(1));
             return;
         }
 
         case Neg: {
+            Air::Opcode multiplyNegOpcode = tryOpcodeForType(MultiplyNeg32, MultiplyNeg64, m_value->type());
+            if (multiplyNegOpcode != Air::Oops
+                && isValidForm(multiplyNegOpcode, Arg::Tmp, Arg::Tmp, Arg::Tmp)
+                && m_value->child(0)->opcode() == Mul
+                && canBeInternal(m_value->child(0))) {
+                Value* multiplyOperation = m_value->child(0);
+                Value* multiplyLeft = multiplyOperation->child(0);
+                Value* multiplyRight = multiplyOperation->child(1);
+                if (!m_locked.contains(multiplyLeft) && !m_locked.contains(multiplyRight)) {
+                    append(multiplyNegOpcode, tmp(multiplyLeft), tmp(multiplyRight), tmp(m_value));
+                    commitInternal(multiplyOperation);
+                    return;
+                }
+            }
+
             appendUnOp<Neg32, Neg64, NegateDouble, Air::Oops>(m_value->child(0));
             return;
         }

Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/air/AirOpcode.opcodes (197762 => 197763)


--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2016-03-08 14:28:40 UTC (rev 197762)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2016-03-08 14:50:15 UTC (rev 197763)
@@ -215,6 +215,24 @@
 Mul64 U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp
 
+arm64: MultiplyAdd32 U:G:32, U:G:32, U:G:32, ZD:G:32
+    Tmp, Tmp, Tmp, Tmp
+
+arm64: MultiplyAdd64 U:G:64, U:G:64, U:G:64, D:G:64
+    Tmp, Tmp, Tmp, Tmp
+
+arm64: MultiplySub32 U:G:32, U:G:32, U:G:32, ZD:G:32
+    Tmp, Tmp, Tmp, Tmp
+
+arm64: MultiplySub64 U:G:64, U:G:64, U:G:64, D:G:64
+    Tmp, Tmp, Tmp, Tmp
+
+arm64: MultiplyNeg32 U:G:32, U:G:32, ZD:G:32
+    Tmp, Tmp, Tmp
+
+arm64: MultiplyNeg64 U:G:64, U:G:64, ZD:G:64
+    Tmp, Tmp, Tmp
+
 arm64: Div32 U:G:32, U:G:32, ZD:G:32
     Tmp, Tmp, Tmp
 

Modified: releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/testb3.cpp (197762 => 197763)


--- releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/testb3.cpp	2016-03-08 14:28:40 UTC (rev 197762)
+++ releases/WebKitGTK/webkit-2.12/Source/_javascript_Core/b3/testb3.cpp	2016-03-08 14:50:15 UTC (rev 197763)
@@ -862,6 +862,256 @@
     test(1);
 }
 
+void testMulAddArgsLeft()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    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, Add, Origin(), multiplied, arg2);
+    root->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int64Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
+            }
+        }
+    }
+}
+
+void testMulAddArgsRight()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    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, Add, Origin(), arg0, multiplied);
+    root->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int64Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
+            }
+        }
+    }
+}
+
+void testMulAddArgsLeft32()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    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, Add, Origin(), multiplied, arg2);
+    root->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int32Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value + c.value);
+            }
+        }
+    }
+}
+
+void testMulAddArgsRight32()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    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, Add, Origin(), arg0, multiplied);
+    root->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int32Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value + b.value * c.value);
+            }
+        }
+    }
+}
+
+void testMulSubArgsLeft()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    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->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int64Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
+            }
+        }
+    }
+}
+
+void testMulSubArgsRight()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    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->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int64Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int64_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
+            }
+        }
+    }
+}
+
+void testMulSubArgsLeft32()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    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->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int32Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value * b.value - c.value);
+            }
+        }
+    }
+}
+
+void testMulSubArgsRight32()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    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->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int32Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            for (auto c : testValues) {
+                CHECK(invoke<int32_t>(*code, a.value, b.value, c.value) == a.value - b.value * c.value);
+            }
+        }
+    }
+}
+
+void testMulNegArgs()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* arg1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+    Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
+    Value* zero = root->appendNew<Const64Value>(proc, Origin(), 0);
+    Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
+    root->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int64Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            CHECK(invoke<int64_t>(*code, a.value, b.value) == -(a.value * b.value));
+        }
+    }
+}
+
+void testMulNegArgs32()
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+
+    Value* arg0 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* arg1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* multiplied = root->appendNew<Value>(proc, Mul, Origin(), arg0, arg1);
+    Value* zero = root->appendNew<Const32Value>(proc, Origin(), 0);
+    Value* added = root->appendNew<Value>(proc, Sub, Origin(), zero, multiplied);
+    root->appendNew<ControlValue>(proc, Return, Origin(), added);
+
+    auto code = compile(proc);
+
+    auto testValues = int32Operands();
+    for (auto a : testValues) {
+        for (auto b : testValues) {
+            CHECK(invoke<int32_t>(*code, a.value, b.value) == -(a.value * b.value));
+        }
+    }
+}
+
 void testMulArgDouble(double a)
 {
     Procedure proc;
@@ -11333,6 +11583,16 @@
     RUN(testMulArgs32(1, 1));
     RUN(testMulArgs32(1, 2));
     RUN(testMulLoadTwice());
+    RUN(testMulAddArgsLeft());
+    RUN(testMulAddArgsRight());
+    RUN(testMulAddArgsLeft32());
+    RUN(testMulAddArgsRight32());
+    RUN(testMulSubArgsLeft());
+    RUN(testMulSubArgsRight());
+    RUN(testMulSubArgsLeft32());
+    RUN(testMulSubArgsRight32());
+    RUN(testMulNegArgs());
+    RUN(testMulNegArgs32());
 
     RUN_UNARY(testMulArgDouble, floatingPointOperands<double>());
     RUN_BINARY(testMulArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to