[optimizing compiler] Add DIV_INT_2ADDR

Change-Id: I38fc7e216f820d8ccc8bbf8b8e7a67b75fb9de87
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index e43841a..6ee236e 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -537,16 +537,16 @@
   return true;
 }
 
-void HGraphBuilder::BuildCheckedDiv(const Instruction& instruction,
+void HGraphBuilder::BuildCheckedDiv(uint16_t out_reg,
+                                    uint16_t first_reg,
+                                    uint16_t second_reg,
                                     uint32_t dex_offset,
                                     Primitive::Type type,
                                     bool second_is_lit) {
   DCHECK(type == Primitive::kPrimInt);
 
-  HInstruction* first = LoadLocal(instruction.VRegB(), type);
-  HInstruction* second = second_is_lit
-      ? GetIntConstant(instruction.VRegC())
-      : LoadLocal(instruction.VRegC(), type);
+  HInstruction* first = LoadLocal(first_reg, type);
+  HInstruction* second = second_is_lit ? GetIntConstant(second_reg) : LoadLocal(second_reg, type);
   if (!second->IsIntConstant() || (second->AsIntConstant()->GetValue() == 0)) {
     second = new (arena_) HDivZeroCheck(second, dex_offset);
     Temporaries temps(graph_, 1);
@@ -555,7 +555,7 @@
   }
 
   current_block_->AddInstruction(new (arena_) HDiv(type, first, second));
-  UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+  UpdateLocal(out_reg, current_block_->GetLastInstruction());
 }
 
 void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
@@ -977,7 +977,8 @@
     }
 
     case Instruction::DIV_INT: {
-      BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, false);
+      BuildCheckedDiv(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
+                      dex_offset, Primitive::kPrimInt, false);
       break;
     }
 
@@ -1046,6 +1047,12 @@
       break;
     }
 
+    case Instruction::DIV_INT_2ADDR: {
+      BuildCheckedDiv(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
+                      dex_offset, Primitive::kPrimInt, false);
+      break;
+    }
+
     case Instruction::DIV_FLOAT_2ADDR: {
       Binop_12x<HDiv>(instruction, Primitive::kPrimFloat);
       break;
@@ -1088,7 +1095,8 @@
 
     case Instruction::DIV_INT_LIT16:
     case Instruction::DIV_INT_LIT8: {
-      BuildCheckedDiv(instruction, dex_offset, Primitive::kPrimInt, true);
+      BuildCheckedDiv(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
+                      dex_offset, Primitive::kPrimInt, true);
       break;
     }
 
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index f09f729..78ed035 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -120,7 +120,9 @@
                       Primitive::Type input_type,
                       Primitive::Type result_type);
 
-  void BuildCheckedDiv(const Instruction& instruction,
+  void BuildCheckedDiv(uint16_t out_reg,
+                       uint16_t first_reg,
+                       uint16_t second_reg,
                        uint32_t dex_offset,
                        Primitive::Type type,
                        bool second_is_lit);
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 6d4514f..be3f5f3 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -552,4 +552,18 @@
   TestCode(data, true, 1);
 }
 
+#if defined(__aarch64__)
+TEST(CodegenTest, DISABLED_ReturnDivInt2Addr) {
+#else
+TEST(CodegenTest, ReturnDivInt2Addr) {
+#endif
+  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
+    Instruction::CONST_4 | 4 << 12 | 0,
+    Instruction::CONST_4 | 2 << 12 | 1 << 8,
+    Instruction::DIV_INT_2ADDR | 1 << 12,
+    Instruction::RETURN);
+
+  TestCode(data, true, 2);
+}
+
 }  // namespace art