[turbofan] Allow 0.0 as immediate for floating-point comparison on arm/arm64.
authorbaptiste.afsa <baptiste.afsa@arm.com>
Thu, 15 Jan 2015 06:30:51 +0000 (22:30 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 15 Jan 2015 06:31:07 +0000 (06:31 +0000)
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#26066}

src/compiler/arm/code-generator-arm.cc
src/compiler/arm/instruction-selector-arm.cc
src/compiler/arm64/code-generator-arm64.cc
src/compiler/arm64/instruction-selector-arm64.cc
test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc

index 81298aa..5616337 100644 (file)
@@ -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:
index 943ad0f..fb25c3b 100644 (file)
@@ -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);
   }
 }
 
index ecdf148..478fcfa 100644 (file)
@@ -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),
index 09c7f2f..1d83a51 100644 (file)
@@ -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);
+  }
 }
 
 
index fbdf87a..1fa0b10 100644 (file)
@@ -1479,6 +1479,85 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
 
 
 // -----------------------------------------------------------------------------
+// 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.
 
 
index 776605c..571dbec 100644 (file)
@@ -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.