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) { }