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>());