Title: [249721] trunk/Source/_javascript_Core
Revision
249721
Author
ysuz...@apple.com
Date
2019-09-10 10:07:24 -0700 (Tue, 10 Sep 2019)

Log Message

[JSC] 32bit bitwide operation with all-one (-1) is wrong in B3
https://bugs.webkit.org/show_bug.cgi?id=201634

Reviewed by Mark Lam.

Accidentally, the B3::Value is ConstInt32(-1), `value->isInt(std::numeric_limits<uint32_t>::max())` returns `false`!
For example, in BitAnd strength reduction,

    1034             // Turn this: BitAnd(value, all-ones)
    1035             // Into this: value.
    1036             if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
    1037                 || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
    1038                 replaceWithIdentity(m_value->child(0));
    1039                 break;
    1040             }

We use `m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max())`. However, Value::isInt is,

    262 inline bool Value::isInt(int64_t value) const
    263 {
    264     return hasInt() && asInt() == value;
    265 }

So, UINT32_MAX is expanded to int64_t, but it is not -1 since UINT32_MAX can be representable in int64_t. And Value::asInt implementation is,

    257 inline int64_t Value::asInt() const
    258 {
    259     return hasInt32() ? asInt32() : asInt64();
    260 }

So, we perform `static_cast<int64_t>(-1) == static_cast<int64_t>(UINT32_MAX)`. This is false, but this comparison is not what we want!
We should use `isInt32` and `isInt64` for bit patterns (like, operands for Bitwise opcodes).

We also fix the following optimization.

    // Turn this: BitAnd(Op(value, constant1), constant2)
    //     where !(constant1 & constant2)
    //       and Op is BitOr or BitXor
    // into this: BitAnd(value, constant2)

Since we stop further optimization when we match `if (m_value->child(1)->hasInt())`, the following optimization is never taken.

    // Turn this: BitAnd(BitXor(x, allOnes), c)
    // Into this: BitXor(BitOr(x, ~c), allOnes)

We add 32bit version of B3 tests for these optimizations.

* b3/B3LowerToAir.cpp:
* b3/B3ReduceStrength.cpp:
* b3/testb3.h:
* b3/testb3_2.cpp:
(testBitAndNotNot32):
(testBitAndNotImm):
(testBitAndNotImm32):
(testBitOrAndAndArgs32):
(testBitOrAndSameArgs32):
(testBitOrNotNot32):
(testBitOrNotImm32):
(addBitTests):
* b3/testb3_3.cpp:
(testBitXorAndAndArgs32):
(testBitXorAndSameArgs32):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (249720 => 249721)


--- trunk/Source/_javascript_Core/ChangeLog	2019-09-10 16:56:46 UTC (rev 249720)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-09-10 17:07:24 UTC (rev 249721)
@@ -1,5 +1,70 @@
 2019-09-10  Yusuke Suzuki  <ysuz...@apple.com>
 
