Title: [208781] trunk
Revision
208781
Author
[email protected]
Date
2016-11-15 20:47:20 -0800 (Tue, 15 Nov 2016)

Log Message

B3 should support UDiv/UMod
https://bugs.webkit.org/show_bug.cgi?id=164811

Reviewed by Filip Pizlo.

JSTests:

Link new instructions to wasm.

* wasm/wasm.json:

Source/_javascript_Core:

This patch adds support for UDiv and UMod in B3. Many of the magic number
cases have been ommited for now since they are unlikely to happen in wasm
code. Most wasm code we will see is generated via llvm, which has more
robust versions of what we would do anyway. Additionally, this patch
links the new opcodes up to the wasm parser.

* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::uDiv32):
(JSC::MacroAssemblerARM64::uDiv64):
* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::x86UDiv32):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::x86UDiv64):
* assembler/X86Assembler.h:
(JSC::X86Assembler::divq_r):
* b3/B3Common.h:
(JSC::B3::chillUDiv):
(JSC::B3::chillUMod):
* b3/B3Const32Value.cpp:
(JSC::B3::Const32Value::uDivConstant):
(JSC::B3::Const32Value::uModConstant):
* b3/B3Const32Value.h:
* b3/B3Const64Value.cpp:
(JSC::B3::Const64Value::uDivConstant):
(JSC::B3::Const64Value::uModConstant):
* b3/B3Const64Value.h:
* b3/B3LowerMacros.cpp:
* b3/B3LowerToAir.cpp:
(JSC::B3::Air::LowerToAir::lower):
(JSC::B3::Air::LowerToAir::lowerX86UDiv):
* b3/B3Opcode.cpp:
(WTF::printInternal):
* b3/B3Opcode.h:
* b3/B3ReduceStrength.cpp:
* b3/B3Validate.cpp:
* b3/B3Value.cpp:
(JSC::B3::Value::uDivConstant):
(JSC::B3::Value::uModConstant):
(JSC::B3::Value::effects):
(JSC::B3::Value::key):
(JSC::B3::Value::typeFor):
* b3/B3Value.h:
* b3/B3ValueKey.cpp:
(JSC::B3::ValueKey::materialize):
* b3/air/AirInstInlines.h:
(JSC::B3::Air::isX86UDiv32Valid):
(JSC::B3::Air::isX86UDiv64Valid):
* b3/air/AirOpcode.opcodes:
* b3/testb3.cpp:
(JSC::B3::testUDivArgsInt32):
(JSC::B3::testUDivArgsInt64):
(JSC::B3::testUModArgsInt32):
(JSC::B3::testUModArgsInt64):
(JSC::B3::run):
* wasm/wasm.json:

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (208780 => 208781)


--- trunk/JSTests/ChangeLog	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/JSTests/ChangeLog	2016-11-16 04:47:20 UTC (rev 208781)
@@ -1,3 +1,14 @@
+2016-11-15  Keith Miller  <[email protected]>
+
+        B3 should support UDiv/UMod
+        https://bugs.webkit.org/show_bug.cgi?id=164811
+
+        Reviewed by Filip Pizlo.
+
+        Link new instructions to wasm.
+
+        * wasm/wasm.json:
+
 2016-11-15  Saam Barati  <[email protected]>
 
         Debug JSC test timeout: stress/has-own-property-name-cache-symbols-and-strings.js.ftl-no-cjit-small-pool

Modified: trunk/JSTests/wasm/wasm.json (208780 => 208781)


