[optimizing compiler] Add division for floats and doubles

backends: x86, x86_64, arm.

Also:
- ordered instructions based on their name.
- add missing kNoOutputOverlap to add/sub/mul.

Change-Id: Ie47cde3b15ac74e7a1660c67a2eed1d7871f0ad0
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index cc9c6c1..f80ebdb 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -828,6 +828,16 @@
       break;
     }
 
+    case Instruction::DIV_FLOAT: {
+      Binop_23x<HDiv>(instruction, Primitive::kPrimFloat);
+      break;
+    }
+
+    case Instruction::DIV_DOUBLE: {
+      Binop_23x<HDiv>(instruction, Primitive::kPrimDouble);
+      break;
+    }
+
     case Instruction::ADD_LONG_2ADDR: {
       Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
       break;
@@ -883,6 +893,16 @@
       break;
     }
 
+    case Instruction::DIV_FLOAT_2ADDR: {
+      Binop_12x<HDiv>(instruction, Primitive::kPrimFloat);
+      break;
+    }
+
+    case Instruction::DIV_DOUBLE_2ADDR: {
+      Binop_12x<HDiv>(instruction, Primitive::kPrimDouble);
+      break;
+    }
+
     case Instruction::ADD_INT_LIT16: {
       Binop_22s<HAdd>(instruction, false);
       break;
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 7adf2cc..a5d4c43 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1128,7 +1128,7 @@
     case Primitive::kPrimDouble: {
       locations->SetInAt(0, Location::RequiresFpuRegister());
       locations->SetInAt(1, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
       break;
     }
 
@@ -1193,7 +1193,7 @@
     case Primitive::kPrimDouble: {
       locations->SetInAt(0, Location::RequiresFpuRegister());
       locations->SetInAt(1, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
       break;
     }
     default:
@@ -1262,7 +1262,7 @@
     case Primitive::kPrimDouble: {
       locations->SetInAt(0, Location::RequiresFpuRegister());
       locations->SetInAt(1, Location::RequiresFpuRegister());
-      locations->SetOut(Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
       break;
     }
 
@@ -1329,6 +1329,58 @@
   }
 }
 
+void LocationsBuilderARM::VisitDiv(HDiv* div) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+  switch (div->GetResultType()) {
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+      break;
+    }
+    case Primitive::kPrimFloat:
+    case Primitive::kPrimDouble: {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetOut(Location::RequiresFpuRegister(), Location::kNoOutputOverlap);
+      break;
+    }
+
+    default:
+      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+  }
+}
+
+void InstructionCodeGeneratorARM::VisitDiv(HDiv* div) {
+  LocationSummary* locations = div->GetLocations();
+  Location out = locations->Out();
+  Location first = locations->InAt(0);
+  Location second = locations->InAt(1);
+
+  switch (div->GetResultType()) {
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+      break;
+    }
+
+    case Primitive::kPrimFloat: {
+      __ vdivs(out.As<SRegister>(), first.As<SRegister>(), second.As<SRegister>());
+      break;
+    }
+
+    case Primitive::kPrimDouble: {
+      __ vdivd(FromLowSToD(out.AsFpuRegisterPairLow<SRegister>()),
+               FromLowSToD(first.AsFpuRegisterPairLow<SRegister>()),
+               FromLowSToD(second.AsFpuRegisterPairLow<SRegister>()));
+      break;
+    }
+
+    default:
+      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+  }
+}
+
 void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 79528ac..f9aa44b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -535,6 +535,7 @@
   M(ArrayGet)                                              \
   M(ArraySet)                                              \
   M(DoubleConstant)                                        \
+  M(Div)                                                   \
   M(FloatConstant)                                         \
   M(Mul)                                                   \
   M(Neg)                                                   \
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 99fa11d..495ff8b 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1293,6 +1293,56 @@
   }
 }
 
+void LocationsBuilderX86::VisitDiv(HDiv* div) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+  switch (div->GetResultType()) {
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+      break;
+    }
+    case Primitive::kPrimFloat:
+    case Primitive::kPrimDouble: {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    }
+
+    default:
+      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+  }
+}
+
+void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) {
+  LocationSummary* locations = div->GetLocations();
+  Location first = locations->InAt(0);
+  Location second = locations->InAt(1);
+  DCHECK(first.Equals(locations->Out()));
+
+  switch (div->GetResultType()) {
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+      break;
+    }
+
+    case Primitive::kPrimFloat: {
+      __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
+      break;
+    }
+
+    case Primitive::kPrimDouble: {
+      __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+      break;
+    }
+
+    default:
+      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+  }
+}
+
 void LocationsBuilderX86::VisitNewInstance(HNewInstance* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 163156a..4d11a24 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1218,6 +1218,56 @@
   }
 }
 