+        [JSC] 32bit bitwide operation with all-one (-1) is wrong in B3
+        https://bugs.webkit.org/show_bug.cgi?id=201634
+
+        Reviewed by Mark Lam.
+
+        Accidentally, the B3::Value is ConstInt32(-1), `value->isInt(std::numeric_limits<uint32_t>::max())` returns `false`!
+        For example, in BitAnd strength reduction,
+
+            1034             // Turn this: BitAnd(value, all-ones)
+            1035             // Into this: value.
+            1036             if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
+            1037                 || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
+            1038                 replaceWithIdentity(m_value->child(0));
+            1039                 break;
+            1040             }
+
+        We use `m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max())`. However, Value::isInt is,
+
+            262 inline bool Value::isInt(int64_t value) const
+            263 {
+            264     return hasInt() && asInt() == value;
+            265 }
+
+        So, UINT32_MAX is expanded to int64_t, but it is not -1 since UINT32_MAX can be representable in int64_t. And Value::asInt implementation is,
+
+            257 inline int64_t Value::asInt() const
+            258 {
+            259     return hasInt32() ? asInt32() : asInt64();
+            260 }
+
+        So, we perform `static_cast<int64_t>(-1) == static_cast<int64_t>(UINT32_MAX)`. This is false, but this comparison is not what we want!
+        We should use `isInt32` and `isInt64` for bit patterns (like, operands for Bitwise opcodes).
+
+        We also fix the following optimization.
+
+            // Turn this: BitAnd(Op(value, constant1), constant2)
+            //     where !(constant1 & constant2)
+            //       and Op is BitOr or BitXor
+            // into this: BitAnd(value, constant2)
+
+        Since we stop further optimization when we match `if (m_value->child(1)->hasInt())`, the following optimization is never taken.
+
+            // Turn this: BitAnd(BitXor(x, allOnes), c)
+            // Into this: BitXor(BitOr(x, ~c), allOnes)
+
+        We add 32bit version of B3 tests for these optimizations.
+
+        * b3/B3LowerToAir.cpp:
+        * b3/B3ReduceStrength.cpp:
+        * b3/testb3.h:
+        * b3/testb3_2.cpp:
+        (testBitAndNotNot32):
+        (testBitAndNotImm):
+        (testBitAndNotImm32):
+        (testBitOrAndAndArgs32):
+        (testBitOrAndSameArgs32):
+        (testBitOrNotNot32):
+        (testBitOrNotImm32):
+        (addBitTests):
+        * b3/testb3_3.cpp:
+        (testBitXorAndAndArgs32):
+        (testBitXorAndSameArgs32):
+
+2019-09-10  Yusuke Suzuki  <ysuz...@apple.com>
+
         [WebAssembly] Use StreamingParser in existing Wasm::BBQPlan
         https://bugs.webkit.org/show_bug.cgi?id=189043
 

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (249720 => 249721)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2019-09-10 16:56:46 UTC (rev 249720)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2019-09-10 17:07:24 UTC (rev 249721)
@@ -2749,7 +2749,7 @@
                 return;
             }
 
