Commit 51f3c66b authored by baptiste.afsa's avatar baptiste.afsa Committed by Commit bot

[turbofan] Allow 0.0 as immediate for floating-point comparison on arm/arm64.

R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#26066}
parent 06559af7
...@@ -494,8 +494,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -494,8 +494,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
DCHECK_EQ(SetCC, i.OutputSBit()); DCHECK_EQ(SetCC, i.OutputSBit());
break; break;
case kArmVcmpF64: case kArmVcmpF64:
__ VFPCompareAndSetFlags(i.InputFloat64Register(0), if (instr->InputAt(1)->IsDoubleRegister()) {
i.InputFloat64Register(1)); __ VFPCompareAndSetFlags(i.InputFloat64Register(0),
i.InputFloat64Register(1));
} else {
DCHECK(instr->InputAt(1)->IsImmediate());
// 0.0 is the only immediate supported by vcmp instructions.
DCHECK(i.InputDouble(1) == 0.0);
__ VFPCompareAndSetFlags(i.InputFloat64Register(0), i.InputDouble(1));
}
DCHECK_EQ(SetCC, i.OutputSBit()); DCHECK_EQ(SetCC, i.OutputSBit());
break; break;
case kArmVaddF64: case kArmVaddF64:
......
...@@ -1073,16 +1073,18 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node, ...@@ -1073,16 +1073,18 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) { FlagsContinuation* cont) {
ArmOperandGenerator g(selector); ArmOperandGenerator g(selector);
Float64BinopMatcher m(node); Float64BinopMatcher m(node);
InstructionOperand* rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node())
: g.UseRegister(m.right().node());
if (cont->IsBranch()) { if (cont->IsBranch()) {
selector->Emit(cont->Encode(kArmVcmpF64), nullptr, selector->Emit(cont->Encode(kArmVcmpF64), nullptr,
g.UseRegister(m.left().node()), g.UseRegister(m.left().node()), rhs,
g.UseRegister(m.right().node()), g.Label(cont->true_block()), g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl(); g.Label(cont->false_block()))->MarkAsControl();
} else { } else {
DCHECK(cont->IsSet()); DCHECK(cont->IsSet());
selector->Emit( selector->Emit(cont->Encode(kArmVcmpF64),
cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()), g.DefineAsRegister(cont->result()),
g.UseRegister(m.left().node()), g.UseRegister(m.right().node())); g.UseRegister(m.left().node()), rhs);
} }
} }
......
...@@ -624,7 +624,14 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -624,7 +624,14 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Tst(i.InputRegister32(0), i.InputOperand32(1)); __ Tst(i.InputRegister32(0), i.InputOperand32(1));
break; break;
case kArm64Float64Cmp: case kArm64Float64Cmp:
__ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); if (instr->InputAt(1)->IsDoubleRegister()) {
__ Fcmp(i.InputDoubleRegister(0), i.InputDoubleRegister(1));
} else {
DCHECK(instr->InputAt(1)->IsImmediate());
// 0.0 is the only immediate supported by fcmp instructions.
DCHECK(i.InputDouble(1) == 0.0);
__ Fcmp(i.InputDoubleRegister(0), i.InputDouble(1));
}
break; break;
case kArm64Float64Add: case kArm64Float64Add:
__ Fadd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), __ Fadd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
......
...@@ -1220,10 +1220,14 @@ static void VisitWord64Test(InstructionSelector* selector, Node* node, ...@@ -1220,10 +1220,14 @@ static void VisitWord64Test(InstructionSelector* selector, Node* node,
static void VisitFloat64Compare(InstructionSelector* selector, Node* node, static void VisitFloat64Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) { FlagsContinuation* cont) {
Arm64OperandGenerator g(selector); Arm64OperandGenerator g(selector);
Node* left = node->InputAt(0); Float64BinopMatcher m(node);
Node* right = node->InputAt(1); if (m.right().Is(0.0)) {
VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(left), VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()),
g.UseRegister(right), cont); g.UseImmediate(m.right().node()), cont);
} else {
VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()),
g.UseRegister(m.right().node()), cont);
}
} }
......
...@@ -1478,6 +1478,85 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, ...@@ -1478,6 +1478,85 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
::testing::ValuesIn(kComparisons)); ::testing::ValuesIn(kComparisons));
// -----------------------------------------------------------------------------
// Floating point comparisons.
const Comparison kFPComparisons[] = {
{&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual},
{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
kUnsignedLessThan, kUnsignedGreaterThanOrEqual},
{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
kUnsignedLessThanOrEqual, kUnsignedGreaterThan}};
typedef InstructionSelectorTestWithParam<Comparison>
InstructionSelectorFPComparisonTest;
TEST_P(InstructionSelectorFPComparisonTest, WithParameters) {
const Comparison& cmp = GetParam();
StreamBuilder m(this, kMachInt32, kMachFloat64, kMachFloat64);
m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)));
Stream const s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
}
TEST_P(InstructionSelectorFPComparisonTest, NegatedWithParameters) {
const Comparison& cmp = GetParam();
StreamBuilder m(this, kMachInt32, kMachFloat64, kMachFloat64);
m.Return(
m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))));
Stream const s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
}
TEST_P(InstructionSelectorFPComparisonTest, WithImmediateZeroOnRight) {
const Comparison& cmp = GetParam();
StreamBuilder m(this, kMachInt32, kMachFloat64);
m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
Stream const s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
InstructionSelectorFPComparisonTest,
::testing::ValuesIn(kFPComparisons));
TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) {
StreamBuilder m(this, kMachInt32, kMachFloat64);
m.Return(m.Float64Equal(m.Float64Constant(0.0), m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(kEqual, s[0]->flags_condition());
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Miscellaneous. // Miscellaneous.
......
...@@ -1518,10 +1518,39 @@ TEST_P(InstructionSelectorFPCmpTest, Parameter) { ...@@ -1518,10 +1518,39 @@ TEST_P(InstructionSelectorFPCmpTest, Parameter) {
} }
TEST_P(InstructionSelectorFPCmpTest, WithImmediateZeroOnRight) {
const FPCmp cmp = GetParam();
StreamBuilder m(this, kMachInt32, cmp.mi.machine_type);
m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Float64Constant(0.0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest,
::testing::ValuesIn(kFPCmpInstructions)); ::testing::ValuesIn(kFPCmpInstructions));
TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) {
StreamBuilder m(this, kMachInt32, kMachFloat64);
m.Return(m.Float64Equal(m.Float64Constant(0.0), m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Float64Cmp, s[0]->arch_opcode());
EXPECT_EQ(2U, s[0]->InputCount());
EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(kEqual, s[0]->flags_condition());
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Conversions. // Conversions.
......
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