--- trunk/JSTests/wasm/wasm.json	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/JSTests/wasm/wasm.json	2016-11-16 04:47:20 UTC (rev 208781)
@@ -96,9 +96,9 @@
         "i32.sub":             { "category": "arithmetic", "value":  65, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
         "i32.mul":             { "category": "arithmetic", "value":  66, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
         "i32.div_s":           { "category": "arithmetic", "value":  67, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Div"          },
-        "i32.div_u":           { "category": "arithmetic", "value":  68, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.div_u":           { "category": "arithmetic", "value":  68, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UDiv"         },
         "i32.rem_s":           { "category": "arithmetic", "value":  69, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mod"          },
-        "i32.rem_u":           { "category": "arithmetic", "value":  70, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.rem_u":           { "category": "arithmetic", "value":  70, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UMod"         },
         "i32.and":             { "category": "arithmetic", "value":  71, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
         "i32.or":              { "category": "arithmetic", "value":  72, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
         "i32.xor":             { "category": "arithmetic", "value":  73, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
@@ -125,9 +125,9 @@
         "i64.sub":             { "category": "arithmetic", "value":  92, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
         "i64.mul":             { "category": "arithmetic", "value":  93, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
         "i64.div_s":           { "category": "arithmetic", "value":  94, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Div"          },
-        "i64.div_u":           { "category": "arithmetic", "value":  95, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.div_u":           { "category": "arithmetic", "value":  95, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
         "i64.rem_s":           { "category": "arithmetic", "value":  96, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mod"          },
-        "i64.rem_u":           { "category": "arithmetic", "value":  97, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.rem_u":           { "category": "arithmetic", "value":  97, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
         "i64.and":             { "category": "arithmetic", "value":  98, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
         "i64.or":              { "category": "arithmetic", "value":  99, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
         "i64.xor":             { "category": "arithmetic", "value": 100, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },

Modified: trunk/Source/_javascript_Core/ChangeLog (208780 => 208781)


--- trunk/Source/_javascript_Core/ChangeLog	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-11-16 04:47:20 UTC (rev 208781)
@@ -1,3 +1,66 @@
+2016-11-15  Keith Miller  <[email protected]>
+
+        B3 should support UDiv/UMod
+        https://bugs.webkit.org/show_bug.cgi?id=164811
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds support for UDiv and UMod in B3. Many of the magic number
+        cases have been ommited for now since they are unlikely to happen in wasm
+        code. Most wasm code we will see is generated via llvm, which has more
+        robust versions of what we would do anyway. Additionally, this patch
+        links the new opcodes up to the wasm parser.
+
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::uDiv32):
+        (JSC::MacroAssemblerARM64::uDiv64):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::x86UDiv32):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::x86UDiv64):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::divq_r):
+        * b3/B3Common.h:
+        (JSC::B3::chillUDiv):
+        (JSC::B3::chillUMod):
+        * b3/B3Const32Value.cpp:
+        (JSC::B3::Const32Value::uDivConstant):
+        (JSC::B3::Const32Value::uModConstant):
+        * b3/B3Const32Value.h:
+        * b3/B3Const64Value.cpp:
+        (JSC::B3::Const64Value::uDivConstant):
+        (JSC::B3::Const64Value::uModConstant):
+        * b3/B3Const64Value.h:
+        * b3/B3LowerMacros.cpp:
+        * b3/B3LowerToAir.cpp:
+        (JSC::B3::Air::LowerToAir::lower):
+        (JSC::B3::Air::LowerToAir::lowerX86UDiv):
+        * b3/B3Opcode.cpp:
+        (WTF::printInternal):
+        * b3/B3Opcode.h:
+        * b3/B3ReduceStrength.cpp:
+        * b3/B3Validate.cpp:
+        * b3/B3Value.cpp:
+        (JSC::B3::Value::uDivConstant):
+        (JSC::B3::Value::uModConstant):
+        (JSC::B3::Value::effects):
+        (JSC::B3::Value::key):
+        (JSC::B3::Value::typeFor):
+        * b3/B3Value.h:
+        * b3/B3ValueKey.cpp:
+        (JSC::B3::ValueKey::materialize):
+        * b3/air/AirInstInlines.h:
+        (JSC::B3::Air::isX86UDiv32Valid):
+        (JSC::B3::Air::isX86UDiv64Valid):
+        * b3/air/AirOpcode.opcodes:
+        * b3/testb3.cpp:
+        (JSC::B3::testUDivArgsInt32):
+        (JSC::B3::testUDivArgsInt64):
+        (JSC::B3::testUModArgsInt32):
+        (JSC::B3::testUModArgsInt64):
+        (JSC::B3::run):
+        * wasm/wasm.json:
+
 2016-11-15  Joseph Pecoraro  <[email protected]>
 
         Web Inspector: Preview other CSS @media in browser window (print)

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (208780 => 208781)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -533,6 +533,16 @@
         m_assembler.sdiv<64>(dest, dividend, divisor);
     }
 
+    void uDiv32(RegisterID dividend, RegisterID divisor, RegisterID dest)
+    {
+        m_assembler.udiv<32>(dest, dividend, divisor);
+    }
+
+    void uDiv64(RegisterID dividend, RegisterID divisor, RegisterID dest)
+    {
+        m_assembler.udiv<64>(dest, dividend, divisor);
+    }
+
     void neg32(RegisterID dest)
     {
         m_assembler.neg<32>(dest, dest);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (208780 => 208781)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -414,6 +414,18 @@
         x86Div32(denominator);
     }
 
+    void x86UDiv32(RegisterID denominator)
+    {
+        m_assembler.divl_r(denominator);
+    }
+
+    void x86UDiv32(RegisterID eax, RegisterID edx, RegisterID denominator)
+    {
+        ASSERT_UNUSED(eax, eax == X86Registers::eax);
+        ASSERT_UNUSED(edx, edx == X86Registers::edx);
+        x86UDiv32(denominator);
+    }
+
     void neg32(RegisterID srcDest)
     {
         m_assembler.negl_r(srcDest);

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (208780 => 208781)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -487,6 +487,18 @@
         x86Div64(denominator);
     }
 
+    void x86UDiv64(RegisterID denominator)
+    {
+        m_assembler.divq_r(denominator);
+    }
+
+    void x86UDiv64(RegisterID rax, RegisterID rdx, RegisterID denominator)
+    {
+        ASSERT_UNUSED(rax, rax == X86Registers::eax);
+        ASSERT_UNUSED(rdx, rdx == X86Registers::edx);
+        x86UDiv64(denominator);
+    }
+
     void neg64(RegisterID dest)
     {
         m_assembler.negq_r(dest);

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (208780 => 208781)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -1154,6 +1154,11 @@
     }
 
 #if CPU(X86_64)
+    void divq_r(RegisterID dst)
+    {
+        m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_DIV, dst);
+    }
+
     void idivq_r(RegisterID dst)
     {
         m_formatter.oneByteOp64(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);

Modified: trunk/Source/_javascript_Core/b3/B3Common.h (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Common.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Common.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -28,6 +28,7 @@
 #if ENABLE(B3_JIT)
 
 #include "JSExportMacros.h"
+#include <wtf/Optional.h>
 
 namespace JSC { namespace B3 {
 
@@ -125,6 +126,28 @@
     return numerator % denominator;
 }
 
+template<typename IntType>
+static IntType chillUDiv(IntType numerator, IntType denominator)
+{
+    typedef typename std::make_unsigned<IntType>::type UnsignedIntType;
+    UnsignedIntType unsignedNumerator = static_cast<UnsignedIntType>(numerator);
+    UnsignedIntType unsignedDenominator = static_cast<UnsignedIntType>(denominator);
+    if (!unsignedDenominator)
+        return 0;
+    return unsignedNumerator / unsignedDenominator;
+}
+
+template<typename IntType>
+static IntType chillUMod(IntType numerator, IntType denominator)
+{
+    typedef typename std::make_unsigned<IntType>::type UnsignedIntType;
+    UnsignedIntType unsignedNumerator = static_cast<UnsignedIntType>(numerator);
+    UnsignedIntType unsignedDenominator = static_cast<UnsignedIntType>(denominator);
+    if (!unsignedDenominator)
+        return 0;
+    return unsignedNumerator % unsignedDenominator;
+}
+
 } } // namespace JSC::B3
 
 #endif // ENABLE(B3_JIT)

Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Const32Value.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -112,6 +112,13 @@
     return proc.add<Const32Value>(origin(), chillDiv(m_value, other->asInt32()));
 }
 
+Value* Const32Value::uDivConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt32())
+        return nullptr;
+    return proc.add<Const32Value>(origin(), chillUDiv(m_value, other->asInt32()));
+}
+
 Value* Const32Value::modConstant(Procedure& proc, const Value* other) const
 {
     if (!other->hasInt32())
@@ -119,6 +126,13 @@
     return proc.add<Const32Value>(origin(), chillMod(m_value, other->asInt32()));
 }
 
+Value* Const32Value::uModConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt32())
+        return nullptr;
+    return proc.add<Const32Value>(origin(), chillUMod(m_value, other->asInt32()));
+}
+
 Value* Const32Value::bitAndConstant(Procedure& proc, const Value* other) const
 {
     if (!other->hasInt32())

Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.h (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Const32Value.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -49,7 +49,9 @@
     Value* checkMulConstant(Procedure&, const Value* other) const override;
     Value* checkNegConstant(Procedure&) const override;
     Value* divConstant(Procedure&, const Value* other) const override;
+    Value* uDivConstant(Procedure&, const Value* other) const override;
     Value* modConstant(Procedure&, const Value* other) const override;
+    Value* uModConstant(Procedure&, const Value* other) const override;
     Value* bitAndConstant(Procedure&, const Value* other) const override;
     Value* bitOrConstant(Procedure&, const Value* other) const override;
     Value* bitXorConstant(Procedure&, const Value* other) const override;

Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Const64Value.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -112,6 +112,13 @@
     return proc.add<Const64Value>(origin(), chillDiv(m_value, other->asInt64()));
 }
 
+Value* Const64Value::uDivConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt64())
+        return nullptr;
+    return proc.add<Const64Value>(origin(), chillUDiv(m_value, other->asInt64()));
+}
+
 Value* Const64Value::modConstant(Procedure& proc, const Value* other) const
 {
     if (!other->hasInt64())
@@ -119,6 +126,13 @@
     return proc.add<Const64Value>(origin(), chillMod(m_value, other->asInt64()));
 }
 
+Value* Const64Value::uModConstant(Procedure& proc, const Value* other) const
+{
+    if (!other->hasInt64())
+        return nullptr;
+    return proc.add<Const64Value>(origin(), chillUMod(m_value, other->asInt64()));
+}
+
 Value* Const64Value::bitAndConstant(Procedure& proc, const Value* other) const
 {
     if (!other->hasInt64())

Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.h (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Const64Value.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -49,7 +49,9 @@
     Value* checkMulConstant(Procedure&, const Value* other) const override;
     Value* checkNegConstant(Procedure&) const override;
     Value* divConstant(Procedure&, const Value* other) const override;
+    Value* uDivConstant(Procedure&, const Value* other) const override;
     Value* modConstant(Procedure&, const Value* other) const override;
+    Value* uModConstant(Procedure&, const Value* other) const override;
     Value* bitAndConstant(Procedure&, const Value* other) const override;
     Value* bitOrConstant(Procedure&, const Value* other) const override;
     Value* bitXorConstant(Procedure&, const Value* other) const override;

Modified: trunk/Source/_javascript_Core/b3/B3LowerMacros.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3LowerMacros.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3LowerMacros.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -149,6 +149,18 @@
                 }
                 break;
             }
+
+            case UMod: {
+                if (isARM64()) {
+                    Value* divResult = m_insertionSet.insert<Value>(m_index, UDiv, m_origin, m_value->child(0), m_value->child(1));
+                    Value* multipliedBack = m_insertionSet.insert<Value>(m_index, Mul, m_origin, divResult, m_value->child(1));
+                    Value* result = m_insertionSet.insert<Value>(m_index, Sub, m_origin, m_value->child(0), multipliedBack);
+                    m_value->replaceWithIdentity(result);
+                    m_changed = true;
+                }
+                break;
+            }
+
             case Div: {
                 if (m_value->isChill())
                     makeDivisionChill(Div);

Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -2095,13 +2095,11 @@
         case Div: {
             if (m_value->isChill())
                 RELEASE_ASSERT(isARM64());
-#if CPU(X86) || CPU(X86_64)
-            if (isInt(m_value->type())) {
+            if (isInt(m_value->type()) && isX86()) {
                 lowerX86Div();
                 append(Move, Tmp(X86Registers::eax), tmp(m_value));
                 return;
             }
-#endif
             ASSERT(!isX86() || isFloat(m_value->type()));
 
             appendBinOp<Div32, Div64, DivDouble, DivFloat>(m_value->child(0), m_value->child(1));
@@ -2108,6 +2106,20 @@
             return;
         }
 
+        case UDiv: {
+            if (isInt(m_value->type()) && isX86()) {
+                lowerX86UDiv();
+                append(Move, Tmp(X86Registers::eax), tmp(m_value));
+                return;
+            }
+
+            ASSERT(!isX86() && !isFloat(m_value->type()));
+
+            appendBinOp<UDiv32, UDiv64, Air::Oops, Air::Oops>(m_value->child(0), m_value->child(1));
+            return;
+
+        }
+
         case Mod: {
             RELEASE_ASSERT(isX86());
             RELEASE_ASSERT(!m_value->isChill());
@@ -2118,6 +2130,15 @@
             return;
         }
 
+        case UMod: {
+            RELEASE_ASSERT(isX86());
+#if CPU(X86) || CPU(X86_64)
+            lowerX86UDiv();
+            append(Move, Tmp(X86Registers::edx), tmp(m_value));
+#endif
+            return;
+        }
+
         case BitAnd: {
             if (m_value->child(1)->isInt(0xff)) {
                 appendUnOp<ZeroExtend8To32, ZeroExtend8To32>(m_value->child(0));
@@ -2774,9 +2795,9 @@
         RELEASE_ASSERT_NOT_REACHED();
     }
 
-#if CPU(X86) || CPU(X86_64)
     void lowerX86Div()
     {
+#if CPU(X86) || CPU(X86_64)
         Tmp eax = Tmp(X86Registers::eax);
         Tmp edx = Tmp(X86Registers::edx);
 
@@ -2799,8 +2820,26 @@
         append(Move, tmp(m_value->child(0)), eax);
         append(convertToDoubleWord, eax, edx);
         append(div, eax, edx, tmp(m_value->child(1)));
+#else
+        UNREACHABLE_FOR_PLATFORM();
+#endif
     }
+
+    void lowerX86UDiv()
+    {
+#if CPU(X86) || CPU(X86_64)
+        Tmp eax = Tmp(X86Registers::eax);
+        Tmp edx = Tmp(X86Registers::edx);
+
+        Air::Opcode div = m_value->type() == Int32 ? X86UDiv32 : X86UDiv64;
+
+        append(Move, tmp(m_value->child(0)), eax);
+        append(Xor64, edx, edx);
+        append(div, eax, edx, tmp(m_value->child(1)));
+#else
+        UNREACHABLE_FOR_PLATFORM();
 #endif
+    }
 
     IndexSet<Value> m_locked; // These are values that will have no Tmp in Air.
     IndexMap<Value, Tmp> m_valueToTmp; // These are values that must have a Tmp in Air. We say that a Value* with a non-null Tmp is "pinned".

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -122,9 +122,15 @@
     case Div:
         out.print("Div");
         return;
+    case UDiv:
+        out.print("UDiv");
+        return;
     case Mod:
         out.print("Mod");
         return;
+    case UMod:
+        out.print("UMod");
+        return;
     case Neg:
         out.print("Neg");
         return;

Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Opcode.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -78,8 +78,11 @@
     Sub,
     Mul,
     Div, // All bets are off as to what will happen when you execute this for -2^31/-1 and x/0.
+    UDiv,
     Mod, // All bets are off as to what will happen when you execute this for -2^31%-1 and x%0.
+    UMod,
 
+
     // Polymorphic negation. Note that we only need this for floating point, since integer negation
     // is exactly like Sub(0, x). But that's not true for floating point. Sub(0, 0) is 0, while
     // Neg(0) is -0. Also, we canonicalize Sub(0, x) into Neg(x) in case of integers.

Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -772,6 +772,35 @@
             }
             break;
 
+        case UDiv:
+            // Turn this: UDiv(constant1, constant2)
+            // Into this: constant1 / constant2
+            if (replaceWithNewValue(m_value->child(0)->uDivConstant(m_proc, m_value->child(1))))
+                break;
+
+            if (m_value->child(1)->hasInt()) {
+                switch (m_value->child(1)->asInt()) {
+                case 0:
+                    // Turn this: UDiv(value, 0)
+                    // Into this: 0
+                    // We can do whatever we want here so we might as well do the chill thing,
+                    // in case we add chill versions of UDiv in the future.
+                    replaceWithIdentity(m_value->child(1));
+                    break;
+
+                case 1:
+                    // Turn this: UDiv(value, 1)
+                    // Into this: value
+                    replaceWithIdentity(m_value->child(0));
+                    break;
+                default:
+                    // FIXME: We should do comprehensive strength reduction for unsigned numbers. Likely,
+                    // we will just want copy what llvm does. https://bugs.webkit.org/show_bug.cgi?id=164809
+                    break;
+                }
+            }
+            break;
+
         case Mod:
             // Turn this: Mod(constant1, constant2)
             // Into this: constant1 / constant2
@@ -829,6 +858,14 @@
             
             break;
 
+        case UMod:
+            // Turn this: UMod(constant1, constant2)
+            // Into this: constant1 / constant2
+            replaceWithNewValue(m_value->child(0)->uModConstant(m_proc, m_value->child(1)));
+            // FIXME: We should do what we do for Mod since the same principle applies here.
+            // https://bugs.webkit.org/show_bug.cgi?id=164809
+            break;
+
         case BitAnd:
             handleCommutativity();
 

Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Validate.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -190,7 +190,9 @@
             case Sub:
             case Mul:
             case Div:
+            case UDiv:
             case Mod:
+            case UMod:
             case BitAnd:
             case BitXor:
                 VALIDATE(!value->kind().traps(), ("At ", *value));

Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Value.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -298,11 +298,21 @@
     return nullptr;
 }
 
+Value* Value::uDivConstant(Procedure&, const Value*) const
+{
+    return nullptr;
+}
+
 Value* Value::modConstant(Procedure&, const Value*) const
 {
     return nullptr;
 }
 
+Value* Value::uModConstant(Procedure&, const Value*) const
+{
+    return nullptr;
+}
+
 Value* Value::bitAndConstant(Procedure&, const Value*) const
 {
     return nullptr;
@@ -569,7 +579,9 @@
     case Select:
         break;
     case Div:
+    case UDiv:
     case Mod:
+    case UMod:
         result.controlDependent = true;
         break;
     case Load8Z:
@@ -675,7 +687,9 @@
     case Sub:
     case Mul:
     case Div:
+    case UDiv:
     case Mod:
+    case UMod:
     case BitAnd:
     case BitOr:
     case BitXor:
@@ -753,7 +767,9 @@
     case Sub:
     case Mul:
     case Div:
+    case UDiv:
     case Mod:
+    case UMod:
     case Neg:
     case BitAnd:
     case BitOr:

Modified: trunk/Source/_javascript_Core/b3/B3Value.h (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3Value.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3Value.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -166,7 +166,9 @@
     virtual Value* checkMulConstant(Procedure&, const Value* other) const;
     virtual Value* checkNegConstant(Procedure&) const;
     virtual Value* divConstant(Procedure&, const Value* other) const; // This chooses Div<Chill> semantics for integers.
+    virtual Value* uDivConstant(Procedure&, const Value* other) const;
     virtual Value* modConstant(Procedure&, const Value* other) const; // This chooses Mod<Chill> semantics.
+    virtual Value* uModConstant(Procedure&, const Value* other) const;
     virtual Value* bitAndConstant(Procedure&, const Value* other) const;
     virtual Value* bitOrConstant(Procedure&, const Value* other) const;
     virtual Value* bitXorConstant(Procedure&, const Value* other) const;
@@ -322,7 +324,9 @@
         case Sub:
         case Mul:
         case Div:
+        case UDiv:
         case Mod:
+        case UMod:
         case BitAnd:
         case BitOr:
         case BitXor:

Modified: trunk/Source/_javascript_Core/b3/B3ValueKey.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/B3ValueKey.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/B3ValueKey.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -76,7 +76,10 @@
     case Add:
     case Sub:
     case Mul:
+    case Div:
+    case UDiv:
     case Mod:
+    case UMod:
     case BitAnd:
     case BitOr:
     case BitXor:
@@ -91,7 +94,6 @@
     case Below:
     case AboveEqual:
     case BelowEqual:
-    case Div:
         return proc.add<Value>(kind(), type(), origin, child(proc, 0), child(proc, 1));
     case Select:
         return proc.add<Value>(kind(), type(), origin, child(proc, 0), child(proc, 1), child(proc, 2));

Modified: trunk/Source/_javascript_Core/b3/air/AirInstInlines.h (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/air/AirInstInlines.h	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/air/AirInstInlines.h	2016-11-16 04:47:20 UTC (rev 208781)
@@ -240,11 +240,21 @@
     return isX86DivHelperValid(inst);
 }
 
+inline bool isX86UDiv32Valid(const Inst& inst)
+{
+    return isX86DivHelperValid(inst);
+}
+
 inline bool isX86Div64Valid(const Inst& inst)
 {
     return isX86DivHelperValid(inst);
 }
 
+inline bool isX86UDiv64Valid(const Inst& inst)
+{
+    return isX86DivHelperValid(inst);
+}
+
 } } } // namespace JSC::B3::Air
 
 #endif // ENABLE(B3_JIT)

Modified: trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/air/AirOpcode.opcodes	2016-11-16 04:47:20 UTC (rev 208781)
@@ -251,9 +251,15 @@
 arm64: Div32 U:G:32, U:G:32, ZD:G:32
     Tmp, Tmp, Tmp
 
+arm64: UDiv32 U:G:32, U:G:32, ZD:G:32
+    Tmp, Tmp, Tmp
+
 arm64: Div64 U:G:64, U:G:64, D:G:64
     Tmp, Tmp, Tmp
 
+arm64: UDiv64 U:G:64, U:G:64, D:G:64
+    Tmp, Tmp, Tmp
+
 MulDouble U:F:64, U:F:64, D:F:64
     Tmp, Tmp, Tmp
     x86: Addr, Tmp, Tmp
@@ -297,9 +303,15 @@
 x86: X86Div32 UZD:G:32, UZD:G:32, U:G:32
     Tmp*, Tmp*, Tmp
 
+x86: X86UDiv32 UZD:G:32, UZD:G:32, U:G:32
+    Tmp*, Tmp*, Tmp
+
 x86_64: X86Div64 UZD:G:64, UZD:G:64, U:G:64
     Tmp*, Tmp*, Tmp
 
+x86_64: X86UDiv64 UZD:G:64, UZD:G:64, U:G:64
+    Tmp*, Tmp*, Tmp
+
 Lea32 UA:G:32, D:G:32
     Addr, Tmp
     x86: Index, Tmp as x86Lea32

Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (208780 => 208781)


--- trunk/Source/_javascript_Core/b3/testb3.cpp	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp	2016-11-16 04:47:20 UTC (rev 208781)
@@ -1757,6 +1757,74 @@
     CHECK(isIdentical(effect, static_cast<double>(a) / static_cast<double>(b)));
 }
 
+void testUDivArgsInt32(uint32_t a, uint32_t b)
+{
+    // UDiv with denominator == 0 is invalid.
+    if (!b)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
+    root->appendNew<Value>(proc, Return, Origin(), result);
+
+    CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a / b);
+}
+
+void testUDivArgsInt64(uint64_t a, uint64_t b)
+{
+    // UDiv with denominator == 0 is invalid.
+    if (!b)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+    Value* result = root->appendNew<Value>(proc, UDiv, Origin(), argument1, argument2);
+    root->appendNew<Value>(proc, Return, Origin(), result);
+
+    CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a / b);
+}
+
+void testUModArgsInt32(uint32_t a, uint32_t b)
+{
+    // UMod with denominator == 0 is invalid.
+    if (!b)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+    Value* argument2 = root->appendNew<Value>(proc, Trunc, Origin(),
+        root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+    Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
+    root->appendNew<Value>(proc, Return, Origin(), result);
+
+    CHECK_EQ(compileAndRun<uint32_t>(proc, a, b), a % b);
+}
+
+void testUModArgsInt64(uint64_t a, uint64_t b)
+{
+    // UMod with denominator == 0 is invalid.
+    if (!b)
+        return;
+
+    Procedure proc;
+    BasicBlock* root = proc.addBlock();
+    Value* argument1 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+    Value* argument2 = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1);
+    Value* result = root->appendNew<Value>(proc, UMod, Origin(), argument1, argument2);
+    root->appendNew<Value>(proc, Return, Origin(), result);
+    
+    CHECK_EQ(compileAndRun<uint64_t>(proc, a, b), a % b);
+}
+
 void testSubArg(int a)
 {
     Procedure proc;
@@ -14053,6 +14121,9 @@
     RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
 
+    RUN_BINARY(testUDivArgsInt32, int32Operands(), int32Operands());
+    RUN_BINARY(testUDivArgsInt64, int64Operands(), int64Operands());
+
     RUN_UNARY(testModArgDouble, floatingPointOperands<double>());
     RUN_BINARY(testModArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
     RUN_BINARY(testModArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
@@ -14064,6 +14135,9 @@
     RUN_BINARY(testModImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
     RUN_BINARY(testModImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
 
+    RUN_BINARY(testUModArgsInt32, int32Operands(), int32Operands());
+    RUN_BINARY(testUModArgsInt64, int64Operands(), int64Operands());
+
     RUN(testSubArg(24));
     RUN(testSubArgs(1, 1));
     RUN(testSubArgs(1, 2));

Modified: trunk/Source/_javascript_Core/wasm/wasm.json (208780 => 208781)


--- trunk/Source/_javascript_Core/wasm/wasm.json	2016-11-16 04:07:30 UTC (rev 208780)
+++ trunk/Source/_javascript_Core/wasm/wasm.json	2016-11-16 04:47:20 UTC (rev 208781)
@@ -96,9 +96,9 @@
         "i32.sub":             { "category": "arithmetic", "value":  65, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Sub"          },
         "i32.mul":             { "category": "arithmetic", "value":  66, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mul"          },
         "i32.div_s":           { "category": "arithmetic", "value":  67, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Div"          },
-        "i32.div_u":           { "category": "arithmetic", "value":  68, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.div_u":           { "category": "arithmetic", "value":  68, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UDiv"         },
         "i32.rem_s":           { "category": "arithmetic", "value":  69, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "Mod"          },
-        "i32.rem_u":           { "category": "arithmetic", "value":  70, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": []                         },
+        "i32.rem_u":           { "category": "arithmetic", "value":  70, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "UMod"         },
         "i32.and":             { "category": "arithmetic", "value":  71, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitAnd"       },
         "i32.or":              { "category": "arithmetic", "value":  72, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitOr"        },
         "i32.xor":             { "category": "arithmetic", "value":  73, "return": ["i32"],      "parameter": ["i32", "i32"],           "immediate": [], "b3op": "BitXor"       },
@@ -125,9 +125,9 @@
         "i64.sub":             { "category": "arithmetic", "value":  92, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Sub"          },
         "i64.mul":             { "category": "arithmetic", "value":  93, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mul"          },
         "i64.div_s":           { "category": "arithmetic", "value":  94, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Div"          },
-        "i64.div_u":           { "category": "arithmetic", "value":  95, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.div_u":           { "category": "arithmetic", "value":  95, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
         "i64.rem_s":           { "category": "arithmetic", "value":  96, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "Mod"          },
-        "i64.rem_u":           { "category": "arithmetic", "value":  97, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": []                         },
+        "i64.rem_u":           { "category": "arithmetic", "value":  97, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "UDiv"         },
         "i64.and":             { "category": "arithmetic", "value":  98, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitAnd"       },
         "i64.or":              { "category": "arithmetic", "value":  99, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitOr"        },
         "i64.xor":             { "category": "arithmetic", "value": 100, "return": ["i64"],      "parameter": ["i64", "i64"],           "immediate": [], "b3op": "BitXor"       },
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to