Use TruncateFloat64ToInt32 instead of ChangeFloat64ToInt32 in lowering of simplified...
authortitzer@chromium.org <titzer@chromium.org>
Thu, 28 Aug 2014 13:31:55 +0000 (13:31 +0000)
committertitzer@chromium.org <titzer@chromium.org>
Thu, 28 Aug 2014 13:31:55 +0000 (13:31 +0000)
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
test/cctest/compiler/test-simplified-lowering.cc

index 72c2d37..9ccd4ed 100644 (file)
@@ -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.
index ac72d78..4c86e40 100644 (file)
@@ -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<Object*> t;
+  FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
+                      kMachFloat64};
+  Node* loaded = t.LoadField(load, t.PointerConstant(&input));
+  Node* convert = t.NumberToInt32(loaded);
+  FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), 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<Object*> t;
+  FieldAccess load = {kUntaggedBase, 0, Handle<Name>(), Type::Number(),
+                      kMachFloat64};
+  Node* loaded = t.LoadField(load, t.PointerConstant(&input));
+  Node* convert = t.NumberToUint32(loaded);
+  FieldAccess store = {kUntaggedBase, 0, Handle<Name>(), 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<int32_t>(expected), static_cast<int32_t>(result));
+    }
+  }
+}
+#endif
+
+
 // Create a simple JSObject with a unique map.
 static Handle<JSObject> 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