-            if (m_value->child(1)->isInt(0xffffffff)) {
+            if (m_value->child(1)->isInt64(0xffffffff) || m_value->child(1)->isInt32(0xffffffff)) {
                 appendUnOp<Move32, Move32>(m_value->child(0));
                 return;
             }

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (249720 => 249721)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2019-09-10 16:56:46 UTC (rev 249720)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2019-09-10 17:07:24 UTC (rev 249721)
@@ -1033,8 +1033,8 @@
 
             // Turn this: BitAnd(value, all-ones)
             // Into this: value.
-            if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
-                || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
+            if ((m_value->type() == Int64 && m_value->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
+                || (m_value->type() == Int32 && m_value->child(1)->isInt32(std::numeric_limits<uint32_t>::max()))) {
                 replaceWithIdentity(m_value->child(0));
                 break;
             }
@@ -1083,6 +1083,7 @@
             //       and Op is BitOr or BitXor
             // into this: BitAnd(value, constant2)
             if (m_value->child(1)->hasInt()) {
+                bool replaced = false;
                 int64_t constant2 = m_value->child(1)->asInt();
                 switch (m_value->child(0)->opcode()) {
                 case BitOr:
@@ -1091,6 +1092,7 @@
                         && !(m_value->child(0)->child(1)->asInt() & constant2)) {
                         m_value->child(0) = m_value->child(0)->child(0);
                         m_changed = true;
+                        replaced = true;
                         break;
                     }
                     break;
@@ -1097,7 +1099,8 @@
                 default:
                     break;
                 }
-                break;
+                if (replaced)
+                    break;
             }
 
             // Turn this: BitAnd(BitXor(x1, allOnes), BitXor(x2, allOnes)
@@ -1106,11 +1109,11 @@
             if (m_value->child(0)->opcode() == BitXor
                 && m_value->child(1)->opcode() == BitXor
                 && ((m_value->type() == Int64
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max())
-                        && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
+                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max())
+                        && m_value->child(1)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
                     || (m_value->type() == Int32
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())
-                        && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
+                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())
+                        && m_value->child(1)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
                 Value* bitOr = m_insertionSet.insert<Value>(m_index, BitOr, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->child(0));
                 replaceWithNew<Value>(BitXor, m_value->origin(), bitOr, m_value->child(1)->child(1));
                 break;
@@ -1123,9 +1126,9 @@
             if (m_value->child(0)->opcode() == BitXor
                 && m_value->child(1)->hasInt()
                 && ((m_value->type() == Int64
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
+                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
                     || (m_value->type() == Int32
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
+                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
                 Value* bitOr = m_insertionSet.insert<Value>(m_index, BitOr, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->bitXorConstant(m_proc, m_value->child(0)->child(1)));
                 replaceWithNew<Value>(BitXor, m_value->origin(), bitOr, m_value->child(0)->child(1));
                 break;
@@ -1171,8 +1174,8 @@
 
             // Turn this: BitOr(value, all-ones)
             // Into this: all-ones.
-            if ((m_value->type() == Int64 && m_value->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
-                || (m_value->type() == Int32 && m_value->child(1)->isInt(std::numeric_limits<uint32_t>::max()))) {
+            if ((m_value->type() == Int64 && m_value->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
+                || (m_value->type() == Int32 && m_value->child(1)->isInt32(std::numeric_limits<uint32_t>::max()))) {
                 replaceWithIdentity(m_value->child(1));
                 break;
             }
@@ -1183,11 +1186,11 @@
             if (m_value->child(0)->opcode() == BitXor
                 && m_value->child(1)->opcode() == BitXor
                 && ((m_value->type() == Int64
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max())
-                        && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
+                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max())
+                        && m_value->child(1)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
                     || (m_value->type() == Int32
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())
-                        && m_value->child(1)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
+                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())
+                        && m_value->child(1)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
                 Value* bitAnd = m_insertionSet.insert<Value>(m_index, BitAnd, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->child(0));
                 replaceWithNew<Value>(BitXor, m_value->origin(), bitAnd, m_value->child(1)->child(1));
                 break;
@@ -1200,9 +1203,9 @@
             if (m_value->child(0)->opcode() == BitXor
                 && m_value->child(1)->hasInt()
                 && ((m_value->type() == Int64
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint64_t>::max()))
+                        && m_value->child(0)->child(1)->isInt64(std::numeric_limits<uint64_t>::max()))
                     || (m_value->type() == Int32
-                        && m_value->child(0)->child(1)->isInt(std::numeric_limits<uint32_t>::max())))) {
+                        && m_value->child(0)->child(1)->isInt32(std::numeric_limits<uint32_t>::max())))) {
                 Value* bitAnd = m_insertionSet.insert<Value>(m_index, BitAnd, m_value->origin(), m_value->child(0)->child(0), m_value->child(1)->bitXorConstant(m_proc, m_value->child(0)->child(1)));
                 replaceWithNew<Value>(BitXor, m_value->origin(), bitAnd, m_value->child(0)->child(1));
                 break;

Modified: trunk/Source/_javascript_Core/b3/testb3.h (249720 => 249721)


--- trunk/Source/_javascript_Core/b3/testb3.h	2019-09-10 16:56:46 UTC (rev 249720)
+++ trunk/Source/_javascript_Core/b3/testb3.h	2019-09-10 17:07:24 UTC (rev 249721)
@@ -459,7 +459,9 @@
 void testBitXorArgs(int64_t, int64_t);
 void testBitXorSameArg(int64_t);
 void testBitXorAndAndArgs(int64_t, int64_t, int64_t c);
+void testBitXorAndAndArgs32(int32_t, int32_t, int32_t c);
 void testBitXorAndSameArgs(int64_t, int64_t);
+void testBitXorAndSameArgs32(int32_t, int32_t);
 void testBitXorImms(int64_t, int64_t);
 void testBitXorArgImm(int64_t, int64_t);
 void testBitXorImmArg(int64_t, int64_t);

Modified: trunk/Source/_javascript_Core/b3/testb3_2.cpp (249720 => 249721)


--- trunk/Source/_javascript_Core/b3/testb3_2.cpp	2019-09-10 16:56:46 UTC (rev 249720)
+++ trunk/Source/_javascript_Core/b3/testb3_2.cpp	2019-09-10 17:07:24 UTC (rev 249721)
@@ -2565,6 +2565,24 @@
     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a & ~b));
 }
 
+static void testBitAndNotNot32(int32_t a, int32_t b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
+    Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const32Value>(proc, Origin(), -1));
+    root->appendNewControlValue(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitAnd, Origin(),
+            notA,
+            notB));
+
+    CHECK_EQ(compileAndRun<int32_t>(proc, a, b), (~a & ~b));
+}
+
 static void testBitAndNotImm(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -2579,9 +2597,26 @@
             notA,
             cstB));
 
