From d6831dbd4bc53801606fa5c29861bcdab73ee00e Mon Sep 17 00:00:00 2001 From: "titzer@chromium.org" Date: Thu, 28 Aug 2014 13:31:55 +0000 Subject: [PATCH] Use TruncateFloat64ToInt32 instead of ChangeFloat64ToInt32 in lowering of simplified operators NumberToInt32/NumberToUint32. R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/509653003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23491 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/simplified-lowering.cc | 10 +- test/cctest/compiler/test-simplified-lowering.cc | 120 +++++++++++++++++++++-- 2 files changed, 118 insertions(+), 12 deletions(-) diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 72c2d37..9ccd4ed 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -453,10 +453,9 @@ class RepresentationSelector { DeferReplacement(node, node->InputAt(0)); } else { // Require the input in float64 format and perform truncation. - // TODO(turbofan): could also avoid the truncation with a tag check. + // TODO(turbofan): avoid a truncation with a smi check. VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); - // TODO(titzer): should be a truncation. - node->set_op(lowering->machine()->ChangeFloat64ToInt32()); + node->set_op(lowering->machine()->TruncateFloat64ToInt32()); } } else { // Propagate a type to the input, but pass through representation. @@ -475,11 +474,10 @@ class RepresentationSelector { DeferReplacement(node, node->InputAt(0)); } else { // Require the input in float64 format to perform truncation. - // TODO(turbofan): could also avoid the truncation with a tag check. + // TODO(turbofan): avoid the truncation with a smi check. VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); - // TODO(titzer): should be a truncation. - node->set_op(lowering->machine()->ChangeFloat64ToUint32()); + node->set_op(lowering->machine()->TruncateFloat64ToInt32()); } } else { // Propagate a type to the input, but pass through representation. diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc index ac72d78..4c86e40 100644 --- a/test/cctest/compiler/test-simplified-lowering.cc +++ b/test/cctest/compiler/test-simplified-lowering.cc @@ -95,6 +95,66 @@ ElementAccess ForBackingStoreElement(MachineType rep) { } +#ifndef V8_TARGET_ARCH_ARM64 +// TODO(titzer): these result in a stub call that doesn't work on ARM64. +// TODO(titzer): factor these tests out to test-run-simplifiedops.cc. +// TODO(titzer): test tagged representation for input to NumberToInt32. +TEST(RunNumberToInt32_float64) { + // TODO(titzer): explicit load/stores here are only because of representations + double input; + int32_t result; + SimplifiedLoweringTester t; + FieldAccess load = {kUntaggedBase, 0, Handle(), Type::Number(), + kMachFloat64}; + Node* loaded = t.LoadField(load, t.PointerConstant(&input)); + Node* convert = t.NumberToInt32(loaded); + FieldAccess store = {kUntaggedBase, 0, Handle(), Type::Signed32(), + kMachInt32}; + t.StoreField(store, t.PointerConstant(&result), convert); + t.Return(t.jsgraph.TrueConstant()); + t.LowerAllNodes(); + t.GenerateCode(); + + if (Pipeline::SupportedTarget()) { + FOR_FLOAT64_INPUTS(i) { + input = *i; + int32_t expected = DoubleToInt32(*i); + t.Call(); + CHECK_EQ(expected, result); + } + } +} + + +// TODO(titzer): test tagged representation for input to NumberToUint32. +TEST(RunNumberToUint32_float64) { + // TODO(titzer): explicit load/stores here are only because of representations + double input; + uint32_t result; + SimplifiedLoweringTester t; + FieldAccess load = {kUntaggedBase, 0, Handle(), Type::Number(), + kMachFloat64}; + Node* loaded = t.LoadField(load, t.PointerConstant(&input)); + Node* convert = t.NumberToUint32(loaded); + FieldAccess store = {kUntaggedBase, 0, Handle(), Type::Unsigned32(), + kMachUint32}; + t.StoreField(store, t.PointerConstant(&result), convert); + t.Return(t.jsgraph.TrueConstant()); + t.LowerAllNodes(); + t.GenerateCode(); + + if (Pipeline::SupportedTarget()) { + FOR_FLOAT64_INPUTS(i) { + input = *i; + uint32_t expected = DoubleToUint32(*i); + t.Call(); + CHECK_EQ(static_cast(expected), static_cast(result)); + } + } +} +#endif + + // Create a simple JSObject with a unique map. static Handle TestObject() { static int index = 0; @@ -908,6 +968,33 @@ TEST(LowerNumberToInt32_to_ChangeTaggedToInt32) { } +TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { + // NumberToInt32(x: kRepFloat64) used as kMachInt32 + TestingGraph t(Type::Number()); + Node* p0 = t.ExampleWithOutput(kMachFloat64); + Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); + Node* use = t.Use(trunc, kMachInt32); + t.Return(use); + t.Lower(); + CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); +} + + +TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32_with_change) { + // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachInt32 + TestingGraph t(Type::Number()); + Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), t.p0); + Node* use = t.Use(trunc, kMachInt32); + t.Return(use); + t.Lower(); + Node* node = use->InputAt(0); + CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); + Node* of = node->InputAt(0); + CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); + CHECK_EQ(t.p0, of->InputAt(0)); +} + + TEST(LowerNumberToInt32_to_ChangeFloat64ToTagged) { // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepTagged } @@ -919,12 +1006,6 @@ TEST(LowerNumberToInt32_to_ChangeFloat64ToInt32) { } -TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { - // TODO(titzer): NumberToInt32(x: kRepFloat64) used as kRepWord32 | - // kTypeUint32 -} - - TEST(LowerNumberToUint32_to_nop) { // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepTagged TestingGraph t(Type::Unsigned32()); @@ -958,6 +1039,33 @@ TEST(LowerNumberToUint32_to_ChangeTaggedToUint32) { } +TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32) { + // NumberToUint32(x: kRepFloat64) used as kMachUint32 + TestingGraph t(Type::Number()); + Node* p0 = t.ExampleWithOutput(kMachFloat64); + Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), p0); + Node* use = t.Use(trunc, kMachUint32); + t.Return(use); + t.Lower(); + CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, p0, use->InputAt(0)); +} + + +TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_with_change) { + // NumberToInt32(x: kTypeNumber | kRepTagged) used as kMachUint32 + TestingGraph t(Type::Number()); + Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), t.p0); + Node* use = t.Use(trunc, kMachUint32); + t.Return(use); + t.Lower(); + Node* node = use->InputAt(0); + CHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, node->opcode()); + Node* of = node->InputAt(0); + CHECK_EQ(IrOpcode::kChangeTaggedToFloat64, of->opcode()); + CHECK_EQ(t.p0, of->InputAt(0)); +} + + TEST(LowerNumberToUint32_to_ChangeFloat64ToTagged) { // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as // kRepTagged -- 2.7.4