[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}
This commit is contained in:
ahaas 2015-11-25 13:12:44 -08:00 committed by Commit bot
parent 802ea71e7c
commit 57117b8339
20 changed files with 88 additions and 11 deletions

View File

@ -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;

View File

@ -72,6 +72,7 @@ namespace compiler {
V(ArmVrintzF32) \
V(ArmVrintzF64) \
V(ArmVrintaF64) \
V(ArmVrintnF32) \
V(ArmVrintnF64) \
V(ArmVcvtF32F64) \
V(ArmVcvtF64F32) \

View File

@ -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;

View File

@ -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;

View File

@ -106,6 +106,7 @@ namespace compiler {
V(Arm64Float64RoundTiesAway) \
V(Arm64Float32RoundTruncate) \
V(Arm64Float64RoundTruncate) \
V(Arm64Float32RoundTiesEven) \
V(Arm64Float64RoundTiesEven) \
V(Arm64Float32ToFloat64) \
V(Arm64Float64ToFloat32) \

View File

@ -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 |

View File

@ -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;

View File

@ -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:

View File

@ -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)

View File

@ -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.

View File

@ -678,6 +678,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kMipsFloat64RoundTiesEven, node);
}

View File

@ -1012,6 +1012,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
VisitRR(this, kMips64Float64RoundTiesEven, node);
}

View File

@ -311,6 +311,7 @@
V(Float32RoundTruncate) \
V(Float64RoundTruncate) \
V(Float64RoundTiesAway) \
V(Float32RoundTiesEven) \
V(Float64RoundTiesEven) \
V(Float64ExtractLowWord32) \
V(Float64ExtractHighWord32) \

View File

@ -1159,6 +1159,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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:

View File

@ -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;

View File

@ -875,6 +875,11 @@ void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
}
void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
UNREACHABLE();
}
void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
UNREACHABLE();
}

View File

@ -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;