diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc index d9f8f8b1de..8855388048 100644 --- a/src/compiler/arm/instruction-selector-arm.cc +++ b/src/compiler/arm/instruction-selector-arm.cc @@ -914,6 +914,17 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { } +void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { + switch (TruncationModeOf(node->op())) { + case TruncationMode::kJavaScript: + return VisitRR(this, kArchTruncateDoubleToI, node); + case TruncationMode::kRoundToZero: + return VisitRR(this, kArmVcvtS32F64, node); + } + UNREACHABLE(); +} + + void InstructionSelector::VisitFloat32Add(Node* node) { ArmOperandGenerator g(this); Float32BinopMatcher m(node); diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc index 7c1c1d76fa..ca0ec4e400 100644 --- a/src/compiler/arm64/instruction-selector-arm64.cc +++ b/src/compiler/arm64/instruction-selector-arm64.cc @@ -1237,9 +1237,18 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { - Arm64OperandGenerator g(this); - Emit(kArm64Float64ToFloat32, g.DefineAsRegister(node), - g.UseRegister(node->InputAt(0))); + VisitRR(this, kArm64Float64ToFloat32, node); +} + + +void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { + switch (TruncationModeOf(node->op())) { + case TruncationMode::kJavaScript: + return VisitRR(this, kArchTruncateDoubleToI, node); + case TruncationMode::kRoundToZero: + return VisitRR(this, kArm64Float64ToInt32, node); + } + UNREACHABLE(); } diff --git a/src/compiler/ia32/instruction-selector-ia32.cc b/src/compiler/ia32/instruction-selector-ia32.cc index d9ff422597..105ca8287b 100644 --- a/src/compiler/ia32/instruction-selector-ia32.cc +++ b/src/compiler/ia32/instruction-selector-ia32.cc @@ -127,15 +127,14 @@ class IA32OperandGenerator final : public OperandGenerator { namespace { -void VisitROFloat(InstructionSelector* selector, Node* node, - ArchOpcode opcode) { +void VisitRO(InstructionSelector* selector, Node* node, ArchOpcode opcode) { IA32OperandGenerator g(selector); selector->Emit(opcode, g.DefineAsRegister(node), g.Use(node->InputAt(0))); } -void VisitRRFloat(InstructionSelector* selector, Node* node, - InstructionCode opcode) { +void VisitRR(InstructionSelector* selector, Node* node, + InstructionCode opcode) { IA32OperandGenerator g(selector); selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); @@ -648,38 +647,43 @@ void InstructionSelector::VisitUint32Mod(Node* node) { void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { - IA32OperandGenerator g(this); - Emit(kSSEFloat32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEFloat32ToFloat64); } void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { - IA32OperandGenerator g(this); - Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEInt32ToFloat64); } void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { - IA32OperandGenerator g(this); - Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEUint32ToFloat64); } void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { - IA32OperandGenerator g(this); - Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEFloat64ToInt32); } void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { - IA32OperandGenerator g(this); - Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEFloat64ToUint32); } void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { - IA32OperandGenerator g(this); - Emit(kSSEFloat64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEFloat64ToFloat32); +} + + +void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { + switch (TruncationModeOf(node->op())) { + case TruncationMode::kJavaScript: + return VisitRR(this, node, kArchTruncateDoubleToI); + case TruncationMode::kRoundToZero: + return VisitRO(this, node, kSSEFloat64ToInt32); + } + UNREACHABLE(); } @@ -791,22 +795,22 @@ void InstructionSelector::VisitFloat64Abs(Node* node) { void InstructionSelector::VisitFloat32Sqrt(Node* node) { - VisitROFloat(this, node, kSSEFloat32Sqrt); + VisitRO(this, node, kSSEFloat32Sqrt); } void InstructionSelector::VisitFloat64Sqrt(Node* node) { - VisitROFloat(this, node, kSSEFloat64Sqrt); + VisitRO(this, node, kSSEFloat64Sqrt); } void InstructionSelector::VisitFloat64RoundDown(Node* node) { - VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundDown)); + VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundDown)); } void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { - VisitRRFloat(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero)); + VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero)); } diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 0a6f237190..813da4f132 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -779,13 +779,6 @@ void InstructionSelector::VisitNode(Node* node) { #if V8_TURBOFAN_BACKEND -void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { - OperandGenerator g(this); - Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node), - g.UseRegister(node->InputAt(0))); -} - - void InstructionSelector::VisitLoadStackPointer(Node* node) { OperandGenerator g(this); Emit(kArchStackPointer, g.DefineAsRegister(node)); diff --git a/src/compiler/machine-operator-reducer.cc b/src/compiler/machine-operator-reducer.cc index ba0b7a1893..3ce59733eb 100644 --- a/src/compiler/machine-operator-reducer.cc +++ b/src/compiler/machine-operator-reducer.cc @@ -646,14 +646,13 @@ Reduction MachineOperatorReducer::ReduceTruncateFloat64ToInt32(Node* node) { Node* const phi = m.node(); DCHECK_EQ(kRepFloat64, RepresentationOf(OpParameter(phi))); if (phi->OwnedBy(node)) { - // TruncateFloat64ToInt32(Phi[Float64](x1,...,xn)) - // => Phi[Int32](TruncateFloat64ToInt32(x1), + // TruncateFloat64ToInt32[mode](Phi[Float64](x1,...,xn)) + // => Phi[Int32](TruncateFloat64ToInt32[mode](x1), // ..., - // TruncateFloat64ToInt32(xn)) + // TruncateFloat64ToInt32[mode](xn)) const int value_input_count = phi->InputCount() - 1; for (int i = 0; i < value_input_count; ++i) { - Node* input = graph()->NewNode(machine()->TruncateFloat64ToInt32(), - phi->InputAt(i)); + Node* input = graph()->NewNode(node->op(), phi->InputAt(i)); // TODO(bmeurer): Reschedule input for reduction once we have Revisit() // instead of recursing into ReduceTruncateFloat64ToInt32() here. Reduction reduction = ReduceTruncateFloat64ToInt32(input); diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc index f34fc86733..2e2229032c 100644 --- a/src/compiler/machine-operator.cc +++ b/src/compiler/machine-operator.cc @@ -12,6 +12,24 @@ namespace v8 { namespace internal { namespace compiler { +std::ostream& operator<<(std::ostream& os, TruncationMode mode) { + switch (mode) { + case TruncationMode::kJavaScript: + return os << "JavaScript"; + case TruncationMode::kRoundToZero: + return os << "RoundToZero"; + } + UNREACHABLE(); + return os; +} + + +TruncationMode TruncationModeOf(Operator const* op) { + DCHECK_EQ(IrOpcode::kTruncateFloat64ToInt32, op->opcode()); + return OpParameter(op); +} + + std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) { switch (kind) { case kNoWriteBarrier: @@ -117,7 +135,6 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) { V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \ V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1) \ V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1) \ - V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \ V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1) \ V(Float32Abs, Operator::kNoProperties, 1, 0, 1) \ V(Float32Add, Operator::kCommutative, 2, 0, 1) \ @@ -191,6 +208,19 @@ struct MachineOperatorGlobalCache { PURE_OPTIONAL_OP_LIST(PURE) #undef PURE + template + struct TruncateFloat64ToInt32Operator final + : public Operator1 { + TruncateFloat64ToInt32Operator() + : Operator1(IrOpcode::kTruncateFloat64ToInt32, + Operator::kPure, "TruncateFloat64ToInt32", + 1, 0, 0, 1, 0, 0, kMode) {} + }; + TruncateFloat64ToInt32Operator + kTruncateFloat64ToInt32JavaScript; + TruncateFloat64ToInt32Operator + kTruncateFloat64ToInt32RoundToZero; + #define LOAD(Type) \ struct Load##Type##Operator final : public Operator1 { \ Load##Type##Operator() \ @@ -268,6 +298,20 @@ PURE_OP_LIST(PURE) PURE_OPTIONAL_OP_LIST(PURE) #undef PURE + +const Operator* MachineOperatorBuilder::TruncateFloat64ToInt32( + TruncationMode mode) { + switch (mode) { + case TruncationMode::kJavaScript: + return &cache_.kTruncateFloat64ToInt32JavaScript; + case TruncationMode::kRoundToZero: + return &cache_.kTruncateFloat64ToInt32RoundToZero; + } + UNREACHABLE(); + return nullptr; +} + + const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) { switch (rep) { #define LOAD(Type) \ diff --git a/src/compiler/machine-operator.h b/src/compiler/machine-operator.h index 288006c509..0c055b8732 100644 --- a/src/compiler/machine-operator.h +++ b/src/compiler/machine-operator.h @@ -16,8 +16,9 @@ namespace compiler { struct MachineOperatorGlobalCache; class Operator; + // For operators that are not supported on all platforms. -class OptionalOperator { +class OptionalOperator final { public: explicit OptionalOperator(const Operator* op) : op_(op) {} @@ -28,9 +29,25 @@ class OptionalOperator { } private: - const Operator* op_; + const Operator* const op_; }; + +// Supported float64 to int32 truncation modes. +enum class TruncationMode : uint8_t { + kJavaScript, // ES6 section 7.1.5 + kRoundToZero // Round towards zero. Implementation defined for NaN and ovf. +}; + +V8_INLINE size_t hash_value(TruncationMode mode) { + return static_cast(mode); +} + +std::ostream& operator<<(std::ostream&, TruncationMode); + +TruncationMode TruncationModeOf(Operator const*); + + // Supported write barrier modes. enum WriteBarrierKind { kNoWriteBarrier, kFullWriteBarrier }; @@ -175,7 +192,7 @@ class MachineOperatorBuilder final : public ZoneObject { // These operators truncate numbers, both changing the representation of // the number and mapping multiple input values onto the same output value. const Operator* TruncateFloat64ToFloat32(); - const Operator* TruncateFloat64ToInt32(); // JavaScript semantics. + const Operator* TruncateFloat64ToInt32(TruncationMode); const Operator* TruncateInt64ToInt32(); // Floating point operators always operate with IEEE 754 round-to-nearest diff --git a/src/compiler/mips/instruction-selector-mips.cc b/src/compiler/mips/instruction-selector-mips.cc index 52be8a9a2a..c2420ac0d8 100644 --- a/src/compiler/mips/instruction-selector-mips.cc +++ b/src/compiler/mips/instruction-selector-mips.cc @@ -391,6 +391,17 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { } +void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { + switch (TruncationModeOf(node->op())) { + case TruncationMode::kJavaScript: + return VisitRR(this, kArchTruncateDoubleToI, node); + case TruncationMode::kRoundToZero: + return VisitRR(this, kMipsTruncWD, node); + } + UNREACHABLE(); +} + + void InstructionSelector::VisitFloat32Add(Node* node) { VisitRRR(this, kMipsAddS, node); } diff --git a/src/compiler/mips64/instruction-selector-mips64.cc b/src/compiler/mips64/instruction-selector-mips64.cc index 8db0113df3..e4d8795f1b 100644 --- a/src/compiler/mips64/instruction-selector-mips64.cc +++ b/src/compiler/mips64/instruction-selector-mips64.cc @@ -539,6 +539,17 @@ void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { } +void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { + switch (TruncationModeOf(node->op())) { + case TruncationMode::kJavaScript: + return VisitRR(this, kArchTruncateDoubleToI, node); + case TruncationMode::kRoundToZero: + return VisitRR(this, kMips64TruncWD, node); + } + UNREACHABLE(); +} + + void InstructionSelector::VisitFloat32Add(Node* node) { VisitRRR(this, kMips64AddS, node); } diff --git a/src/compiler/raw-machine-assembler.h b/src/compiler/raw-machine-assembler.h index 80af21339f..bc28e6c817 100644 --- a/src/compiler/raw-machine-assembler.h +++ b/src/compiler/raw-machine-assembler.h @@ -412,8 +412,8 @@ class RawMachineAssembler : public GraphBuilder { Node* TruncateFloat64ToFloat32(Node* a) { return NewNode(machine()->TruncateFloat64ToFloat32(), a); } - Node* TruncateFloat64ToInt32(Node* a) { - return NewNode(machine()->TruncateFloat64ToInt32(), a); + Node* TruncateFloat64ToInt32(TruncationMode mode, Node* a) { + return NewNode(machine()->TruncateFloat64ToInt32(mode), a); } Node* TruncateInt64ToInt32(Node* a) { return NewNode(machine()->TruncateInt64ToInt32(), a); diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h index 6ec4b86bb4..9538684af2 100644 --- a/src/compiler/representation-change.h +++ b/src/compiler/representation-change.h @@ -232,13 +232,13 @@ class RepresentationChanger { // Select the correct X -> Word32 truncation operator. const Operator* op = NULL; if (output_type & kRepFloat64) { - op = machine()->TruncateFloat64ToInt32(); + op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript); } else if (output_type & kRepFloat32) { node = InsertChangeFloat32ToFloat64(node); - op = machine()->TruncateFloat64ToInt32(); + op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript); } else if (output_type & kRepTagged) { node = InsertChangeTaggedToFloat64(node); - op = machine()->TruncateFloat64ToInt32(); + op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript); } else { return TypeError(node, output_type, kRepWord32); } diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index 68e7567a5c..006b6ab28f 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -727,8 +727,10 @@ class RepresentationSelector { // Require the input in float64 format and perform truncation. // TODO(turbofan): avoid a truncation with a smi check. VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32); - if (lower()) - node->set_op(lowering->machine()->TruncateFloat64ToInt32()); + if (lower()) { + node->set_op(lowering->machine()->TruncateFloat64ToInt32( + TruncationMode::kJavaScript)); + } } break; } @@ -755,8 +757,10 @@ class RepresentationSelector { // Require the input in float64 format and perform truncation. // TODO(turbofan): avoid a truncation with a smi check. VisitUnop(node, kTypeUint32 | kRepFloat64, kTypeUint32 | kRepWord32); - if (lower()) - node->set_op(lowering->machine()->TruncateFloat64ToInt32()); + if (lower()) { + node->set_op(lowering->machine()->TruncateFloat64ToInt32( + TruncationMode::kJavaScript)); + } } break; } @@ -1008,6 +1012,9 @@ class RepresentationSelector { case IrOpcode::kTruncateFloat64ToFloat32: return VisitUnop(node, kTypeNumber | kRepFloat64, kTypeNumber | kRepFloat32); + case IrOpcode::kTruncateFloat64ToInt32: + return VisitUnop(node, kTypeNumber | kRepFloat64, + kTypeInt32 | kRepWord32); case IrOpcode::kTruncateInt64ToInt32: // TODO(titzer): Is kTypeInt32 correct here? return VisitUnop(node, kTypeInt32 | kRepWord64, diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index a7331fdee2..6d7fca472e 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -818,37 +818,23 @@ void InstructionSelector::VisitChangeUint32ToUint64(Node* node) { } -void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { - X64OperandGenerator g(this); - Emit(kSSEFloat64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0))); -} - - -void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { - X64OperandGenerator g(this); - Node* value = node->InputAt(0); - if (CanCover(node, value)) { - switch (value->opcode()) { - case IrOpcode::kWord64Sar: - case IrOpcode::kWord64Shr: { - Int64BinopMatcher m(value); - if (m.right().Is(32)) { - Emit(kX64Shr, g.DefineSameAsFirst(node), - g.UseRegister(m.left().node()), g.TempImmediate(32)); - return; - } - break; - } - default: - break; - } - } - Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value)); -} - - namespace { +void VisitRO(InstructionSelector* selector, Node* node, + InstructionCode opcode) { + X64OperandGenerator g(selector); + selector->Emit(opcode, g.DefineAsRegister(node), g.Use(node->InputAt(0))); +} + + +void VisitRR(InstructionSelector* selector, Node* node, + InstructionCode opcode) { + X64OperandGenerator g(selector); + selector->Emit(opcode, g.DefineAsRegister(node), + g.UseRegister(node->InputAt(0))); +} + + void VisitFloatBinop(InstructionSelector* selector, Node* node, ArchOpcode avx_opcode, ArchOpcode sse_opcode) { X64OperandGenerator g(selector); @@ -872,10 +858,48 @@ void VisitFloatUnop(InstructionSelector* selector, Node* node, Node* input, } } - } // namespace +void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) { + VisitRO(this, node, kSSEFloat64ToFloat32); +} + + +void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) { + switch (TruncationModeOf(node->op())) { + case TruncationMode::kJavaScript: + return VisitRR(this, node, kArchTruncateDoubleToI); + case TruncationMode::kRoundToZero: + return VisitRO(this, node, kSSEFloat64ToInt32); + } + UNREACHABLE(); +} + + +void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { + X64OperandGenerator g(this); + Node* value = node->InputAt(0); + if (CanCover(node, value)) { + switch (value->opcode()) { + case IrOpcode::kWord64Sar: + case IrOpcode::kWord64Shr: { + Int64BinopMatcher m(value); + if (m.right().Is(32)) { + Emit(kX64Shr, g.DefineSameAsFirst(node), + g.UseRegister(m.left().node()), g.TempImmediate(32)); + return; + } + break; + } + default: + break; + } + } + Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value)); +} + + void InstructionSelector::VisitFloat32Add(Node* node) { VisitFloatBinop(this, node, kAVXFloat32Add, kSSEFloat32Add); } @@ -914,14 +938,12 @@ void InstructionSelector::VisitFloat32Min(Node* node) { void InstructionSelector::VisitFloat32Abs(Node* node) { - X64OperandGenerator g(this); VisitFloatUnop(this, node, node->InputAt(0), kAVXFloat32Abs, kSSEFloat32Abs); } void InstructionSelector::VisitFloat32Sqrt(Node* node) { - X64OperandGenerator g(this); - Emit(kSSEFloat32Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEFloat32Sqrt); } @@ -984,37 +1006,22 @@ void InstructionSelector::VisitFloat64Min(Node* node) { void InstructionSelector::VisitFloat64Abs(Node* node) { - X64OperandGenerator g(this); VisitFloatUnop(this, node, node->InputAt(0), kAVXFloat64Abs, kSSEFloat64Abs); } void InstructionSelector::VisitFloat64Sqrt(Node* node) { - X64OperandGenerator g(this); - Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); + VisitRO(this, node, kSSEFloat64Sqrt); } -namespace { - -void VisitRRFloat64(InstructionSelector* selector, InstructionCode opcode, - Node* node) { - X64OperandGenerator g(selector); - selector->Emit(opcode, g.DefineAsRegister(node), - g.UseRegister(node->InputAt(0))); -} - -} // namespace - - void InstructionSelector::VisitFloat64RoundDown(Node* node) { - VisitRRFloat64(this, kSSEFloat64Round | MiscField::encode(kRoundDown), node); + VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundDown)); } void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { - VisitRRFloat64(this, kSSEFloat64Round | MiscField::encode(kRoundToZero), - node); + VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToZero)); } diff --git a/test/cctest/compiler/test-run-machops.cc b/test/cctest/compiler/test-run-machops.cc index 58b26ea908..b1fc36968f 100644 --- a/test/cctest/compiler/test-run-machops.cc +++ b/test/cctest/compiler/test-run-machops.cc @@ -4840,7 +4840,8 @@ TEST(RunTruncateFloat64ToInt32P) { {-1.7976931348623157e+308, 0}}; double input = -1.0; RawMachineAssemblerTester m; - m.Return(m.TruncateFloat64ToInt32(m.LoadFromPointer(&input, kMachFloat64))); + m.Return(m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, + m.LoadFromPointer(&input, kMachFloat64))); for (size_t i = 0; i < arraysize(kValues); ++i) { input = kValues[i].from; uint64_t expected = static_cast(kValues[i].raw); diff --git a/test/unittests/compiler/instruction-selector-unittest.cc b/test/unittests/compiler/instruction-selector-unittest.cc index 4fd35830cf..acab91b009 100644 --- a/test/unittests/compiler/instruction-selector-unittest.cc +++ b/test/unittests/compiler/instruction-selector-unittest.cc @@ -207,7 +207,8 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnZero) { TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToInt32WithParameter) { StreamBuilder m(this, kMachInt32, kMachFloat64); - m.Return(m.TruncateFloat64ToInt32(m.Parameter(0))); + m.Return( + m.TruncateFloat64ToInt32(TruncationMode::kJavaScript, m.Parameter(0))); Stream s = m.Build(kAllInstructions); ASSERT_EQ(4U, s.size()); EXPECT_EQ(kArchNop, s[0]->arch_opcode()); diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc index 9836be4fb2..ce11fdef81 100644 --- a/test/unittests/compiler/machine-operator-reducer-unittest.cc +++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc @@ -234,6 +234,10 @@ const uint32_t kUint32Values[] = { 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff}; +const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript, + TruncationMode::kRoundToZero}; + + struct ComparisonBinaryOperator { const Operator* (MachineOperatorBuilder::*constructor)(); const char* constructor_name; @@ -257,53 +261,6 @@ const ComparisonBinaryOperator kComparisonBinaryOperators[] = { } // namespace -// ----------------------------------------------------------------------------- -// Unary operators - - -namespace { - -struct UnaryOperator { - const Operator* (MachineOperatorBuilder::*constructor)(); - const char* constructor_name; -}; - - -std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) { - return os << unop.constructor_name; -} - - -static const UnaryOperator kUnaryOperators[] = { - {&MachineOperatorBuilder::ChangeInt32ToFloat64, "ChangeInt32ToFloat64"}, - {&MachineOperatorBuilder::ChangeUint32ToFloat64, "ChangeUint32ToFloat64"}, - {&MachineOperatorBuilder::ChangeFloat64ToInt32, "ChangeFloat64ToInt32"}, - {&MachineOperatorBuilder::ChangeFloat64ToUint32, "ChangeFloat64ToUint32"}, - {&MachineOperatorBuilder::ChangeInt32ToInt64, "ChangeInt32ToInt64"}, - {&MachineOperatorBuilder::ChangeUint32ToUint64, "ChangeUint32ToUint64"}, - {&MachineOperatorBuilder::TruncateFloat64ToInt32, "TruncateFloat64ToInt32"}, - {&MachineOperatorBuilder::TruncateInt64ToInt32, "TruncateInt64ToInt32"}}; - -} // namespace - - -typedef MachineOperatorReducerTestWithParam - MachineUnaryOperatorReducerTest; - - -TEST_P(MachineUnaryOperatorReducerTest, Parameter) { - const UnaryOperator unop = GetParam(); - Reduction reduction = - Reduce(graph()->NewNode((machine()->*unop.constructor)(), Parameter(0))); - EXPECT_FALSE(reduction.Changed()); -} - - -INSTANTIATE_TEST_CASE_P(MachineOperatorReducerTest, - MachineUnaryOperatorReducerTest, - ::testing::ValuesIn(kUnaryOperators)); - - // ----------------------------------------------------------------------------- // ChangeFloat64ToFloat32 @@ -459,19 +416,22 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToFloat32WithConstant) { TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithChangeInt32ToFloat64) { - Node* value = Parameter(0); - Reduction reduction = Reduce(graph()->NewNode( - machine()->TruncateFloat64ToInt32(), - graph()->NewNode(machine()->ChangeInt32ToFloat64(), value))); - ASSERT_TRUE(reduction.Changed()); - EXPECT_EQ(value, reduction.replacement()); + TRACED_FOREACH(TruncationMode, mode, kTruncationModes) { + Node* value = Parameter(0); + Reduction reduction = Reduce(graph()->NewNode( + machine()->TruncateFloat64ToInt32(mode), + graph()->NewNode(machine()->ChangeInt32ToFloat64(), value))); + ASSERT_TRUE(reduction.Changed()); + EXPECT_EQ(value, reduction.replacement()); + } } TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithConstant) { TRACED_FOREACH(double, x, kFloat64Values) { Reduction reduction = Reduce(graph()->NewNode( - machine()->TruncateFloat64ToInt32(), Float64Constant(x))); + machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript), + Float64Constant(x))); ASSERT_TRUE(reduction.Changed()); EXPECT_THAT(reduction.replacement(), IsInt32Constant(DoubleToInt32(x))); } @@ -482,13 +442,15 @@ TEST_F(MachineOperatorReducerTest, TruncateFloat64ToInt32WithPhi) { Node* const p0 = Parameter(0); Node* const p1 = Parameter(1); Node* const merge = graph()->start(); - Reduction reduction = Reduce(graph()->NewNode( - machine()->TruncateFloat64ToInt32(), - graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge))); - ASSERT_TRUE(reduction.Changed()); - EXPECT_THAT(reduction.replacement(), - IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0), - IsTruncateFloat64ToInt32(p1), merge)); + TRACED_FOREACH(TruncationMode, mode, kTruncationModes) { + Reduction reduction = Reduce(graph()->NewNode( + machine()->TruncateFloat64ToInt32(mode), + graph()->NewNode(common()->Phi(kMachFloat64, 2), p0, p1, merge))); + ASSERT_TRUE(reduction.Changed()); + EXPECT_THAT(reduction.replacement(), + IsPhi(kMachInt32, IsTruncateFloat64ToInt32(p0), + IsTruncateFloat64ToInt32(p1), merge)); + } } diff --git a/test/unittests/compiler/machine-operator-unittest.cc b/test/unittests/compiler/machine-operator-unittest.cc index fdba663e24..fca53e2bd8 100644 --- a/test/unittests/compiler/machine-operator-unittest.cc +++ b/test/unittests/compiler/machine-operator-unittest.cc @@ -224,7 +224,6 @@ const PureOperator kPureOperators[] = { PURE(ChangeUint32ToFloat64, 1, 0, 1), // -- PURE(ChangeUint32ToUint64, 1, 0, 1), // -- PURE(TruncateFloat64ToFloat32, 1, 0, 1), // -- - PURE(TruncateFloat64ToInt32, 1, 0, 1), // -- PURE(TruncateInt64ToInt32, 1, 0, 1), // -- PURE(Float32Abs, 1, 0, 1), // -- PURE(Float32Add, 2, 0, 1), // --