[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:
parent
11fd60f5a9
commit
809f6b15be
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user