[turbofan] Elide fp32 convert for const compares

Reduce operations of the form f64cmp(fp32to64(x), k) to f32cmp(x, k) when k
can be encoded as a 32-bit float.

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

Cr-Commit-Position: refs/heads/master@{#30909}
This commit is contained in:
martyn.capewell 2015-09-24 04:24:23 -07:00 committed by Commit bot
parent 11fd60f5a9
commit 809f6b15be
5 changed files with 102 additions and 9 deletions

View File

@ -572,8 +572,8 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
} else {
DCHECK(instr->InputAt(1)->IsImmediate());
// 0.0 is the only immediate supported by vcmp instructions.
DCHECK(i.InputDouble(1) == 0.0);
__ VFPCompareAndSetFlags(i.InputFloat32Register(0), i.InputDouble(1));
DCHECK(i.InputFloat32(1) == 0.0f);
__ VFPCompareAndSetFlags(i.InputFloat32Register(0), i.InputFloat32(1));
}
DCHECK_EQ(SetCC, i.OutputSBit());
break;

View File

@ -770,8 +770,8 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
} else {
DCHECK(instr->InputAt(1)->IsImmediate());
// 0.0 is the only immediate supported by fcmp instructions.
DCHECK(i.InputDouble(1) == 0.0);
__ Fcmp(i.InputFloat32Register(0), i.InputDouble(1));
DCHECK(i.InputFloat32(1) == 0.0f);
__ Fcmp(i.InputFloat32Register(0), i.InputFloat32(1));
}
break;
case kArm64Float32Add:

View File

@ -37,6 +37,8 @@ class InstructionOperandConverter {
double InputDouble(size_t index) { return ToDouble(instr_->InputAt(index)); }
float InputFloat32(size_t index) { return ToFloat32(instr_->InputAt(index)); }
int32_t InputInt32(size_t index) {
return ToConstant(instr_->InputAt(index)).ToInt32();
}
@ -112,6 +114,8 @@ class InstructionOperandConverter {
double ToDouble(InstructionOperand* op) { return ToConstant(op).ToFloat64(); }
float ToFloat32(InstructionOperand* op) { return ToConstant(op).ToFloat32(); }
ExternalReference ToExternalReference(InstructionOperand* op) {
return ToConstant(op).ToExternalReference();
}

View File

@ -1008,16 +1008,36 @@ Reduction MachineOperatorReducer::ReduceFloat64InsertHighWord32(Node* node) {
}
namespace {
bool IsFloat64RepresentableAsFloat32(const Float64Matcher& m) {
if (m.HasValue()) {
double v = m.Value();
float fv = static_cast<float>(v);
return static_cast<double>(fv) == v;
}
return false;
}
} // namespace
Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
DCHECK((IrOpcode::kFloat64Equal == node->opcode()) ||
(IrOpcode::kFloat64LessThan == node->opcode()) ||
(IrOpcode::kFloat64LessThanOrEqual == node->opcode()));
// As all Float32 values have an exact representation in Float64, comparing
// two Float64 values both converted from Float32 is equivalent to comparing
// the original Float32s, so we can ignore the conversions.
// the original Float32s, so we can ignore the conversions. We can also reduce
// comparisons of converted Float64 values against constants that can be
// represented exactly as Float32.
Float64BinopMatcher m(node);
if (m.left().IsChangeFloat32ToFloat64() &&
m.right().IsChangeFloat32ToFloat64()) {
if ((m.left().IsChangeFloat32ToFloat64() &&
m.right().IsChangeFloat32ToFloat64()) ||
(m.left().IsChangeFloat32ToFloat64() &&
IsFloat64RepresentableAsFloat32(m.right())) ||
(IsFloat64RepresentableAsFloat32(m.left()) &&
m.right().IsChangeFloat32ToFloat64())) {
switch (node->opcode()) {
case IrOpcode::kFloat64Equal:
node->set_op(machine()->Float32Equal());
@ -1031,8 +1051,14 @@ Reduction MachineOperatorReducer::ReduceFloat64Compare(Node* node) {
default:
return NoChange();
}
node->ReplaceInput(0, m.left().InputAt(0));
node->ReplaceInput(1, m.right().InputAt(0));
node->ReplaceInput(
0, m.left().HasValue()
? Float32Constant(static_cast<float>(m.left().Value()))
: m.left().InputAt(0));
node->ReplaceInput(
1, m.right().HasValue()
? Float32Constant(static_cast<float>(m.right().Value()))
: m.right().InputAt(0));
return Changed(node);
}
return NoChange();

View File

@ -1454,6 +1454,19 @@ TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Conversions) {
}
TEST_F(MachineOperatorReducerTest, Float64EqualWithFloat32Constant) {
Node* const p0 = Parameter(0);
TRACED_FOREACH(float, x, kFloat32Values) {
Reduction r = Reduce(graph()->NewNode(
machine()->Float64Equal(),
graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat32Equal(p0, IsFloat32Constant(x)));
}
}
// -----------------------------------------------------------------------------
// Float64LessThan
@ -1470,6 +1483,30 @@ TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Conversions) {
}
TEST_F(MachineOperatorReducerTest, Float64LessThanWithFloat32Constant) {
Node* const p0 = Parameter(0);
{
TRACED_FOREACH(float, x, kFloat32Values) {
Reduction r = Reduce(graph()->NewNode(
machine()->Float64LessThan(),
graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat32LessThan(p0, IsFloat32Constant(x)));
}
}
{
TRACED_FOREACH(float, x, kFloat32Values) {
Reduction r = Reduce(graph()->NewNode(
machine()->Float64LessThan(), Float64Constant(x),
graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFloat32LessThan(IsFloat32Constant(x), p0));
}
}
}
// -----------------------------------------------------------------------------
// Float64LessThanOrEqual
@ -1487,6 +1524,32 @@ TEST_F(MachineOperatorReducerTest,
}
TEST_F(MachineOperatorReducerTest, Float64LessThanOrEqualWithFloat32Constant) {
Node* const p0 = Parameter(0);
{
TRACED_FOREACH(float, x, kFloat32Values) {
Reduction r = Reduce(graph()->NewNode(
machine()->Float64LessThanOrEqual(),
graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0),
Float64Constant(x)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat32LessThanOrEqual(p0, IsFloat32Constant(x)));
}
}
{
TRACED_FOREACH(float, x, kFloat32Values) {
Reduction r = Reduce(graph()->NewNode(
machine()->Float64LessThanOrEqual(), Float64Constant(x),
graph()->NewNode(machine()->ChangeFloat32ToFloat64(), p0)));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsFloat32LessThanOrEqual(IsFloat32Constant(x), p0));
}
}
}
// -----------------------------------------------------------------------------
// Store