+void LocationsBuilderX86_64::VisitDiv(HDiv* div) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
+  switch (div->GetResultType()) {
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+      break;
+    }
+    case Primitive::kPrimFloat:
+    case Primitive::kPrimDouble: {
+      locations->SetInAt(0, Location::RequiresFpuRegister());
+      locations->SetInAt(1, Location::RequiresFpuRegister());
+      locations->SetOut(Location::SameAsFirstInput());
+      break;
+    }
+
+    default:
+      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+  }
+}
+
+void InstructionCodeGeneratorX86_64::VisitDiv(HDiv* div) {
+  LocationSummary* locations = div->GetLocations();
+  Location first = locations->InAt(0);
+  Location second = locations->InAt(1);
+  DCHECK(first.Equals(locations->Out()));
+
+  switch (div->GetResultType()) {
+    case Primitive::kPrimInt:
+    case Primitive::kPrimLong: {
+      LOG(FATAL) << "Not implemented div type" << div->GetResultType();
+      break;
+    }
+
+    case Primitive::kPrimFloat: {
+      __ divss(first.As<XmmRegister>(), second.As<XmmRegister>());
+      break;
+    }
+
+    case Primitive::kPrimDouble: {
+      __ divsd(first.As<XmmRegister>(), second.As<XmmRegister>());
+      break;
+    }
+
+    default:
+      LOG(FATAL) << "Unexpected div type " << div->GetResultType();
+  }
+}
+
 void LocationsBuilderX86_64::VisitNewInstance(HNewInstance* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7adb840..f530708 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -468,46 +468,47 @@
 
 #define FOR_EACH_CONCRETE_INSTRUCTION(M)                                \
   M(Add, BinaryOperation)                                               \
+  M(ArrayGet, Instruction)                                              \
+  M(ArrayLength, Instruction)                                           \
+  M(ArraySet, Instruction)                                              \
+  M(BoundsCheck, Instruction)                                           \
+  M(Compare, BinaryOperation)                                           \
   M(Condition, BinaryOperation)                                         \
+  M(Div, BinaryOperation)                                               \
+  M(DoubleConstant, Constant)                                           \
   M(Equal, Condition)                                                   \
-  M(NotEqual, Condition)                                                \
-  M(LessThan, Condition)                                                \
-  M(LessThanOrEqual, Condition)                                         \
+  M(Exit, Instruction)                                                  \
+  M(FloatConstant, Constant)                                            \
+  M(Goto, Instruction)                                                  \
   M(GreaterThan, Condition)                                             \
   M(GreaterThanOrEqual, Condition)                                      \
-  M(Exit, Instruction)                                                  \
-  M(Goto, Instruction)                                                  \
   M(If, Instruction)                                                    \
+  M(InstanceFieldGet, Instruction)                                      \
+  M(InstanceFieldSet, Instruction)                                      \
   M(IntConstant, Constant)                                              \
   M(InvokeStatic, Invoke)                                               \
   M(InvokeVirtual, Invoke)                                              \
+  M(LessThan, Condition)                                                \
+  M(LessThanOrEqual, Condition)                                         \
   M(LoadLocal, Instruction)                                             \
   M(Local, Instruction)                                                 \
   M(LongConstant, Constant)                                             \
+  M(Mul, BinaryOperation)                                               \
+  M(Neg, UnaryOperation)                                                \
+  M(NewArray, Instruction)                                              \
   M(NewInstance, Instruction)                                           \
   M(Not, UnaryOperation)                                                \
-  M(ParameterValue, Instruction)                                        \
+  M(NotEqual, Condition)                                                \
+  M(NullCheck, Instruction)                                             \
   M(ParallelMove, Instruction)                                          \
+  M(ParameterValue, Instruction)                                        \
   M(Phi, Instruction)                                                   \
   M(Return, Instruction)                                                \
   M(ReturnVoid, Instruction)                                            \
   M(StoreLocal, Instruction)                                            \
   M(Sub, BinaryOperation)                                               \
-  M(Compare, BinaryOperation)                                           \
-  M(InstanceFieldGet, Instruction)                                      \
-  M(InstanceFieldSet, Instruction)                                      \
-  M(ArrayGet, Instruction)                                              \
-  M(ArraySet, Instruction)                                              \
-  M(ArrayLength, Instruction)                                           \
-  M(BoundsCheck, Instruction)                                           \
-  M(NullCheck, Instruction)                                             \
-  M(Temporary, Instruction)                                             \
   M(SuspendCheck, Instruction)                                          \
-  M(Mul, BinaryOperation)                                               \
-  M(Neg, UnaryOperation)                                                \
-  M(FloatConstant, Constant)                                            \
-  M(DoubleConstant, Constant)                                           \
-  M(NewArray, Instruction)                                              \
+  M(Temporary, Instruction)                                             \
 
 #define FOR_EACH_INSTRUCTION(M)                                         \
   FOR_EACH_CONCRETE_INSTRUCTION(M)                                      \
@@ -1658,8 +1659,6 @@
   HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
       : HBinaryOperation(result_type, left, right) {}
 
-  virtual bool IsCommutative() { return false; }
-
   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
     return x - y;
   }
@@ -1689,6 +1688,20 @@
   DISALLOW_COPY_AND_ASSIGN(HMul);
 };
 
+class HDiv : public HBinaryOperation {
+ public:
+  HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+      : HBinaryOperation(result_type, left, right) {}
+
+  virtual int32_t Evaluate(int32_t x, int32_t y) const { return x / y; }
+  virtual int64_t Evaluate(int64_t x, int64_t y) const { return x / y; }
+
+  DECLARE_INSTRUCTION(Div);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HDiv);
+};
+
 // The value of a parameter in this method. Its location depends on
 // the calling convention.
 class HParameterValue : public HExpression<0> {