-    CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a & b));
+    CHECK_EQ(compileAndRun<int64_t>(proc, a), (~a & b));
 }
 
+static void testBitAndNotImm32(int32_t a, int32_t b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
+    Value* cstB = root->appendNew<Const32Value>(proc, Origin(), b);
+    root->appendNewControlValue(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitAnd, Origin(),
+            notA,
+            cstB));
+
+    CHECK_EQ(compileAndRun<int32_t>(proc, a), (~a & b));
+}
+
 static void testBitAndImms(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -2994,6 +3029,34 @@
     }
 }
 
+static void testBitOrAndAndArgs32(int32_t a, int32_t b, int32_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<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+        Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
+        Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
+            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
+        Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
+            : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
+        root->appendNewControlValue(
+            proc, Return, Origin(),
+            root->appendNew<Value>(
+                proc, BitOr, Origin(),
+                andAB,
+                andAC));
+
+        CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) | (a & c)));
+    }
+}
+
 static void testBitOrAndSameArgs(int64_t a, int64_t b)
 {
     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
@@ -3016,6 +3079,28 @@
     }
 }
 
+static void testBitOrAndSameArgs32(int32_t a, int32_t b)
+{
+    // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
+    // ((a & b) | a)
+    // ((b & a) | a)
+    // (a | (a & b))
+    // (a | (b & a))
+    for (int i = 0; i < 4; ++i) {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+        Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+        Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
+            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
+        Value* result = i & 2 ? root->appendNew<Value>(proc, BitOr, Origin(), andAB, argA)
+            : root->appendNew<Value>(proc, BitOr, Origin(), argA, andAB);
+        root->appendNewControlValue(proc, Return, Origin(), result);
+
+        CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) | a));
+    }
+}
+
 static void testBitOrNotNot(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -3034,6 +3119,24 @@
     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | ~b));
 }
 
+static void testBitOrNotNot32(int32_t a, int32_t b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
+    Value* notB = root->appendNew<Value>(proc, BitXor, Origin(), argB, root->appendNew<Const32Value>(proc, Origin(), -1));
+    root->appendNewControlValue(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitOr, Origin(),
+            notA,
+            notB));
+
+    CHECK_EQ(compileAndRun<int32_t>(proc, a, b), (~a | ~b));
+}
+
 static void testBitOrNotImm(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -3051,6 +3154,23 @@
     CHECK_EQ(compileAndRun<int64_t>(proc, a, b), (~a | b));
 }
 
