[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:
parent
802ea71e7c
commit
57117b8339
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user