[optimizing compiler] Add div-int and exception handling.

- for backends: arm, x86, x86_64
- fixed a register allocator bug: the request for a fixed register for
the first input was ignored if the output was kSameAsFirstInput
- added divide by zero exception
- more tests
- shuffle around some code in the builder to reduce the number of lines
of code for a single function.

Change-Id: Id3a515e02bfbc66cd9d16cb9746f7551bdab3d42
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 39e564a..982d6d4 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -92,6 +92,22 @@
   DISALLOW_COPY_AND_ASSIGN(NullCheckSlowPathARM);
 };
 
+class DivZeroCheckSlowPathARM : public SlowPathCodeARM {
+ public:
+  explicit DivZeroCheckSlowPathARM(HDivZeroCheck* instruction) : instruction_(instruction) {}
+
+  virtual void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
+    CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
+    __ Bind(GetEntryLabel());
+    arm_codegen->InvokeRuntime(
+        QUICK_ENTRY_POINT(pThrowDivZero), instruction_, instruction_->GetDexPc());
+  }
+
+ private:
+  HDivZeroCheck* const instruction_;
+  DISALLOW_COPY_AND_ASSIGN(DivZeroCheckSlowPathARM);
+};
+
 class StackOverflowCheckSlowPathARM : public SlowPathCodeARM {
  public:
   StackOverflowCheckSlowPathARM() {}
@@ -785,6 +801,7 @@
   DCHECK(instruction->IsSuspendCheck()
       || instruction->IsBoundsCheck()
       || instruction->IsNullCheck()
+      || instruction->IsDivZeroCheck()
       || !IsLeafMethod());
 }
 
@@ -1533,7 +1550,12 @@
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(div, LocationSummary::kNoCall);
   switch (div->GetResultType()) {
-    case Primitive::kPrimInt:
+    case Primitive::kPrimInt: {
+      locations->SetInAt(0, Location::RequiresRegister());
+      locations->SetInAt(1, Location::RequiresRegister());
+      locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+      break;
+    }
     case Primitive::kPrimLong: {
       LOG(FATAL) << "Not implemented div type" << div->GetResultType();
       break;
@@ -1558,7 +1580,11 @@
   Location second = locations->InAt(1);
 
   switch (div->GetResultType()) {
-    case Primitive::kPrimInt:
+    case Primitive::kPrimInt: {
+      __ sdiv(out.As<Register>(), first.As<Register>(), second.As<Register>());
+      break;
+    }
+
     case Primitive::kPrimLong: {
       LOG(FATAL) << "Not implemented div type" << div->GetResultType();
       break;
@@ -1581,6 +1607,27 @@
   }
 }
 
+void LocationsBuilderARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
+  LocationSummary* locations =
+      new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
+  locations->SetInAt(0, Location::RequiresRegister());
+  if (instruction->HasUses()) {
+    locations->SetOut(Location::SameAsFirstInput());
+  }
+}
+
+void InstructionCodeGeneratorARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
+  SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) DivZeroCheckSlowPathARM(instruction);
+  codegen_->AddSlowPath(slow_path);
+
+  LocationSummary* locations = instruction->GetLocations();
+  Location value = locations->InAt(0);
+
+  DCHECK(value.IsRegister()) << value;
+  __ cmp(value.As<Register>(), ShifterOperand(0));
+  __ b(slow_path->GetEntryLabel(), EQ);
+}
+
 void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) {
   LocationSummary* locations =
       new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);