[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}
This commit is contained in:
parent
06559af7b4
commit
51f3c66b64
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user