Title: [243670] trunk/Source/_javascript_Core
Revision
243670
Author
[email protected]
Date
2019-03-29 17:21:38 -0700 (Fri, 29 Mar 2019)

Log Message

B3ReduceStrength should know that Mul distributes over Add and Sub
https://bugs.webkit.org/show_bug.cgi?id=196325

Reviewed by Michael Saboff.

In this patch I add the following patterns to B3ReduceStrength:
- Turn this: Integer Neg(Mul(value, c))
  Into this: Mul(value, -c), as long as -c does not overflow
- Turn these: Integer Mul(value, Neg(otherValue)) and Integer Mul(Neg(value), otherValue)
  Into this: Neg(Mul(value, otherValue))
- 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))

Also includes a trivial change: a similar reduction for the distributivity of BitAnd over BitOr/BitXor now
emits the arguments to BitAnd in the other order, to minimize the probability that we'll spend a full fixpoint step just to flip them.

* b3/B3ReduceStrength.cpp:
* b3/testb3.cpp:
(JSC::B3::testAddMulMulArgs):
(JSC::B3::testMulArgNegArg):
(JSC::B3::testMulNegArgArg):
(JSC::B3::testNegMulArgImm):
(JSC::B3::testSubMulMulArgs):
(JSC::B3::run):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (243669 => 243670)


--- trunk/Source/_javascript_Core/ChangeLog	2019-03-30 00:21:31 UTC (rev 243669)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-03-30 00:21:38 UTC (rev 243670)
@@ -1,3 +1,34 @@
+2019-03-29  Robin Morisset  <[email protected]>
+
+        B3ReduceStrength should know that Mul distributes over Add and Sub
+        https://bugs.webkit.org/show_bug.cgi?id=196325
+
+        Reviewed by Michael Saboff.
+
+        In this patch I add the following patterns to B3ReduceStrength:
+        - Turn this: Integer Neg(Mul(value, c))
+          Into this: Mul(value, -c), as long as -c does not overflow
+        - Turn these: Integer Mul(value, Neg(otherValue)) and Integer Mul(Neg(value), otherValue)
+          Into this: Neg(Mul(value, otherValue))
+        - 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))
+
+        Also includes a trivial change: a similar reduction for the distributivity of BitAnd over BitOr/BitXor now
+        emits the arguments to BitAnd in the other order, to minimize the probability that we'll spend a full fixpoint step just to flip them.
+
+        * b3/B3ReduceStrength.cpp:
+        * b3/testb3.cpp:
+        (JSC::B3::testAddMulMulArgs):
+        (JSC::B3::testMulArgNegArg):
+        (JSC::B3::testMulNegArgArg):
+        (JSC::B3::testNegMulArgImm):
+        (JSC::B3::testSubMulMulArgs):
+        (JSC::B3::run):
+
 2019-03-29  Yusuke Suzuki  <[email protected]>
 
         [JSC] Remove distancing for LargeAllocation

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));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to