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) {
DCHECK_EQ(SetCC, i.OutputSBit());
break;
case kArmVcmpF64:
__ VFPCompareAndSetFlags(i.InputFloat64Register(0),
i.InputFloat64Register(1));
if (instr->InputAt(1)->IsDoubleRegister()) {
__ 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());
break;
case kArmVaddF64:
......
......@@ -1073,16 +1073,18 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
Float64BinopMatcher m(node);
InstructionOperand* rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node())
: g.UseRegister(m.right().node());
if (cont->IsBranch()) {
selector->Emit(cont->Encode(kArmVcmpF64), nullptr,
g.UseRegister(m.left().node()),
g.UseRegister(m.right().node()), g.Label(cont->true_block()),
g.UseRegister(m.left().node()), rhs,
g.Label(cont->true_block()),
g.Label(cont->false_block()))->MarkAsControl();
} else {
DCHECK(cont->IsSet());
selector->Emit(
cont->Encode(kArmVcmpF64), g.DefineAsRegister(cont->result()),
g.UseRegister(m.left().node()), g.UseRegister(m.right().node()));
selector->Emit(cont->Encode(kArmVcmpF64),
g.DefineAsRegister(cont->result()),
g.UseRegister(m.left().node()), rhs);
}
}
......
......@@ -624,7 +624,14 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
__ Tst(i.InputRegister32(0), i.InputOperand32(1));
break;
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;
case kArm64Float64Add:
__ Fadd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
......
......@@ -1220,10 +1220,14 @@ static void VisitWord64Test(InstructionSelector* selector, Node* node,
static void VisitFloat64Compare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
Arm64OperandGenerator g(selector);
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(left),
g.UseRegister(right), cont);
Float64BinopMatcher m(node);
if (m.right().Is(0.0)) {
VisitCompare(selector, kArm64Float64Cmp, g.UseRegister(m.left().node()),
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,
::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.
......
......@@ -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,
::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.
......
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