+static void testBitOrNotImm32(int32_t a, int32_t b)
+{
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* notA = root->appendNew<Value>(proc, BitXor, Origin(), argA, root->appendNew<Const32Value>(proc, Origin(), -1));
+    Value* cstB = root->appendNew<Const32Value>(proc, Origin(), b);
+    root->appendNewControlValue(
+        proc, Return, Origin(),
+        root->appendNew<Value>(
+            proc, BitOr, Origin(),
+            notA,
+            cstB));
+
+    CHECK_EQ(compileAndRun<int32_t>(proc, a), (~a | b));
+}
+
 static void testBitOrImms(int64_t a, int64_t b)
 {
     Procedure proc;
@@ -3287,7 +3407,9 @@
     RUN_BINARY(testBitAndImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN_BINARY(testBitAndArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN_BINARY(testBitAndNotNot, int64Operands(), int64Operands());
+    RUN_BINARY(testBitAndNotNot32, int32Operands(), int32Operands());
     RUN_BINARY(testBitAndNotImm, int64Operands(), int64Operands());
+    RUN_BINARY(testBitAndNotImm32, int32Operands(), int32Operands());
     
     RUN(testBitOrArgs(43, 43));
     RUN(testBitOrArgs(43, 0));
@@ -3351,9 +3473,13 @@
     RUN_BINARY(testBitOrImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN_BINARY(testBitOrArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN_TERNARY(testBitOrAndAndArgs, int64Operands(), int64Operands(), int64Operands());
+    RUN_TERNARY(testBitOrAndAndArgs32, int32Operands(), int32Operands(), int32Operands());
     RUN_BINARY(testBitOrAndSameArgs, int64Operands(), int64Operands());
+    RUN_BINARY(testBitOrAndSameArgs32, int32Operands(), int32Operands());
     RUN_BINARY(testBitOrNotNot, int64Operands(), int64Operands());
+    RUN_BINARY(testBitOrNotNot32, int32Operands(), int32Operands());
     RUN_BINARY(testBitOrNotImm, int64Operands(), int64Operands());
+    RUN_BINARY(testBitOrNotImm32, int32Operands(), int32Operands());
     
     RUN_BINARY(testBitXorArgs, int64Operands(), int64Operands());
     RUN_UNARY(testBitXorSameArg, int64Operands());
@@ -3393,7 +3519,9 @@
     RUN(testBitXorImmBitXorArgImm32(6, 1, 6));
     RUN(testBitXorImmBitXorArgImm32(24, 0xffff, 7));
     RUN_TERNARY(testBitXorAndAndArgs, int64Operands(), int64Operands(), int64Operands());
+    RUN_TERNARY(testBitXorAndAndArgs32, int32Operands(), int32Operands(), int32Operands());
     RUN_BINARY(testBitXorAndSameArgs, int64Operands(), int64Operands());
+    RUN_BINARY(testBitXorAndSameArgs32, int32Operands(), int32Operands());
     
     RUN_UNARY(testBitNotArg, int64Operands());
     RUN_UNARY(testBitNotImm, int64Operands());

Modified: trunk/Source/_javascript_Core/b3/testb3_3.cpp (249720 => 249721)


--- trunk/Source/_javascript_Core/b3/testb3_3.cpp	2019-09-10 16:56:46 UTC (rev 249720)
+++ trunk/Source/_javascript_Core/b3/testb3_3.cpp	2019-09-10 17:07:24 UTC (rev 249721)
@@ -259,6 +259,34 @@
     }
 }
 
+void testBitXorAndAndArgs32(int32_t a, int32_t b, int32_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<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+        Value* argC = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR2));
+        Value* andAB = i & 2 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
+            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
+        Value* andAC = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argC)
+            : root->appendNew<Value>(proc, BitAnd, Origin(), argC, argA);
+        root->appendNewControlValue(
+            proc, Return, Origin(),
+            root->appendNew<Value>(
+                proc, BitXor, Origin(),
+                andAB,
+                andAC));
+
+        CHECK_EQ(compileAndRun<int32_t>(proc, a, b, c), ((a & b) ^ (a & c)));
+    }
+}
+
 void testBitXorAndSameArgs(int64_t a, int64_t b)
 {
     // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
@@ -281,6 +309,28 @@
     }
 }
 
+void testBitXorAndSameArgs32(int32_t a, int32_t b)
+{
+    // We want to check every possible ordering of arguments (to properly check every path in B3ReduceStrength):
+    // ((a & b) ^ a)
+    // ((b & a) ^ a)
+    // (a ^ (a & b))
+    // (a ^ (b & a))
+    for (int i = 0; i < 4; ++i) {
+        Procedure proc;
+        BasicBlock* root = proc.addBlock();
+        Value* argA = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+        Value* argB = root->appendNew<Value>(proc, Trunc, Origin(), root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+        Value* andAB = i & 1 ? root->appendNew<Value>(proc, BitAnd, Origin(), argA, argB)
+            : root->appendNew<Value>(proc, BitAnd, Origin(), argB, argA);
+        Value* result = i & 2 ? root->appendNew<Value>(proc, BitXor, Origin(), andAB, argA)
+            : root->appendNew<Value>(proc, BitXor, Origin(), argA, andAB);
+        root->appendNewControlValue(proc, Return, Origin(), result);
+
+        CHECK_EQ(compileAndRun<int32_t>(proc, a, b), ((a & b) ^ a));
+    }
+}
+
 void testBitXorImms(int64_t a, int64_t b)
 {
     Procedure proc;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to