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.
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.
}
+#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;
}
+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
}
}
-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());
}
+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