Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (193932 => 193933)
--- trunk/Source/_javascript_Core/ChangeLog 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-12-11 00:31:51 UTC (rev 193933)
@@ -1,3 +1,80 @@
+2015-12-10 Benjamin Poulain <bpoul...@apple.com>
+
+ [JSC] Add a Modulo operator to B3, and a chill variant
+ https://bugs.webkit.org/show_bug.cgi?id=152110
+
+ Reviewed by Geoffrey Garen.
+
+ It is basically refactoring the Div and ChillDiv
+ code to be used by both opcodes.
+
+ * b3/B3Common.h:
+ (JSC::B3::chillDiv):
+ (JSC::B3::chillMod):
+ * b3/B3Const32Value.cpp:
+ (JSC::B3::Const32Value::modConstant):
+ * b3/B3Const32Value.h:
+ * b3/B3Const64Value.cpp:
+ (JSC::B3::Const64Value::modConstant):
+ * b3/B3Const64Value.h:
+ * b3/B3ConstDoubleValue.cpp:
+ (JSC::B3::ConstDoubleValue::modConstant):
+ * b3/B3ConstDoubleValue.h:
+ * b3/B3LowerMacros.cpp:
+ * b3/B3LowerToAir.cpp:
+ (JSC::B3::Air::LowerToAir::lower):
+ (JSC::B3::Air::LowerToAir::lowerX86Div):
+ * b3/B3Opcode.cpp:
+ (WTF::printInternal):
+ * b3/B3Opcode.h:
+ * b3/B3ReduceStrength.cpp:
+ * b3/B3Validate.cpp:
+ * b3/B3Value.cpp:
+ (JSC::B3::Value::modConstant):
+ (JSC::B3::Value::effects):
+ (JSC::B3::Value::key):
+ (JSC::B3::Value::typeFor):
+ * b3/B3Value.h:
+ * b3/testb3.cpp:
+ (JSC::B3::testModArgDouble):
+ (JSC::B3::testModArgsDouble):
+ (JSC::B3::testModArgImmDouble):
+ (JSC::B3::testModImmArgDouble):
+ (JSC::B3::testModImmsDouble):
+ (JSC::B3::testModArgFloat):
+ (JSC::B3::testModArgsFloat):
+ (JSC::B3::testModArgImmFloat):
+ (JSC::B3::testModImmArgFloat):
+ (JSC::B3::testModImmsFloat):
+ (JSC::B3::testModArg):
+ (JSC::B3::testModArgs):
+ (JSC::B3::testModImms):
+ (JSC::B3::testModArg32):
+ (JSC::B3::testModArgs32):
+ (JSC::B3::testModImms32):
+ (JSC::B3::testChillModArg):
+ (JSC::B3::testChillModArgs):
+ (JSC::B3::testChillModImms):
+ (JSC::B3::testChillModArg32):
+ (JSC::B3::testChillModArgs32):
+ (JSC::B3::testChillModImms32):
+ (JSC::B3::run):
+ * ftl/FTLB3Output.h:
+ (JSC::FTL::Output::mod):
+ (JSC::FTL::Output::chillMod):
+ (JSC::FTL::Output::doubleMod):
+ (JSC::FTL::Output::rem): Deleted.
+ (JSC::FTL::Output::doubleRem): Deleted.
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileArithMod):
+ * ftl/FTLOutput.cpp:
+ (JSC::FTL::Output::chillMod):
+ * ftl/FTLOutput.h:
+ (JSC::FTL::Output::mod):
+ (JSC::FTL::Output::doubleMod):
+ (JSC::FTL::Output::rem): Deleted.
+ (JSC::FTL::Output::doubleRem): Deleted.
+
2015-12-10 Csaba Osztrogonác <o...@webkit.org>
[B3] Add new files to the cmake build system
Modified: trunk/Source/_javascript_Core/b3/B3Common.h (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Common.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Common.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -94,22 +94,24 @@
return isRepresentableAsImpl<ResultType, double, int64_t>(value);
}
-inline int32_t chillDiv(int32_t num, int32_t den)
+template<typename IntType>
+static IntType chillDiv(IntType numerator, IntType denominator)
{
- if (!den)
+ if (!denominator)
return 0;
- if (den == -1 && num == std::numeric_limits<int32_t>::min())
- return num;
- return num / den;
+ if (denominator == -1 && numerator == std::numeric_limits<IntType>::min())
+ return std::numeric_limits<IntType>::min();
+ return numerator / denominator;
}
-inline int64_t chillDiv(int64_t num, int64_t den)
+template<typename IntType>
+static IntType chillMod(IntType numerator, IntType denominator)
{
- if (!den)
+ if (!denominator)
return 0;
- if (den == -1 && num == std::numeric_limits<int64_t>::min())
- return num;
- return num / den;
+ if (denominator == -1 && numerator == std::numeric_limits<IntType>::min())
+ return 0;
+ return numerator % denominator;
}
} } // namespace JSC::B3
Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Const32Value.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -112,6 +112,13 @@
return proc.add<Const32Value>(origin(), chillDiv(m_value, other->asInt32()));
}
+Value* Const32Value::modConstant(Procedure& proc, const Value* other) const
+{
+ if (!other->hasInt32())
+ return nullptr;
+ return proc.add<Const32Value>(origin(), chillMod(m_value, other->asInt32()));
+}
+
Value* Const32Value::bitAndConstant(Procedure& proc, const Value* other) const
{
if (!other->hasInt32())
Modified: trunk/Source/_javascript_Core/b3/B3Const32Value.h (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Const32Value.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Const32Value.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -50,6 +50,7 @@
Value* checkMulConstant(Procedure&, const Value* other) const override;
Value* checkNegConstant(Procedure&) const override;
Value* divConstant(Procedure&, const Value* other) const override;
+ Value* modConstant(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 (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Const64Value.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -112,6 +112,13 @@
return proc.add<Const64Value>(origin(), chillDiv(m_value, other->asInt64()));
}
+Value* Const64Value::modConstant(Procedure& proc, const Value* other) const
+{
+ if (!other->hasInt64())
+ return nullptr;
+ return proc.add<Const64Value>(origin(), chillMod(m_value, other->asInt64()));
+}
+
Value* Const64Value::bitAndConstant(Procedure& proc, const Value* other) const
{
if (!other->hasInt64())
Modified: trunk/Source/_javascript_Core/b3/B3Const64Value.h (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Const64Value.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Const64Value.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -50,6 +50,7 @@
Value* checkMulConstant(Procedure&, const Value* other) const override;
Value* checkNegConstant(Procedure&) const override;
Value* divConstant(Procedure&, const Value* other) const override;
+ Value* modConstant(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/B3ConstDoubleValue.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -91,6 +91,13 @@
return proc.add<ConstDoubleValue>(origin(), m_value / other->asDouble());
}
+Value* ConstDoubleValue::modConstant(Procedure& proc, const Value* other) const
+{
+ if (!other->hasDouble())
+ return nullptr;
+ return proc.add<ConstDoubleValue>(origin(), fmod(m_value, other->asDouble()));
+}
+
TriState ConstDoubleValue::equalConstant(const Value* other) const
{
if (!other->hasDouble())
Modified: trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3ConstDoubleValue.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -45,6 +45,7 @@
Value* addConstant(Procedure&, const Value* other) const override;
Value* subConstant(Procedure&, const Value* other) const override;
Value* divConstant(Procedure&, const Value* other) const override;
+ Value* modConstant(Procedure&, const Value* other) const override;
Value* mulConstant(Procedure&, const Value* other) const override;
Value* bitwiseCastConstant(Procedure&) const override;
Value* doubleToFloatConstant(Procedure&) const override;
Modified: trunk/Source/_javascript_Core/b3/B3LowerMacros.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3LowerMacros.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3LowerMacros.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -30,6 +30,8 @@
#include "B3BasicBlockInlines.h"
#include "B3BlockInsertionSet.h"
+#include "B3CCallValue.h"
+#include "B3ConstPtrValue.h"
#include "B3ControlValue.h"
#include "B3InsertionSetInlines.h"
#include "B3PhaseScope.h"
@@ -37,6 +39,7 @@
#include "B3SwitchValue.h"
#include "B3UpsilonValue.h"
#include "B3ValueInlines.h"
+#include <cmath>
namespace JSC { namespace B3 {
@@ -72,105 +75,36 @@
m_value = m_block->at(m_index);
m_origin = m_value->origin();
switch (m_value->opcode()) {
+ case Mod: {
+ if (m_value->type() == Double) {
+ Value* functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, fmod);
+ Value* result = m_insertionSet.insert<CCallValue>(m_index, Double, m_origin,
+ Effects::none(),
+ functionAddress,
+ m_value->child(0),
+ m_value->child(1));
+ m_value->replaceWithIdentity(result);
+ } else if (m_value->type() == Float) {
+ Value* numeratorAsDouble = m_insertionSet.insert<Value>(m_index, FloatToDouble, m_origin, m_value->child(0));
+ Value* denominatorAsDouble = m_insertionSet.insert<Value>(m_index, FloatToDouble, m_origin, m_value->child(1));
+ Value* functionAddress = m_insertionSet.insert<ConstPtrValue>(m_index, m_origin, fmod);
+ Value* doubleMod = m_insertionSet.insert<CCallValue>(m_index, Double, m_origin,
+ Effects::none(),
+ functionAddress,
+ numeratorAsDouble,
+ denominatorAsDouble);
+ Value* result = m_insertionSet.insert<Value>(m_index, DoubleToFloat, m_origin, doubleMod);
+ m_value->replaceWithIdentity(result);
+ }
+ break;
+ }
case ChillDiv: {
- // ARM supports this instruction natively.
- if (isARM64())
- break;
+ makeDivisionChill(Div);
+ break;
+ }
- m_changed = true;
-
- // We implement "res = ChillDiv(num, den)" as follows:
- //
- // if (den + 1 <=_unsigned 1) {
- // if (!den) {
- // res = 0;
- // goto done;
- // }
- // if (num == -2147483648) {
- // res = num;
- // goto done;
- // }
- // }
- // res = num / dev;
- // done:
-
- Value* num = m_value->child(0);
- Value* den = m_value->child(1);
-
- Value* _one_ =
- m_insertionSet.insertIntConstant(m_index, m_value, 1);
- Value* isDenOK = m_insertionSet.insert<Value>(
- m_index, Above, m_origin,
- m_insertionSet.insert<Value>(m_index, Add, m_origin, den, one),
- one);
-
- BasicBlock* before =
- m_blockInsertionSet.splitForward(m_block, m_index, &m_insertionSet);
-
- BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
- BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
-
- before->replaceLastWithNew<ControlValue>(
- m_proc, Branch, m_origin, isDenOK,
- FrequentedBlock(normalDivCase, FrequencyClass::Normal),
- FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
-
- UpsilonValue* normalResult = normalDivCase->appendNew<UpsilonValue>(
- m_proc, m_origin,
- normalDivCase->appendNew<Value>(m_proc, Div, m_origin, num, den));
- normalDivCase->appendNew<ControlValue>(
- m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- shadyDenCase->appendNew<ControlValue>(
- m_proc, Branch, m_origin, den,
- FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
- FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
-
- UpsilonValue* zeroResult = zeroDenCase->appendNew<UpsilonValue>(
- m_proc, m_origin,
- zeroDenCase->appendIntConstant(m_proc, m_value, 0));
- zeroDenCase->appendNew<ControlValue>(
- m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- int64_t badNumeratorConst;
- switch (m_value->type()) {
- case Int32:
- badNumeratorConst = std::numeric_limits<int32_t>::min();
- break;
- case Int64:
- badNumeratorConst = std::numeric_limits<int64_t>::min();
- break;
- default:
- ASSERT_NOT_REACHED();
- badNumeratorConst = 0;
- }
-
- Value* badNumerator =
- neg1DenCase->appendIntConstant(m_proc, m_value, badNumeratorConst);
-
- neg1DenCase->appendNew<ControlValue>(
- m_proc, Branch, m_origin,
- neg1DenCase->appendNew<Value>(
- m_proc, Equal, m_origin, num, badNumerator),
- FrequentedBlock(intMinCase, FrequencyClass::Rare),
- FrequentedBlock(normalDivCase, FrequencyClass::Normal));
-
- UpsilonValue* intMinResult = intMinCase->appendNew<UpsilonValue>(
- m_proc, m_origin, badNumerator);
- intMinCase->appendNew<ControlValue>(
- m_proc, Jump, m_origin, FrequentedBlock(m_block));
-
- Value* phi = m_insertionSet.insert<Value>(
- m_index, Phi, m_value->type(), m_origin);
- normalResult->setPhi(phi);
- zeroResult->setPhi(phi);
- intMinResult->setPhi(phi);
-
- m_value->replaceWithIdentity(phi);
- before->updatePredecessorsAfter();
+ case ChillMod: {
+ makeDivisionChill(Mod);
break;
}
@@ -199,6 +133,108 @@
m_insertionSet.execute(m_block);
}
+ void makeDivisionChill(Opcode nonChillOpcode)
+ {
+ ASSERT(nonChillOpcode == Div || nonChillOpcode == Mod);
+
+ // ARM supports this instruction natively.
+ if (isARM64())
+ return;
+
+ // We implement "res = ChillDiv/ChillMod(num, den)" as follows:
+ //
+ // if (den + 1 <=_unsigned 1) {
+ // if (!den) {
+ // res = 0;
+ // goto done;
+ // }
+ // if (num == -2147483648) {
+ // res = isDiv ? num : 0;
+ // goto done;
+ // }
+ // }
+ // res = num (/ or %) dev;
+ // done:
+ m_changed = true;
+
+ Value* num = m_value->child(0);
+ Value* den = m_value->child(1);
+
+ Value* _one_ = m_insertionSet.insertIntConstant(m_index, m_value, 1);
+ Value* isDenOK = m_insertionSet.insert<Value>(
+ m_index, Above, m_origin,
+ m_insertionSet.insert<Value>(m_index, Add, m_origin, den, one),
+ one);
+
+ BasicBlock* before = m_blockInsertionSet.splitForward(m_block, m_index, &m_insertionSet);
+
+ BasicBlock* normalDivCase = m_blockInsertionSet.insertBefore(m_block);
+ BasicBlock* shadyDenCase = m_blockInsertionSet.insertBefore(m_block);
+ BasicBlock* zeroDenCase = m_blockInsertionSet.insertBefore(m_block);
+ BasicBlock* neg1DenCase = m_blockInsertionSet.insertBefore(m_block);
+ BasicBlock* intMinCase = m_blockInsertionSet.insertBefore(m_block);
+
+ before->replaceLastWithNew<ControlValue>(
+ m_proc, Branch, m_origin, isDenOK,
+ FrequentedBlock(normalDivCase, FrequencyClass::Normal),
+ FrequentedBlock(shadyDenCase, FrequencyClass::Rare));
+
+ UpsilonValue* normalResult = normalDivCase->appendNew<UpsilonValue>(
+ m_proc, m_origin,
+ normalDivCase->appendNew<Value>(m_proc, nonChillOpcode, m_origin, num, den));
+ normalDivCase->appendNew<ControlValue>(
+ m_proc, Jump, m_origin, FrequentedBlock(m_block));
+
+ shadyDenCase->appendNew<ControlValue>(
+ m_proc, Branch, m_origin, den,
+ FrequentedBlock(neg1DenCase, FrequencyClass::Normal),
+ FrequentedBlock(zeroDenCase, FrequencyClass::Rare));
+
+ UpsilonValue* zeroResult = zeroDenCase->appendNew<UpsilonValue>(
+ m_proc, m_origin,
+ zeroDenCase->appendIntConstant(m_proc, m_value, 0));
+ zeroDenCase->appendNew<ControlValue>(
+ m_proc, Jump, m_origin, FrequentedBlock(m_block));
+
+ int64_t badNumeratorConst = 0;
+ switch (m_value->type()) {
+ case Int32:
+ badNumeratorConst = std::numeric_limits<int32_t>::min();
+ break;
+ case Int64:
+ badNumeratorConst = std::numeric_limits<int64_t>::min();
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ badNumeratorConst = 0;
+ }
+
+ Value* badNumerator =
+ neg1DenCase->appendIntConstant(m_proc, m_value, badNumeratorConst);
+
+ neg1DenCase->appendNew<ControlValue>(
+ m_proc, Branch, m_origin,
+ neg1DenCase->appendNew<Value>(
+ m_proc, Equal, m_origin, num, badNumerator),
+ FrequentedBlock(intMinCase, FrequencyClass::Rare),
+ FrequentedBlock(normalDivCase, FrequencyClass::Normal));
+
+ Value* intMinResult = nonChillOpcode == Div ? badNumerator : intMinCase->appendIntConstant(m_proc, m_value, 0);
+ UpsilonValue* intMinResultUpsilon = intMinCase->appendNew<UpsilonValue>(
+ m_proc, m_origin, intMinResult);
+ intMinCase->appendNew<ControlValue>(
+ m_proc, Jump, m_origin, FrequentedBlock(m_block));
+
+ Value* phi = m_insertionSet.insert<Value>(
+ m_index, Phi, m_value->type(), m_origin);
+ normalResult->setPhi(phi);
+ zeroResult->setPhi(phi);
+ intMinResultUpsilon->setPhi(phi);
+
+ m_value->replaceWithIdentity(phi);
+ before->updatePredecessorsAfter();
+ }
+
void recursivelyBuildSwitch(
const Vector<SwitchCase>& cases, unsigned start, bool hardStart, unsigned end,
BasicBlock* before)
Modified: trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3LowerToAir.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -1441,29 +1441,8 @@
case Div: {
if (isInt(m_value->type())) {
- Tmp eax = Tmp(X86Registers::eax);
- Tmp edx = Tmp(X86Registers::edx);
-
- Air::Opcode convertToDoubleWord;
- Air::Opcode div;
- switch (m_value->type()) {
- case Int32:
- convertToDoubleWord = X86ConvertToDoubleWord32;
- div = X86Div32;
- break;
- case Int64:
- convertToDoubleWord = X86ConvertToQuadWord64;
- div = X86Div64;
- break;
- default:
- RELEASE_ASSERT_NOT_REACHED();
- return;
- }
-
- append(Move, tmp(m_value->child(0)), eax);
- append(convertToDoubleWord, eax, edx);
- append(div, eax, edx, tmp(m_value->child(1)));
- append(Move, eax, tmp(m_value));
+ lowerX86Div();
+ append(Move, Tmp(X86Registers::eax), tmp(m_value));
return;
}
ASSERT(isFloat(m_value->type()));
@@ -1472,6 +1451,12 @@
return;
}
+ case Mod: {
+ lowerX86Div();
+ append(Move, Tmp(X86Registers::edx), tmp(m_value));
+ return;
+ }
+
case BitAnd: {
appendBinOp<And32, And64, Commutative>(
m_value->child(0), m_value->child(1));
@@ -1977,6 +1962,32 @@
dataLog("FATAL: could not lower ", deepDump(m_value), "\n");
RELEASE_ASSERT_NOT_REACHED();
}
+
+ void lowerX86Div()
+ {
+ Tmp eax = Tmp(X86Registers::eax);
+ Tmp edx = Tmp(X86Registers::edx);
+
+ Air::Opcode convertToDoubleWord;
+ Air::Opcode div;
+ switch (m_value->type()) {
+ case Int32:
+ convertToDoubleWord = X86ConvertToDoubleWord32;
+ div = X86Div32;
+ break;
+ case Int64:
+ convertToDoubleWord = X86ConvertToQuadWord64;
+ div = X86Div64;
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return;
+ }
+
+ append(Move, tmp(m_value->child(0)), eax);
+ append(convertToDoubleWord, eax, edx);
+ append(div, eax, edx, tmp(m_value->child(1)));
+ }
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 (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Opcode.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -116,11 +116,14 @@
case Div:
out.print("Div");
return;
+ case Mod:
+ out.print("Mod");
+ return;
case ChillDiv:
out.print("ChillDiv");
return;
- case Mod:
- out.print("Mod");
+ case ChillMod:
+ out.print("ChillMod");
return;
case BitAnd:
out.print("BitAnd");
Modified: trunk/Source/_javascript_Core/b3/B3Opcode.h (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Opcode.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Opcode.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -71,10 +71,11 @@
Sub,
Mul,
Div, // All bets are off as to what will happen when you execute this for -2^31/-1 and x/0.
+ Mod, // All bets are off as to what will happen when you execute this for -2^31%-1 and x%0.
// Integer math.
ChillDiv, // doesn't trap ever, behaves like JS (x/y)|0.
- Mod,
+ ChillMod, // doesn't trap ever, behaves like JS (x%y)|0.
BitAnd,
BitOr,
BitXor,
Modified: trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3ReduceStrength.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -291,6 +291,11 @@
replaceWithNewValue(m_value->child(0)->divConstant(m_proc, m_value->child(1)));
break;
+ case Mod:
+ case ChillMod:
+ replaceWithNewValue(m_value->child(0)->modConstant(m_proc, m_value->child(1)));
+ break;
+
case BitAnd:
handleCommutativity();
@@ -658,7 +663,7 @@
}
// Turn this: Load(constant1, offset = constant2)
- // Into this: Laod(constant1 + constant2)
+ // Into this: Load(constant1 + constant2)
//
// This is a fun canonicalization. It purely regresses naively generated code. We rely
// on constant materialization to be smart enough to materialize this constant the smart
@@ -677,6 +682,18 @@
break;
}
+ case CCall:
+ // Turn this: Call(fmod, constant1, constant2)
+ // Into this: fcall-constant(constant1, constant2)
+ if (m_value->type() == Double
+ && m_value->numChildren() == 3
+ && m_value->child(0)->isIntPtr(reinterpret_cast<intptr_t>(fmod))
+ && m_value->child(1)->type() == Double
+ && m_value->child(2)->type() == Double) {
+ replaceWithNewValue(m_value->child(1)->modConstant(m_proc, m_value->child(2)));
+ }
+ break;
+
case Equal:
handleCommutativity();
Modified: trunk/Source/_javascript_Core/b3/B3Validate.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Validate.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Validate.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -153,13 +153,14 @@
case Sub:
case Mul:
case Div:
+ case Mod:
VALIDATE(value->numChildren() == 2, ("At ", *value));
VALIDATE(value->type() == value->child(0)->type(), ("At ", *value));
VALIDATE(value->type() == value->child(1)->type(), ("At ", *value));
VALIDATE(value->type() != Void, ("At ", *value));
break;
case ChillDiv:
- case Mod:
+ case ChillMod:
case BitAnd:
case BitOr:
case BitXor:
Modified: trunk/Source/_javascript_Core/b3/B3Value.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Value.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Value.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -164,6 +164,11 @@
return nullptr;
}
+Value* Value::modConstant(Procedure&, const Value*) const
+{
+ return nullptr;
+}
+
Value* Value::bitAndConstant(Procedure&, const Value*) const
{
return nullptr;
@@ -337,7 +342,7 @@
case Sub:
case Mul:
case ChillDiv:
- case Mod:
+ case ChillMod:
case BitAnd:
case BitOr:
case BitXor:
@@ -369,6 +374,7 @@
case Select:
break;
case Div:
+ case Mod:
result.controlDependent = true;
break;
case Load8Z:
@@ -436,8 +442,10 @@
case Add:
case Sub:
case Mul:
+ case Div:
+ case Mod:
case ChillDiv:
- case Mod:
+ case ChillMod:
case BitAnd:
case BitOr:
case BitXor:
@@ -452,7 +460,6 @@
case Below:
case AboveEqual:
case BelowEqual:
- case Div:
case CheckAdd:
case CheckSub:
case CheckMul:
@@ -514,8 +521,9 @@
case Sub:
case Mul:
case Div:
+ case Mod:
case ChillDiv:
- case Mod:
+ case ChillMod:
case BitAnd:
case BitOr:
case BitXor:
Modified: trunk/Source/_javascript_Core/b3/B3Value.h (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/B3Value.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/B3Value.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -121,6 +121,7 @@
virtual Value* checkMulConstant(Procedure&, const Value* other) const;
virtual Value* checkNegConstant(Procedure&) const;
virtual Value* divConstant(Procedure&, const Value* other) const; // This chooses ChillDiv semantics for integers.
+ virtual Value* modConstant(Procedure&, const Value* other) const; // This chooses ChillMod semantics for integers.
virtual Value* bitAndConstant(Procedure&, const Value* other) const;
virtual Value* bitOrConstant(Procedure&, const Value* other) const;
virtual Value* bitXorConstant(Procedure&, const Value* other) const;
Modified: trunk/Source/_javascript_Core/b3/testb3.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/b3/testb3.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/b3/testb3.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -1027,6 +1027,145 @@
CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(a / b)));
}
+void testModArgDouble(double a)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* value = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Value>(proc, Mod, Origin(), value, value));
+
+ CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, a)));
+}
+
+void testModArgsDouble(double a, double b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+ Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR1);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
+
+ CHECK(isIdentical(compileAndRun<double>(proc, a, b), fmod(a, b)));
+}
+
+void testModArgImmDouble(double a, double b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* valueA = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+ Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
+
+ CHECK(isIdentical(compileAndRun<double>(proc, a), fmod(a, b)));
+}
+
+void testModImmArgDouble(double a, double b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
+ Value* valueB = root->appendNew<ArgumentRegValue>(proc, Origin(), FPRInfo::argumentFPR0);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
+
+ CHECK(isIdentical(compileAndRun<double>(proc, b), fmod(a, b)));
+}
+
+void testModImmsDouble(double a, double b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* valueA = root->appendNew<ConstDoubleValue>(proc, Origin(), a);
+ Value* valueB = root->appendNew<ConstDoubleValue>(proc, Origin(), b);
+ root->appendNew<ControlValue>(
+ proc, Return, Origin(),
+ root->appendNew<Value>(proc, Mod, Origin(), valueA, valueB));
+
+ CHECK(isIdentical(compileAndRun<double>(proc), fmod(a, b)));
+}
+
+void testModArgFloat(float a)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, floatValue);
+ Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+
+ CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, a)))));
+}
+
+void testModArgsFloat(float a, float b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argument1int32 = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* argument2int32 = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR1));
+ Value* floatValue1 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument1int32);
+ Value* floatValue2 = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument2int32);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue1, floatValue2);
+ Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+ CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a), bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
+}
+
+void testModArgImmFloat(float a, float b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+ Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), b);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), floatValue, constValue);
+ Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+ CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(a)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
+}
+
+void testModImmArgFloat(float a, float b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* argument32 = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* floatValue = root->appendNew<Value>(proc, BitwiseCast, Origin(), argument32);
+ Value* constValue = root->appendNew<ConstFloatValue>(proc, Origin(), a);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue, floatValue);
+ Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+ CHECK(isIdentical(compileAndRun<int32_t>(proc, bitwise_cast<int32_t>(b)), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
+}
+
+void testModImmsFloat(float a, float b)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+ Value* constValue1 = root->appendNew<ConstFloatValue>(proc, Origin(), a);
+ Value* constValue2 = root->appendNew<ConstFloatValue>(proc, Origin(), b);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), constValue1, constValue2);
+ Value* result32 = root->appendNew<Value>(proc, BitwiseCast, Origin(), result);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result32);
+
+ CHECK(isIdentical(compileAndRun<int32_t>(proc), bitwise_cast<int32_t>(static_cast<float>(fmod(a, b)))));
+}
+
void testDivArgFloatWithUselessDoubleConversion(float a)
{
Procedure proc;
@@ -6300,6 +6439,190 @@
}
}
+void testModArg(int64_t value)
+{
+ if (!value)
+ return;
+
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(!compileAndRun<int64_t>(proc, value));
+}
+
+void testModArgs(int64_t numerator, int64_t denominator)
+{
+ if (!denominator)
+ return;
+ if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1)
+ 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, Mod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testModImms(int64_t numerator, int64_t denominator)
+{
+ if (!denominator)
+ return;
+ if (numerator == std::numeric_limits<int64_t>::min() && denominator == -1)
+ return;
+
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator);
+ Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testModArg32(int32_t value)
+{
+ if (!value)
+ return;
+
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument, argument);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(!compileAndRun<int32_t>(proc, value));
+}
+
+void testModArgs32(int32_t numerator, int32_t denominator)
+{
+ if (!denominator)
+ return;
+ if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1)
+ 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, Mod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testModImms32(int32_t numerator, int32_t denominator)
+{
+ if (!denominator)
+ return;
+ if (numerator == std::numeric_limits<int32_t>::min() && denominator == -1)
+ return;
+
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator);
+ Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator);
+ Value* result = root->appendNew<Value>(proc, Mod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == numerator % denominator);
+}
+
+void testChillModArg(int64_t value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument = root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0);
+ Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument, argument);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(!compileAndRun<int64_t>(proc, value));
+}
+
+void testChillModArgs(int64_t numerator, int64_t denominator)
+{
+ 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, ChillMod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
+void testChillModImms(int64_t numerator, int64_t denominator)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument1 = root->appendNew<Const64Value>(proc, Origin(), numerator);
+ Value* argument2 = root->appendNew<Const64Value>(proc, Origin(), denominator);
+ Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int64_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
+void testChillModArg32(int32_t value)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument = root->appendNew<Value>(proc, Trunc, Origin(),
+ root->appendNew<ArgumentRegValue>(proc, Origin(), GPRInfo::argumentGPR0));
+ Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument, argument);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(!compileAndRun<int32_t>(proc, value));
+}
+
+void testChillModArgs32(int32_t numerator, int32_t denominator)
+{
+ 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, ChillMod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
+void testChillModImms32(int32_t numerator, int32_t denominator)
+{
+ Procedure proc;
+ BasicBlock* root = proc.addBlock();
+
+ Value* argument1 = root->appendNew<Const32Value>(proc, Origin(), numerator);
+ Value* argument2 = root->appendNew<Const32Value>(proc, Origin(), denominator);
+ Value* result = root->appendNew<Value>(proc, ChillMod, Origin(), argument1, argument2);
+ root->appendNew<ControlValue>(proc, Return, Origin(), result);
+
+ CHECK(compileAndRun<int32_t>(proc, numerator, denominator) == chillMod(numerator, denominator));
+}
+
void testSwitch(unsigned degree, unsigned gap = 1)
{
Procedure proc;
@@ -7059,6 +7382,17 @@
RUN_BINARY(testDivArgsFloatWithUselessDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
RUN_BINARY(testDivArgsFloatWithEffectfulDoubleConversion, floatingPointOperands<float>(), floatingPointOperands<float>());
+ RUN_UNARY(testModArgDouble, floatingPointOperands<double>());
+ RUN_BINARY(testModArgsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+ RUN_BINARY(testModArgImmDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+ RUN_BINARY(testModImmArgDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+ RUN_BINARY(testModImmsDouble, floatingPointOperands<double>(), floatingPointOperands<double>());
+ RUN_UNARY(testModArgFloat, floatingPointOperands<float>());
+ RUN_BINARY(testModArgsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+ RUN_BINARY(testModArgImmFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+ RUN_BINARY(testModImmArgFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+ RUN_BINARY(testModImmsFloat, floatingPointOperands<float>(), floatingPointOperands<float>());
+
RUN(testSubArg(24));
RUN(testSubArgs(1, 1));
RUN(testSubArgs(1, 2));
@@ -7633,6 +7967,19 @@
RUN(testChillDivTwice(4, 0, 6, 2, 3));
RUN(testChillDivTwice(4, 2, 6, 0, 2));
+ RUN_UNARY(testModArg, int64Operands());
+ RUN_BINARY(testModArgs, int64Operands(), int64Operands());
+ RUN_BINARY(testModImms, int64Operands(), int64Operands());
+ RUN_UNARY(testModArg32, int32Operands());
+ RUN_BINARY(testModArgs32, int32Operands(), int32Operands());
+ RUN_BINARY(testModImms32, int32Operands(), int32Operands());
+ RUN_UNARY(testChillModArg, int64Operands());
+ RUN_BINARY(testChillModArgs, int64Operands(), int64Operands());
+ RUN_BINARY(testChillModImms, int64Operands(), int64Operands());
+ RUN_UNARY(testChillModArg32, int32Operands());
+ RUN_BINARY(testChillModArgs32, int32Operands(), int32Operands());
+ RUN_BINARY(testChillModImms32, int32Operands(), int32Operands());
+
RUN(testSwitch(0, 1));
RUN(testSwitch(1, 1));
RUN(testSwitch(2, 1));
Modified: trunk/Source/_javascript_Core/ftl/FTLB3Output.h (193932 => 193933)
--- trunk/Source/_javascript_Core/ftl/FTLB3Output.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/ftl/FTLB3Output.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -128,7 +128,8 @@
LValue mul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
LValue div(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
LValue chillDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ChillDiv, origin(), left, right); }
- LValue rem(LValue left, LValue right) { CRASH(); }
+ LValue mod(LValue left, LValue right) { m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right); }
+ LValue chillMod(LValue left, LValue right) { m_block->appendNew<B3::Value>(m_proc, B3::ChillMod, origin(), left, right); }
LValue neg(LValue value)
{
LValue zero = m_block->appendIntConstant(m_proc, origin(), value->type(), 0);
@@ -139,7 +140,7 @@
LValue doubleSub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
LValue doubleMul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
LValue doubleDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
- LValue doubleRem(LValue left, LValue right) { return callWithoutSideEffects(B3::Double, fmod, left, right); }
+ LValue doubleMod(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right); }
LValue doubleNeg(LValue value)
{
return sub(doubleZero, value);
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -2025,89 +2025,53 @@
case Int32Use: {
LValue numerator = lowInt32(m_node->child1());
LValue denominator = lowInt32(m_node->child2());
-
- LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
- LBasicBlock done = FTL_NEW_BLOCK(m_out, ("ArithMod done"));
-
- Vector<ValueFromBlock, 3> results;
-
- LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
-
- m_out.branch(
- m_out.above(adjustedDenominator, m_out.int32One),
- usually(continuation), rarely(unsafeDenominator));
-
- LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
-
- LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
-
- // FIXME: -2^31 / -1 will actually yield negative zero, so we could have a
- // separate case for that. But it probably doesn't matter so much.
+
+ LValue remainder;
if (shouldCheckOverflow(m_node->arithMode())) {
+ LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(m_out, ("ArithMod unsafe denominator"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithMod continuation"));
+
+ LValue adjustedDenominator = m_out.add(denominator, m_out.int32One);
+ m_out.branch(
+ m_out.above(adjustedDenominator, m_out.int32One),
+ usually(continuation), rarely(unsafeDenominator));
+
+ LBasicBlock lastNext = m_out.appendTo(unsafeDenominator, continuation);
+ LValue neg2ToThe31 = m_out.constInt32(-2147483647-1);
LValue cond = m_out.bitOr(m_out.isZero32(denominator), m_out.equal(numerator, neg2ToThe31));
speculate(Overflow, noValue(), 0, cond);
m_out.jump(continuation);
- } else {
- // This is the case where we convert the result to an int after we're done. So,
- // if the denominator is zero, then the result should be result should be zero.
- // If the denominator is not zero (i.e. it's -1 because we're guarded by the
- // check above) and the numerator is -2^31 then the result should be -2^31.
-
- LBasicBlock modByZero = FTL_NEW_BLOCK(m_out, ("ArithMod modulo by zero"));
- LBasicBlock notModByZero = FTL_NEW_BLOCK(m_out, ("ArithMod not modulo by zero"));
- LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(m_out, ("ArithMod -2^31/-1"));
-
- m_out.branch(
- m_out.isZero32(denominator), rarely(modByZero), usually(notModByZero));
-
- m_out.appendTo(modByZero, notModByZero);
- results.append(m_out.anchor(m_out.int32Zero));
- m_out.jump(done);
-
- m_out.appendTo(notModByZero, neg2ToThe31ByNeg1);
- m_out.branch(
- m_out.equal(numerator, neg2ToThe31),
- rarely(neg2ToThe31ByNeg1), usually(continuation));
-
- m_out.appendTo(neg2ToThe31ByNeg1, continuation);
- results.append(m_out.anchor(m_out.int32Zero));
- m_out.jump(done);
- }
-
- m_out.appendTo(continuation, done);
-
- LValue remainder = m_out.rem(numerator, denominator);
-
+
+ m_out.appendTo(continuation, lastNext);
+ LValue result = m_out.mod(numerator, denominator);
+ remainder = result;
+ } else
+ remainder = m_out.chillMod(numerator, denominator);
+
if (shouldCheckNegativeZero(m_node->arithMode())) {
LBasicBlock negativeNumerator = FTL_NEW_BLOCK(m_out, ("ArithMod negative numerator"));
LBasicBlock numeratorContinuation = FTL_NEW_BLOCK(m_out, ("ArithMod numerator continuation"));
-
+
m_out.branch(
m_out.lessThan(numerator, m_out.int32Zero),
unsure(negativeNumerator), unsure(numeratorContinuation));
-
+
LBasicBlock innerLastNext = m_out.appendTo(negativeNumerator, numeratorContinuation);
-
+
speculate(NegativeZero, noValue(), 0, m_out.isZero32(remainder));
-
+
m_out.jump(numeratorContinuation);
-
+
m_out.appendTo(numeratorContinuation, innerLastNext);
}
-
- results.append(m_out.anchor(remainder));
- m_out.jump(done);
-
- m_out.appendTo(done, lastNext);
-
- setInt32(m_out.phi(m_out.int32, results));
+
+ setInt32(remainder);
break;
}
case DoubleRepUse: {
setDouble(
- m_out.doubleRem(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
+ m_out.doubleMod(lowDouble(m_node->child1()), lowDouble(m_node->child2())));
break;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.cpp (193932 => 193933)
--- trunk/Source/_javascript_Core/ftl/FTLOutput.cpp 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.cpp 2015-12-11 00:31:51 UTC (rev 193933)
@@ -116,6 +116,47 @@
return phi(int32, results);
}
+LValue Output::chillMod(LValue numerator, LValue denominator)
+{
+ LBasicBlock unsafeDenominator = FTL_NEW_BLOCK(*this, ("ChillMod unsafe denominator"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(*this, ("ChillMod continuation"));
+ LBasicBlock done = FTL_NEW_BLOCK(*this, ("ChillMod done"));
+ LBasicBlock divByZero = FTL_NEW_BLOCK(*this, ("ChillMod divide by zero"));
+ LBasicBlock notDivByZero = FTL_NEW_BLOCK(*this, ("ChillMod not divide by zero"));
+ LBasicBlock neg2ToThe31ByNeg1 = FTL_NEW_BLOCK(*this, ("ChillMod -2^31/-1"));
+
+ LValue adjustedDenominator = add(denominator, int32One);
+ branch(
+ above(adjustedDenominator, int32One),
+ usually(continuation), rarely(unsafeDenominator));
+
+ Vector<ValueFromBlock, 3> results;
+ LBasicBlock lastNext = appendTo(unsafeDenominator, continuation);
+
+ LValue neg2ToThe31 = constInt32(-2147483647-1);
+ branch(isZero32(denominator), rarely(divByZero), usually(notDivByZero));
+
+ appendTo(divByZero, notDivByZero);
+ results.append(anchor(int32Zero));
+ jump(done);
+
+ appendTo(notDivByZero, neg2ToThe31ByNeg1);
+ branch(equal(numerator, neg2ToThe31),
+ rarely(neg2ToThe31ByNeg1), usually(continuation));
+
+ appendTo(neg2ToThe31ByNeg1, continuation);
+ results.append(anchor(int32Zero));
+ jump(done);
+
+ appendTo(continuation, done);
+ LValue result = mod(numerator, denominator);
+ results.append(anchor(result));
+ jump(done);
+
+ appendTo(done, lastNext);
+ return phi(int32, results);
+}
+
LValue Output::sensibleDoubleToInt(LValue value)
{
RELEASE_ASSERT(isX86());
Modified: trunk/Source/_javascript_Core/ftl/FTLOutput.h (193932 => 193933)
--- trunk/Source/_javascript_Core/ftl/FTLOutput.h 2015-12-11 00:05:00 UTC (rev 193932)
+++ trunk/Source/_javascript_Core/ftl/FTLOutput.h 2015-12-11 00:31:51 UTC (rev 193933)
@@ -126,14 +126,15 @@
LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
LValue chillDiv(LValue left, LValue right);
- LValue rem(LValue left, LValue right) { return buildRem(m_builder, left, right); }
+ LValue mod(LValue left, LValue right) { return buildRem(m_builder, left, right); }
+ LValue chillMod(LValue left, LValue right);
LValue neg(LValue value) { return buildNeg(m_builder, value); }
LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
- LValue doubleRem(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
+ LValue doubleMod(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }