diff options
author | 2014-03-28 15:43:40 +0000 | |
---|---|---|
committer | 2014-03-31 11:41:39 +0100 | |
commit | d8ee737fdbf380c5bb90c9270c8d1087ac23e76c (patch) | |
tree | becdbf2b4e2a3c84952bd7b1db60a2daccd47206 /compiler/optimizing | |
parent | 7f466c08888129a9923cb973a4dc73ee4a71574e (diff) |
Add support for adding two integers in optimizing compiler.
Change-Id: I5524e193cd07f2692a57c6b4f8069904471b2928
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 32 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 28 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 27 | ||||
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 38 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 46 |
5 files changed, 166 insertions, 5 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index db77feef63..64ecdb5c24 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -211,6 +211,38 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_ 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 c85d67da6c..68c997bf5f 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -221,5 +221,33 @@ void InstructionCodeGeneratorARM::VisitInvokeStatic(HInvokeStatic* invoke) { 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 54bff0c454..1764486e57 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -218,5 +218,32 @@ void InstructionCodeGeneratorX86::VisitInvokeStatic(HInvokeStatic* invoke) { 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 ff743d8ed3..d40990e86b 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -196,4 +196,42 @@ TEST(CodegenTest, ReturnIf2) { 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 50d5c59672..fc67486267 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -180,6 +180,7 @@ class HBasicBlock : public ArenaObject { }; #define FOR_EACH_INSTRUCTION(M) \ + M(Add) \ M(Equal) \ M(Exit) \ M(Goto) \ @@ -477,14 +478,36 @@ class HIf : public HTemplateInstruction<1> { 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 @@ class HInvokeStatic : public HInvoke { 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) { } |