Add support for adding two integers in optimizing compiler.

Change-Id: I5524e193cd07f2692a57c6b4f8069904471b2928
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index db77fee..64ecdb5 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -211,6 +211,38 @@
       break;
     }
 
+    case Instruction::ADD_INT: {
+      HInstruction* first = LoadLocal(instruction.VRegB());
+      HInstruction* second = LoadLocal(instruction.VRegC());
+      current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
+      UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+      break;
+    }
+
+    case Instruction::ADD_INT_2ADDR: {
+      HInstruction* first = LoadLocal(instruction.VRegA());
+      HInstruction* second = LoadLocal(instruction.VRegB());
+      current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
+      UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+      break;
+    }
+
+    case Instruction::ADD_INT_LIT16: {
+      HInstruction* first = LoadLocal(instruction.VRegB());
+      HInstruction* second = GetConstant(instruction.VRegC_22s());
+      current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
+      UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+      break;
+    }
+
+    case Instruction::ADD_INT_LIT8: {
+      HInstruction* first = LoadLocal(instruction.VRegB());
+      HInstruction* second = GetConstant(instruction.VRegC_22b());
+      current_block_->AddInstruction(new (arena_) HAdd(Primitive::kPrimInt, first, second));
+      UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+      break;
+    }
+
     case Instruction::NOP:
       break;
 
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c85d67d..68c997b 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -221,5 +221,33 @@
   codegen_->RecordPcInfo(invoke->GetDexPc());
 }
 
+void LocationsBuilderARM::VisitAdd(HAdd* add) {
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
+  switch (add->GetResultType()) {
+    case Primitive::kPrimInt: {
+      locations->SetInAt(0, Location(R0));
+      locations->SetInAt(1, Location(R1));
+      locations->SetOut(Location(R0));
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unimplemented";
+  }
+  add->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) {
+  LocationSummary* locations = add->GetLocations();
+  switch (add->GetResultType()) {
+    case Primitive::kPrimInt:
+      __ add(locations->Out().reg<Register>(),
+             locations->InAt(0).reg<Register>(),
+             ShifterOperand(locations->InAt(1).reg<Register>()));
+      break;
+    default:
+      LOG(FATAL) << "Unimplemented";
+  }
+}
+
 }  // namespace arm
 }  // namespace art
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 54bff0c..1764486 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -218,5 +218,32 @@
   codegen_->RecordPcInfo(invoke->GetDexPc());
 }
 
+void LocationsBuilderX86::VisitAdd(HAdd* add) {
+  LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add);
+  switch (add->GetResultType()) {
+    case Primitive::kPrimInt: {
+      locations->SetInAt(0, Location(EAX));
+      locations->SetInAt(1, Location(ECX));
+      locations->SetOut(Location(EAX));
+      break;
+    }
+    default:
+      LOG(FATAL) << "Unimplemented";
+  }
+  add->SetLocations(locations);
+}
+
+void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) {
+  LocationSummary* locations = add->GetLocations();
+  switch (add->GetResultType()) {
+    case Primitive::kPrimInt:
+      DCHECK_EQ(locations->InAt(0).reg<Register>(), locations->Out().reg<Register>());
+      __ addl(locations->InAt(0).reg<Register>(), locations->InAt(1).reg<Register>());
+      break;
+    default:
+      LOG(FATAL) << "Unimplemented";
+  }
+}
+
 }  // namespace x86
 }  // namespace art
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index ff743d8..d40990e 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -196,4 +196,42 @@
   TestCode(data, true, 0);
 }
 
+TEST(CodegenTest, ReturnAdd1) {
+  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
+    Instruction::CONST_4 | 3 << 12 | 0,
+    Instruction::CONST_4 | 4 << 12 | 1 << 8,
+    Instruction::ADD_INT, 1 << 8 | 0,
+    Instruction::RETURN);
+
+  TestCode(data, true, 7);
+}
+
+TEST(CodegenTest, ReturnAdd2) {
+  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
+    Instruction::CONST_4 | 3 << 12 | 0,
+    Instruction::CONST_4 | 4 << 12 | 1 << 8,
+    Instruction::ADD_INT_2ADDR | 1 << 12,
+    Instruction::RETURN);
+
+  TestCode(data, true, 7);
+}
+
+TEST(CodegenTest, ReturnAdd3) {
+  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
+    Instruction::CONST_4 | 4 << 12 | 0 << 8,
+    Instruction::ADD_INT_LIT8, 3 << 8 | 0,
+    Instruction::RETURN);
+
+  TestCode(data, true, 7);
+}
+
+TEST(CodegenTest, ReturnAdd4) {
+  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
+    Instruction::CONST_4 | 4 << 12 | 0 << 8,
+    Instruction::ADD_INT_LIT16, 3,
+    Instruction::RETURN);
+
+  TestCode(data, true, 7);
+}
+
 }  // namespace art
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 50d5c59..fc67486 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -180,6 +180,7 @@
 };
 
 #define FOR_EACH_INSTRUCTION(M)                            \
+  M(Add)                                                   \
   M(Equal)                                                 \
   M(Exit)                                                  \
   M(Goto)                                                  \
@@ -477,14 +478,36 @@
   DISALLOW_COPY_AND_ASSIGN(HIf);
 };
 
-// Instruction to check if two inputs are equal to each other.
-class HEqual : public HTemplateInstruction<2> {
+class HBinaryOperation : public HTemplateInstruction<2> {
  public:
-  HEqual(HInstruction* first, HInstruction* second) {
-    SetRawInputAt(0, first);
-    SetRawInputAt(1, second);
+  HBinaryOperation(Primitive::Type result_type,
+                   HInstruction* left,
+                   HInstruction* right) : result_type_(result_type) {
+    SetRawInputAt(0, left);
+    SetRawInputAt(1, right);
   }
 
+  HInstruction* GetLeft() const { return InputAt(0); }
+  HInstruction* GetRight() const { return InputAt(1); }
+  Primitive::Type GetResultType() const { return result_type_; }
+
+  virtual bool IsCommutative() { return false; }
+
+ private:
+  const Primitive::Type result_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
+};
+
+
+// Instruction to check if two inputs are equal to each other.
+class HEqual : public HBinaryOperation {
+ public:
+  HEqual(HInstruction* first, HInstruction* second)
+      : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
+
+  virtual bool IsCommutative() { return true; }
+
   DECLARE_INSTRUCTION(Equal)
 
  private:
@@ -591,6 +614,19 @@
   DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
 };
 
+class HAdd : public HBinaryOperation {
+ public:
+  HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
+      : HBinaryOperation(result_type, left, right) {}
+
+  virtual bool IsCommutative() { return true; }
+
+  DECLARE_INSTRUCTION(Add);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(HAdd);
+};
+
 class HGraphVisitor : public ValueObject {
  public:
   explicit HGraphVisitor(HGraph* graph) : graph_(graph) { }