Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (243669 => 243670)
--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2019-03-30 00:21:31 UTC (rev 243669)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2019-03-30 00:21:38 UTC (rev 243670)
@@ -602,6 +602,9 @@
replaceWithNew<Value>(BitXor, m_value->origin(), m_value->child(0)->child(1), m_value->child(1));
break;
}
+
+ if (handleMulDistributivity())
+ break;
}
break;
@@ -644,6 +647,9 @@
replaceWithNew<Value>(Add, m_value->origin(), m_value->child(0), m_value->child(1)->child(0));
break;
}
+
+ if (handleMulDistributivity())
+ break;
}
break;
@@ -662,14 +668,30 @@
replaceWithIdentity(m_value->child(0)->child(0));
break;
}
-
- // Turn this: Integer Neg(Sub(value, otherValue))
- // Into this: Sub(otherValue, value)
- if (m_value->isInteger() && m_value->child(0)->opcode() == Sub) {
- replaceWithNew<Value>(Sub, m_value->origin(), m_value->child(0)->child(1), m_value->child(0)->child(0));
- break;
+
+ if (m_value->isInteger()) {
+ // Turn this: Integer Neg(Sub(value, otherValue))
+ // Into this: Sub(otherValue, value)
+ if (m_value->child(0)->opcode() == Sub) {
+ replaceWithNew<Value>(Sub, m_value->origin(), m_value->child(0)->child(1), m_value->child(0)->child(0));
+ break;
+ }
+
+ // Turn this: Integer Neg(Mul(value, c))
+ // Into this: Mul(value, -c), as long as -c does not overflow
+ if (m_value->child(0)->opcode() == Mul && m_value->child(0)->child(1)->hasInt()) {
+ int64_t factor = m_value->child(0)->child(1)->asInt();
+ if (m_value->type() == Int32 && factor != std::numeric_limits<int32_t>::min()) {
+ Value* newFactor = m_insertionSet.insert<Const32Value>(m_index, m_value->child(0)->child(1)->origin(), -factor);
+ replaceWithNew<Value>(Mul, m_value->origin(), m_value->child(0)->child(0), newFactor);
+ } else if (m_value->type() == Int64 && factor != std::numeric_limits<int64_t>::min()) {
+ Value* newFactor = m_insertionSet.insert<Const64Value>(m_index, m_value->child(0)->child(1)->origin(), -factor);
+ replaceWithNew<Value>(Mul, m_value->origin(), m_value->child(0)->child(0), newFactor);
+ }
+ }
}
+
break;
case Mul:
@@ -702,13 +724,9 @@
}
// Turn this: Mul(value, -1)
- // Into this: Sub(0, value)
+ // Into this: Neg(value)
if (factor == -1) {
- replaceWithNewValue(
- m_proc.add<Value>(
- Sub, m_value->origin(),
- m_insertionSet.insertIntConstant(m_index, m_value, 0),
- m_value->child(0)));
+ replaceWithNew<Value>(Neg, m_value->origin(), m_value->child(0));
break;
}
@@ -734,6 +752,23 @@
}
}
+ if (m_value->isInteger()) {
+ // Turn this: Integer Mul(value, Neg(otherValue))
+ // Into this: Neg(Mul(value, otherValue))
+ if (m_value->child(1)->opcode() == Neg) {
+ Value* newMul = m_insertionSet.insert<Value>(m_index, Mul, m_value->origin(), m_value->child(0), m_value->child(1)->child(0));
+ replaceWithNew<Value>(Neg, m_value->origin(), newMul);
+ break;
+ }
+ // Turn this: Integer Mul(Neg(value), otherValue)
+ // Into this: Neg(Mul(value, value2))
+ if (m_value->child(0)->opcode() == Neg) {
+ Value* newMul = m_insertionSet.insert<Value>(m_index, Mul, m_value->origin(), m_value->child(0)->child(0), m_value->child(1));
+ replaceWithNew<Value>(Neg, m_value->origin(), newMul);
+ break;
+ }
+ }
+
break;
case Div:
@@ -2296,6 +2331,53 @@
}
}
+ // For Op==Add or Sub, turn any of these:
+ // Op(Mul(x1, x2), Mul(x1, x3))
+ // Op(Mul(x2, x1), Mul(x1, x3))
+ // Op(Mul(x1, x2), Mul(x3, x1))
+ // Op(Mul(x2, x1), Mul(x3, x1))
+ // Into this: Mul(x1, Op(x2, x3))
+ bool handleMulDistributivity()
+ {
+ ASSERT(m_value->opcode() == Add || m_value->opcode() == Sub);
+ Value* x1 = nullptr;
+ Value* x2 = nullptr;
+ Value* x3 = nullptr;
+ if (m_value->child(0)->opcode() == Mul && m_value->child(1)->opcode() == Mul) {
+ Value* x1 = nullptr;
+ Value* x2 = nullptr;
+ Value* x3 = nullptr;
+ if (m_value->child(0)->child(0) == m_value->child(1)->child(0)) {
+ // Op(Mul(x1, x2), Mul(x1, x3))
+ x1 = m_value->child(0)->child(0);
+ x2 = m_value->child(0)->child(1);
+ x3 = m_value->child(1)->child(1);
+ } else if (m_value->child(0)->child(1) == m_value->child(1)->child(0)) {
+ // Op(Mul(x2, x1), Mul(x1, x3))
+ x1 = m_value->child(0)->child(1);
+ x2 = m_value->child(0)->child(0);
+ x3 = m_value->child(1)->child(1);
+ } else if (m_value->child(0)->child(0) == m_value->child(1)->child(1)) {
+ // Op(Mul(x1, x2), Mul(x3, x1))
+ x1 = m_value->child(0)->child(0);
+ x2 = m_value->child(0)->child(1);
+ x3 = m_value->child(1)->child(0);
+ } else if (m_value->child(0)->child(1) == m_value->child(1)->child(1)) {
+ // Op(Mul(x2, x1), Mul(x3, x1))
+ x1 = m_value->child(0)->child(1);
+ x2 = m_value->child(0)->child(0);
+ x3 = m_value->child(1)->child(0);
+ }
+ }
+ if (x1 != nullptr) {
+ ASSERT(x2 != nullptr && x3 != nullptr);
+ Value* newOp = m_insertionSet.insert<Value>(m_index, m_value->opcode(), m_value->origin(), x2, x3);
+ replaceWithNew<Value>(Mul, m_value->origin(), x1, newOp);
+ return true;
+ }
+ return false;
+ }
+
// For Op==BitOr or BitXor, turn any of these:
// Op(BitAnd(x1, x2), BitAnd(x1, x3))
// Op(BitAnd(x2, x1), BitAnd(x1, x3))
@@ -2354,7 +2436,7 @@
if (x1 != nullptr) {
ASSERT(x2 != nullptr && x3 != nullptr);
Value* bitOp = m_insertionSet.insert<Value>(m_index, m_value->opcode(), m_value->origin(), x2, x3);
- replaceWithNew<Value>(BitAnd, m_value->origin(), bitOp, x1);
+ replaceWithNew<Value>(BitAnd, m_value->origin(), x1, bitOp);
return true;
}
return false;
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (243669 => 243670)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2019-03-30 00:21:31 UTC (rev 243669)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2019-03-30 00:21:38 UTC (rev 243670)
@@ -891,6 +891,32 @@
CHECK(isIdentical(effect, static_cast<double>(a) + static_cast<double>(b)));
}
+void testAddMulMulArgs(int64_t a, int64_t b, int64_t c)
+{
+ // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
+ // ((a * b) + (a * c))
+ // ((a * b) + (c * a))
+ // ((b * a) + (a * c))
+ // ((b * a) + (c * a))
+ for (int i = 0; i < 4; ++i) {
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+ Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
+ Value* mulAB = i & 2 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argB)
+ : root->appendNew<Value>(proc, Mul, Origin(), argB, argA);
+ Value* mulAC = i & 1 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argC)
+ : root->appendNew<Value>(proc, Mul, Origin(), argC, argA);
+ root->appendNew<Value>(proc, Return, Origin(),
+ root->appendNew<Value>(proc, Add, Origin(),
+ mulAB,
+ mulAC));
+
+ CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a * b) + (a * c)));
+ }
+}
+
void testMulArg(int a)
{
Procedure proc;
@@ -963,6 +989,32 @@
CHECK(compileAndRun<int>(proc, a, b) == a * b);
}
+void testMulArgNegArg(int a, int b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+ Value* negB = root->appendNew<Value>(proc, Neg, Origin(), argB);
+ Value* result = root->appendNew<Value>(proc, Mul, Origin(), argA, negB);
+ root->appendNew<Value>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int>(proc, a, b) == a * (-b));
+}
+
+void testMulNegArgArg(int a, int b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+ Value* negA = root->appendNew<Value>(proc, Neg, Origin(), argA);
+ Value* result = root->appendNew<Value>(proc, Mul, Origin(), negA, argB);
+ root->appendNew<Value>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int>(proc, a, b) == (-a) * b);
+}
+
void testMulArgImm(int64_t a, int64_t b)
{
Procedure proc;
@@ -2180,6 +2232,45 @@
CHECK(compileAndRun<int>(proc, a) == -a - 1);
}
+void testNegMulArgImm(int64_t a, int64_t b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* constant = root->appendNew<Const64Value>(proc, Origin(), b);
+ Value* mul = root->appendNew<Value>(proc, Mul, Origin(), argument, constant);
+ Value* result = root->appendNew<Value>(proc, Neg, Origin(), mul);
+ root->appendNew<Value>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int64_t>(proc, a) == -(a * b));
+}
+
+void testSubMulMulArgs(int64_t a, int64_t b, int64_t c)
+{
+ // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
+ // ((a * b) - (a * c))
+ // ((a * b) - (c * a))
+ // ((b * a) - (a * c))
+ // ((b * a) - (c * a))
+ for (int i = 0; i < 4; ++i) {
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argA = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* argB = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+ Value* argC = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2);
+ Value* mulAB = i & 2 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argB)
+ : root->appendNew<Value>(proc, Mul, Origin(), argB, argA);
+ Value* mulAC = i & 1 ? root->appendNew<Value>(proc, Mul, Origin(), argA, argC)
+ : root->appendNew<Value>(proc, Mul, Origin(), argC, argA);
+ root->appendNew<Value>(proc, Return, Origin(),
+ root->appendNew<Value>(proc, Sub, Origin(),
+ mulAB,
+ mulAC));
+
+ CHECK_EQ(compileAndRun<int64_t>(proc, a, b, c), ((a * b) - (a * c)));
+ }
+}
+
void testSubArgDouble(double a)
{
Procedure proc;
@@ -16979,6 +17070,7 @@
RUN_BINARY(testAddNeg2, int32Operands(), int32Operands());
RUN(testAddArgZeroImmZDef());
RUN(testAddLoadTwice());
+ RUN_TERNARY(testAddMulMulArgs, int64Operands(), int64Operands(), int64Operands());
RUN(testAddArgDouble(M_PI));
RUN(testAddArgsDouble(M_PI, 1));
@@ -17063,6 +17155,8 @@
RUN(testMulNegArgs());
RUN(testMulNegArgs32());
+ RUN_BINARY(testMulArgNegArg, int64Operands(), int64Operands())
+ RUN_BINARY(testMulNegArgArg, int64Operands(), int64Operands())
RUN_UNARY(testMulArgDouble, floatingPointOperands<double>());
RUN_BINARY(testMulArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
RUN_BINARY(testMulArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
@@ -17147,6 +17241,8 @@
RUN_BINARY(testSubNeg, int32Operands(), int32Operands());
RUN_BINARY(testNegSub, int32Operands(), int32Operands());
RUN_UNARY(testNegValueSubOne, int32Operands());
+ RUN_BINARY(testNegMulArgImm, int64Operands(), int64Operands());
+ RUN_TERNARY(testSubMulMulArgs, int64Operands(), int64Operands(), int64Operands());
RUN(testSubArgs32(1, 1));
RUN(testSubArgs32(1, 2));