}
+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);
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();
}
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)));
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();
}
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));
}
#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));
Node* const phi = m.node();
DCHECK_EQ(kRepFloat64, RepresentationOf(OpParameter<MachineType>(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);
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<TruncationMode>(op);
+}
+
+
std::ostream& operator<<(std::ostream& os, WriteBarrierKind kind) {
switch (kind) {
case kNoWriteBarrier:
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) \
PURE_OPTIONAL_OP_LIST(PURE)
#undef PURE
+ template <TruncationMode kMode>
+ struct TruncateFloat64ToInt32Operator final
+ : public Operator1<TruncationMode> {
+ TruncateFloat64ToInt32Operator()
+ : Operator1<TruncationMode>(IrOpcode::kTruncateFloat64ToInt32,
+ Operator::kPure, "TruncateFloat64ToInt32",
+ 1, 0, 0, 1, 0, 0, kMode) {}
+ };
+ TruncateFloat64ToInt32Operator<TruncationMode::kJavaScript>
+ kTruncateFloat64ToInt32JavaScript;
+ TruncateFloat64ToInt32Operator<TruncationMode::kRoundToZero>
+ kTruncateFloat64ToInt32RoundToZero;
+
#define LOAD(Type) \
struct Load##Type##Operator final : public Operator1<LoadRepresentation> { \
Load##Type##Operator() \
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) \
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) {}
}
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<uint8_t>(mode);
+}
+
+std::ostream& operator<<(std::ostream&, TruncationMode);
+
+TruncationMode TruncationModeOf(Operator const*);
+
+
// Supported write barrier modes.
enum WriteBarrierKind { kNoWriteBarrier, kFullWriteBarrier };
// 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
}
+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);
}
}
+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);
}
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);
// 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);
}
// 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;
}
// 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;
}
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,
}
-void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
- X64OperandGenerator g(this);
- Emit(kSSEFloat64ToFloat32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+namespace {
+
+void VisitRO(InstructionSelector* selector, Node* node,
+ InstructionCode opcode) {
+ X64OperandGenerator g(selector);
+ selector->Emit(opcode, 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));
+void VisitRR(InstructionSelector* selector, Node* node,
+ InstructionCode opcode) {
+ X64OperandGenerator g(selector);
+ selector->Emit(opcode, g.DefineAsRegister(node),
+ g.UseRegister(node->InputAt(0)));
}
-namespace {
-
void VisitFloatBinop(InstructionSelector* selector, Node* node,
ArchOpcode avx_opcode, ArchOpcode sse_opcode) {
X64OperandGenerator g(selector);
}
}
-
} // 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);
}
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);
}
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));
}
{-1.7976931348623157e+308, 0}};
double input = -1.0;
RawMachineAssemblerTester<int32_t> 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<int64_t>(kValues[i].raw);
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());
0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff};
+const TruncationMode kTruncationModes[] = {TruncationMode::kJavaScript,
+ TruncationMode::kRoundToZero};
+
+
struct ComparisonBinaryOperator {
const Operator* (MachineOperatorBuilder::*constructor)();
const char* constructor_name;
// -----------------------------------------------------------------------------
-// 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<UnaryOperator>
- 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
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)));
}
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));
+ }
}
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), // --