Index: test/cctest/compiler/test-simplified-lowering.cc |
diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc |
index 291f749fb1683fb85fade9d147c60f72fe426ff5..b75ed58abbef291185407b27d1aad139da336b27 100644 |
--- a/test/cctest/compiler/test-simplified-lowering.cc |
+++ b/test/cctest/compiler/test-simplified-lowering.cc |
@@ -69,6 +69,15 @@ class SimplifiedLoweringTester : public GraphBuilderTester<ReturnType> { |
Verifier::Run(this->graph()); |
} |
+ void CheckNumberCall(double expected, double input) { |
+ // TODO(titzer): make calls to NewNumber work in cctests. |
+ if (expected <= Smi::kMinValue) return; |
+ if (expected >= Smi::kMaxValue) return; |
+ Handle<Object> num = factory()->NewNumber(input); |
+ Object* result = this->Call(*num); |
+ CHECK(factory()->NewNumber(expected)->SameValue(result)); |
+ } |
+ |
Factory* factory() { return this->isolate()->factory(); } |
Heap* heap() { return this->isolate()->heap(); } |
}; |
@@ -1564,14 +1573,72 @@ TEST(RunNumberDivide_minus_1_TruncatingToInt32) { |
t.GenerateCode(); |
FOR_INT32_INPUTS(i) { |
- Handle<HeapNumber> num = t.factory()->NewHeapNumber(*i); |
int32_t x = 0 - *i; |
- // TODO(titzer): make calls to NewHeapNumber work in cctests. |
- if (x <= Smi::kMinValue) continue; |
- if (x >= Smi::kMaxValue) continue; |
- Handle<HeapNumber> expected = t.factory()->NewHeapNumber(x); |
- Object* result = t.Call(*num); |
- CHECK(expected->SameValue(result)); |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
+ } |
+} |
+ |
+ |
+TEST(NumberMultiply_TruncatingToInt32) { |
+ int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kInt32Mul, mul->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(RunNumberMultiply_TruncatingToInt32) { |
+ int32_t constants[] = {-100, -10, -1, 0, 1, 100, 1000, 3000999}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ double k = static_cast<double>(constants[i]); |
+ SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
+ Node* num = t.NumberToInt32(t.Parameter(0)); |
+ Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); |
+ Node* trunc = t.NumberToInt32(mul); |
+ t.Return(trunc); |
+ |
+ if (Pipeline::SupportedTarget()) { |
+ t.LowerAllNodesAndLowerChanges(); |
+ t.GenerateCode(); |
+ |
+ FOR_INT32_INPUTS(i) { |
+ int32_t x = DoubleToInt32(static_cast<double>(*i) * k); |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+TEST(RunNumberMultiply_TruncatingToUint32) { |
+ uint32_t constants[] = {0, 1, 2, 3, 4, 100, 1000, 1024, 2048, 3000999}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ double k = static_cast<double>(constants[i]); |
+ SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
+ Node* num = t.NumberToUint32(t.Parameter(0)); |
+ Node* mul = t.NumberMultiply(num, t.jsgraph.Constant(k)); |
+ Node* trunc = t.NumberToUint32(mul); |
+ t.Return(trunc); |
+ |
+ if (Pipeline::SupportedTarget()) { |
+ t.LowerAllNodesAndLowerChanges(); |
+ t.GenerateCode(); |
+ |
+ FOR_UINT32_INPUTS(i) { |
+ uint32_t x = DoubleToUint32(static_cast<double>(*i) * k); |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
} |
} |
} |
@@ -1586,24 +1653,281 @@ TEST(RunNumberDivide_2_TruncatingToUint32) { |
if (Pipeline::SupportedTarget()) { |
t.LowerAllNodesAndLowerChanges(); |
- { |
- FILE* dot_file = fopen("/tmp/test.dot", "w+"); |
- OFStream dot_of(dot_file); |
- dot_of << AsDOT(*t.jsgraph.graph()); |
- fclose(dot_file); |
- } |
t.GenerateCode(); |
FOR_UINT32_INPUTS(i) { |
- Handle<HeapNumber> num = |
- t.factory()->NewHeapNumber(static_cast<double>(*i)); |
- uint32_t x = *i / 2; |
- // TODO(titzer): make calls to NewHeapNumber work in cctests. |
- if (x >= static_cast<uint32_t>(Smi::kMaxValue)) continue; |
- Handle<HeapNumber> expected = |
- t.factory()->NewHeapNumber(static_cast<double>(x)); |
- Object* result = t.Call(*num); |
- CHECK(expected->SameValue(result)); |
+ uint32_t x = DoubleToUint32(static_cast<double>(*i / 2.0)); |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
+ } |
+} |
+ |
+ |
+TEST(NumberMultiply_ConstantOutOfRange) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(1000000023); |
+ Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mul); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode()); |
+} |
+ |
+ |
+TEST(NumberMultiply_NonTruncating) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(111); |
+ Node* mul = t.graph()->NewNode(t.simplified()->NumberMultiply(), t.p0, k); |
+ t.Return(mul); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Mul, mul->opcode()); |
+} |
+ |
+ |
+TEST(NumberDivide_TruncatingToInt32) { |
+ int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), div); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kInt32Div, div->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(RunNumberDivide_TruncatingToInt32) { |
+ int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ int32_t k = constants[i]; |
+ SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
+ Node* num = t.NumberToInt32(t.Parameter(0)); |
+ Node* div = t.NumberDivide(num, t.jsgraph.Constant(k)); |
+ Node* trunc = t.NumberToInt32(div); |
+ t.Return(trunc); |
+ |
+ if (Pipeline::SupportedTarget()) { |
+ t.LowerAllNodesAndLowerChanges(); |
+ t.GenerateCode(); |
+ |
+ FOR_INT32_INPUTS(i) { |
+ if (*i == INT_MAX) continue; // exclude max int. |
+ int32_t x = DoubleToInt32(static_cast<double>(*i) / k); |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+TEST(NumberDivide_TruncatingToUint32) { |
+ double constants[] = {1, 3, 100, 1000, 100998348}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Unsigned32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), div); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kUint32Div, div->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(RunNumberDivide_TruncatingToUint32) { |
+ uint32_t constants[] = {100, 10, 1, 1, 2, 4, 1000, 1024, 2048}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ uint32_t k = constants[i]; |
+ SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
+ Node* num = t.NumberToUint32(t.Parameter(0)); |
+ Node* div = t.NumberDivide(num, t.jsgraph.Constant(static_cast<double>(k))); |
+ Node* trunc = t.NumberToUint32(div); |
+ t.Return(trunc); |
+ |
+ if (Pipeline::SupportedTarget()) { |
+ t.LowerAllNodesAndLowerChanges(); |
+ t.GenerateCode(); |
+ |
+ FOR_UINT32_INPUTS(i) { |
+ uint32_t x = *i / k; |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
} |
} |
} |
+ |
+ |
+TEST(NumberDivide_BadConstants) { |
+ int32_t constants[] = {-1, 0}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), div); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Div, div->opcode()); |
+ } |
+ |
+ { |
+ TestingGraph t(Type::Unsigned32()); |
+ Node* k = t.jsgraph.Constant(0); |
+ Node* div = t.graph()->NewNode(t.simplified()->NumberDivide(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), div); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Div, div->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(NumberModulus_TruncatingToInt32) { |
+ int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mod); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kInt32Mod, mod->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(RunNumberModulus_TruncatingToInt32) { |
+ int32_t constants[] = {-100, -10, -1, 1, 2, 100, 1000, 1024, 2048}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ int32_t k = constants[i]; |
+ SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
+ Node* num = t.NumberToInt32(t.Parameter(0)); |
+ Node* mod = t.NumberModulus(num, t.jsgraph.Constant(k)); |
+ Node* trunc = t.NumberToInt32(mod); |
+ t.Return(trunc); |
+ |
+ if (Pipeline::SupportedTarget()) { |
+ t.LowerAllNodesAndLowerChanges(); |
+ t.GenerateCode(); |
+ |
+ FOR_INT32_INPUTS(i) { |
+ if (*i == INT_MAX) continue; // exclude max int. |
+ int32_t x = DoubleToInt32(std::fmod(static_cast<double>(*i), k)); |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+TEST(NumberModulus_TruncatingToUint32) { |
+ double constants[] = {1, 3, 100, 1000, 100998348}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Unsigned32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kUint32Mod, mod->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(RunNumberModulus_TruncatingToUint32) { |
+ uint32_t constants[] = {1, 2, 100, 1000, 1024, 2048}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ uint32_t k = constants[i]; |
+ SimplifiedLoweringTester<Object*> t(kMachAnyTagged); |
+ Node* num = t.NumberToUint32(t.Parameter(0)); |
+ Node* mod = |
+ t.NumberModulus(num, t.jsgraph.Constant(static_cast<double>(k))); |
+ Node* trunc = t.NumberToUint32(mod); |
+ t.Return(trunc); |
+ |
+ if (Pipeline::SupportedTarget()) { |
+ t.LowerAllNodesAndLowerChanges(); |
+ t.GenerateCode(); |
+ |
+ FOR_UINT32_INPUTS(i) { |
+ uint32_t x = *i % k; |
+ t.CheckNumberCall(static_cast<double>(x), static_cast<double>(*i)); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+TEST(NumberModulus_Int32) { |
+ int32_t constants[] = {-100, -10, 1, 4, 100, 1000}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
+ t.Return(mod); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); // Pesky -0 behavior. |
+ } |
+} |
+ |
+ |
+TEST(NumberModulus_Uint32) { |
+ double constants[] = {1, 3, 100, 1000, 100998348}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Unsigned32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
+ t.Return(mod); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kUint32Mod, mod->opcode()); |
+ } |
+} |
+ |
+ |
+TEST(NumberModulus_BadConstants) { |
+ int32_t constants[] = {-1, 0}; |
+ |
+ for (size_t i = 0; i < arraysize(constants); i++) { |
+ TestingGraph t(Type::Signed32()); |
+ Node* k = t.jsgraph.Constant(constants[i]); |
+ Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), mod); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); |
+ } |
+ |
+ { |
+ TestingGraph t(Type::Unsigned32()); |
+ Node* k = t.jsgraph.Constant(0); |
+ Node* mod = t.graph()->NewNode(t.simplified()->NumberModulus(), t.p0, k); |
+ Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), mod); |
+ t.Return(trunc); |
+ t.Lower(); |
+ |
+ CHECK_EQ(IrOpcode::kFloat64Mod, mod->opcode()); |
+ } |
+} |