Commit 57117b83 authored by ahaas's avatar ahaas Committed by Commit bot

[turbofan] Implemented the optional Float32RoundTiesEven operator.

The Float32RoundTiesEven operator rounds float32 numbers towards the nearest
integer. If the distance to two integers is the same, then the result is
the even integer. This is the default rounding mode of the ieee 754 floating
point standard.

I implemented the optional Float32RoundTiesEven operator on x64, ia32, arm, and arm64.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1477753002

Cr-Commit-Position: refs/heads/master@{#32308}
parent 802ea71e
......@@ -812,6 +812,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArmVrintaF64:
__ vrinta(i.OutputFloat64Register(), i.InputFloat64Register(0));
break;
case kArmVrintnF32:
__ vrintn(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
case kArmVrintnF64:
__ vrintn(i.OutputFloat64Register(), i.InputFloat64Register(0));
break;
......
......@@ -72,6 +72,7 @@ namespace compiler {
V(ArmVrintzF32) \
V(ArmVrintzF64) \
V(ArmVrintaF64) \
V(ArmVrintnF32) \
V(ArmVrintnF64) \
V(ArmVcvtF32F64) \
V(ArmVcvtF64F32) \
......
......@@ -1150,6 +1150,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
VisitRR(this, kArmVrintnF32, node);
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kArmVrintnF64, node);
}
......@@ -1587,6 +1592,7 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat32RoundTruncate |
MachineOperatorBuilder::kFloat64RoundTruncate |
MachineOperatorBuilder::kFloat64RoundTiesAway |
MachineOperatorBuilder::kFloat32RoundTiesEven |
MachineOperatorBuilder::kFloat64RoundTiesEven;
}
return flags;
......
......@@ -644,6 +644,9 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
case kArm64Float64RoundTruncate:
__ Frintz(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
case kArm64Float32RoundTiesEven:
__ Frintn(i.OutputFloat32Register(), i.InputFloat32Register(0));
break;
case kArm64Float64RoundTiesEven:
__ Frintn(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
break;
......
......@@ -106,6 +106,7 @@ namespace compiler {
V(Arm64Float64RoundTiesAway) \
V(Arm64Float32RoundTruncate) \
V(Arm64Float64RoundTruncate) \
V(Arm64Float32RoundTiesEven) \
V(Arm64Float64RoundTiesEven) \
V(Arm64Float32ToFloat64) \
V(Arm64Float64ToFloat32) \
......
......@@ -1508,6 +1508,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
VisitRR(this, kArm64Float32RoundTiesEven, node);
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kArm64Float64RoundTiesEven, node);
}
......@@ -2088,6 +2093,7 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat32RoundTruncate |
MachineOperatorBuilder::kFloat64RoundTruncate |
MachineOperatorBuilder::kFloat64RoundTiesAway |
MachineOperatorBuilder::kFloat32RoundTiesEven |
MachineOperatorBuilder::kFloat64RoundTiesEven |
MachineOperatorBuilder::kWord32ShiftIsSafe |
MachineOperatorBuilder::kInt32DivIsSafe |
......
......@@ -886,6 +886,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
VisitRR(this, node, kSSEFloat32Round | MiscField::encode(kRoundToNearest));
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToNearest));
}
......@@ -1305,6 +1310,7 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat64RoundUp |
MachineOperatorBuilder::kFloat32RoundTruncate |
MachineOperatorBuilder::kFloat64RoundTruncate |
MachineOperatorBuilder::kFloat32RoundTiesEven |
MachineOperatorBuilder::kFloat64RoundTiesEven;
}
return flags;
......
......@@ -937,6 +937,8 @@ void InstructionSelector::VisitNode(Node* node) {
return MarkAsFloat64(node), VisitFloat64RoundTruncate(node);
case IrOpcode::kFloat64RoundTiesAway:
return MarkAsFloat64(node), VisitFloat64RoundTiesAway(node);
case IrOpcode::kFloat32RoundTiesEven:
return MarkAsFloat32(node), VisitFloat32RoundTiesEven(node);
case IrOpcode::kFloat64RoundTiesEven:
return MarkAsFloat64(node), VisitFloat64RoundTiesEven(node);
case IrOpcode::kFloat64ExtractLowWord32:
......
......@@ -193,6 +193,7 @@ CheckedStoreRepresentation CheckedStoreRepresentationOf(Operator const* op) {
V(Float32RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTiesAway, Operator::kNoProperties, 1, 0, 1) \
V(Float32RoundTiesEven, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTiesEven, Operator::kNoProperties, 1, 0, 1)
......
......@@ -122,21 +122,22 @@ class MachineOperatorBuilder final : public ZoneObject {
kFloat64RoundUp = 1u << 7,
kFloat32RoundTruncate = 1u << 8,
kFloat64RoundTruncate = 1u << 9,
kFloat64RoundTiesEven = 1u << 10,
kFloat64RoundTiesAway = 1u << 11,
kInt32DivIsSafe = 1u << 12,
kUint32DivIsSafe = 1u << 13,
kWord32ShiftIsSafe = 1u << 14,
kWord32Ctz = 1u << 15,
kWord64Ctz = 1u << 16,
kWord32Popcnt = 1u << 17,
kWord64Popcnt = 1u << 18,
kFloat32RoundTiesEven = 1u << 10,
kFloat64RoundTiesEven = 1u << 11,
kFloat64RoundTiesAway = 1u << 12,
kInt32DivIsSafe = 1u << 13,
kUint32DivIsSafe = 1u << 14,
kWord32ShiftIsSafe = 1u << 15,
kWord32Ctz = 1u << 16,
kWord64Ctz = 1u << 17,
kWord32Popcnt = 1u << 18,
kWord64Popcnt = 1u << 19,
kAllOptionalOps = kFloat32Max | kFloat32Min | kFloat64Max | kFloat64Min |
kFloat32RoundDown | kFloat64RoundDown | kFloat32RoundUp |
kFloat64RoundUp | kFloat32RoundTruncate |
kFloat64RoundTruncate | kFloat64RoundTiesAway |
kFloat64RoundTiesEven | kWord32Ctz | kWord64Ctz |
kWord32Popcnt | kWord64Popcnt
kFloat32RoundTiesEven | kFloat64RoundTiesEven |
kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt
};
typedef base::Flags<Flag, unsigned> Flags;
......@@ -279,6 +280,7 @@ class MachineOperatorBuilder final : public ZoneObject {
const OptionalOperator Float32RoundTruncate();
const OptionalOperator Float64RoundTruncate();
const OptionalOperator Float64RoundTiesAway();
const OptionalOperator Float32RoundTiesEven();
const OptionalOperator Float64RoundTiesEven();
// Floating point bit representation.
......
......@@ -678,6 +678,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kMipsFloat64RoundTiesEven, node);
}
......
......@@ -1012,6 +1012,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kMips64Float64RoundTiesEven, node);
}
......
......@@ -311,6 +311,7 @@
V(Float32RoundTruncate) \
V(Float64RoundTruncate) \
V(Float64RoundTiesAway) \
V(Float32RoundTiesEven) \
V(Float64RoundTiesEven) \
V(Float64ExtractLowWord32) \
V(Float64ExtractHighWord32) \
......
......@@ -1159,6 +1159,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}
......
......@@ -504,6 +504,9 @@ class RawMachineAssembler {
Node* Float64RoundTiesAway(Node* a) {
return AddNode(machine()->Float64RoundTiesAway().op(), a);
}
Node* Float32RoundTiesEven(Node* a) {
return AddNode(machine()->Float32RoundTiesEven().op(), a);
}
Node* Float64RoundTiesEven(Node* a) {
return AddNode(machine()->Float64RoundTiesEven().op(), a);
}
......
......@@ -2312,6 +2312,12 @@ Type* Typer::Visitor::TypeFloat64RoundTiesAway(Node* node) {
}
Type* Typer::Visitor::TypeFloat32RoundTiesEven(Node* node) {
// TODO(sigurds): We could have a tighter bound here.
return Type::Number();
}
Type* Typer::Visitor::TypeFloat64RoundTiesEven(Node* node) {
// TODO(sigurds): We could have a tighter bound here.
return Type::Number();
......
......@@ -896,6 +896,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kFloat32RoundTruncate:
case IrOpcode::kFloat64RoundTruncate:
case IrOpcode::kFloat64RoundTiesAway:
case IrOpcode::kFloat32RoundTiesEven:
case IrOpcode::kFloat64RoundTiesEven:
case IrOpcode::kFloat64Equal:
case IrOpcode::kFloat64LessThan:
......
......@@ -1173,6 +1173,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
VisitRR(this, node, kSSEFloat32Round | MiscField::encode(kRoundToNearest));
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, node, kSSEFloat64Round | MiscField::encode(kRoundToNearest));
}
......@@ -1712,6 +1717,7 @@ InstructionSelector::SupportedMachineOperatorFlags() {
MachineOperatorBuilder::kFloat64RoundUp |
MachineOperatorBuilder::kFloat32RoundTruncate |
MachineOperatorBuilder::kFloat64RoundTruncate |
MachineOperatorBuilder::kFloat32RoundTiesEven |
MachineOperatorBuilder::kFloat64RoundTiesEven;
}
return flags;
......
......@@ -875,6 +875,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}
......
......@@ -5195,6 +5195,15 @@ TEST(RunFloat64RoundUp) {
}
TEST(RunFloat32RoundTiesEven) {
BufferedRawMachineAssemblerTester<float> m(kMachFloat32);
if (!m.machine()->Float32RoundTiesEven().IsSupported()) return;
m.Return(m.Float32RoundTiesEven(m.Parameter(0)));
FOR_FLOAT32_INPUTS(i) { CheckFloatEq(nearbyint(*i), m.Call(*i)); }
}
TEST(RunFloat64RoundTiesEven) {
BufferedRawMachineAssemblerTester<double> m(kMachFloat64);
if (!m.machine()->Float64RoundTiesEven().IsSupported()) return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment