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" },