diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-03-04 14:46:47 +0000 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-03-10 11:41:22 +0000 |
commit | 3ff386aafefd5282bb76c8a50506a70a4321e698 (patch) | |
tree | 5f6e990553daae150a168f581bac79e659f7f712 /compiler/optimizing/builder.cc | |
parent | 0307b5c91c287e08cd414ecc5de32befceb7e371 (diff) | |
download | art-3ff386aafefd5282bb76c8a50506a70a4321e698.zip art-3ff386aafefd5282bb76c8a50506a70a4321e698.tar.gz art-3ff386aafefd5282bb76c8a50506a70a4321e698.tar.bz2 |
Add register support to the optimizing compiler.
Also make if take an input and build the use list for instructions.
Change-Id: I1938cee7dce5bd4c66b259fa2b431d2c79b3cf82
Diffstat (limited to 'compiler/optimizing/builder.cc')
-rw-r--r-- | compiler/optimizing/builder.cc | 76 |
1 files changed, 71 insertions, 5 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index f78e56b..190c925 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -15,23 +15,46 @@ * limitations under the License. */ +#include "dex_file.h" #include "dex_instruction.h" +#include "dex_instruction-inl.h" #include "builder.h" #include "nodes.h" namespace art { -HGraph* HGraphBuilder::BuildGraph(const uint16_t* code_ptr, const uint16_t* code_end) { +void HGraphBuilder::InitializeLocals(int count) { + locals_.SetSize(count); + for (int i = 0; i < count; i++) { + HLocal* local = new (arena_) HLocal(i); + entry_block_->AddInstruction(local); + locals_.Put(0, local); + } +} + +static bool CanHandleCodeItem(const DexFile::CodeItem& code_item) { + if (code_item.tries_size_ > 0) return false; + if (code_item.outs_size_ > 0) return false; + if (code_item.ins_size_ > 0) return false; + return true; +} + +HGraph* HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) { + if (!CanHandleCodeItem(code_item)) return nullptr; + + const uint16_t* code_ptr = code_item.insns_; + const uint16_t* code_end = code_item.insns_ + code_item.insns_size_in_code_units_; + // Setup the graph with the entry block and exit block. graph_ = new (arena_) HGraph(arena_); entry_block_ = new (arena_) HBasicBlock(graph_); graph_->AddBlock(entry_block_); - entry_block_->AddInstruction(new (arena_) HGoto()); exit_block_ = new (arena_) HBasicBlock(graph_); - exit_block_->AddInstruction(new (arena_) HExit()); graph_->set_entry_block(entry_block_); graph_->set_exit_block(exit_block_); + InitializeLocals(code_item.registers_size_); + // To avoid splitting blocks, we compute ahead of time the instructions that // start a new block, and create these blocks. ComputeBranchTargets(code_ptr, code_end); @@ -48,6 +71,8 @@ HGraph* HGraphBuilder::BuildGraph(const uint16_t* code_ptr, const uint16_t* code // Add the exit block at the end to give it the highest id. graph_->AddBlock(exit_block_); + exit_block_->AddInstruction(new (arena_) HExit()); + entry_block_->AddInstruction(new (arena_) HGoto()); return graph_; } @@ -109,16 +134,24 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_ if (current_block_ == nullptr) return true; // Dead code switch (instruction.Opcode()) { + case Instruction::CONST_4: { + int32_t register_index = instruction.VRegA(); + HIntConstant* constant = GetConstant(instruction.VRegB_11n()); + UpdateLocal(register_index, constant); + break; + } case Instruction::RETURN_VOID: current_block_->AddInstruction(new (arena_) HReturnVoid()); current_block_->AddSuccessor(exit_block_); current_block_ = nullptr; break; case Instruction::IF_EQ: { - // TODO: Read the dex register. + HInstruction* first = LoadLocal(instruction.VRegA()); + HInstruction* second = LoadLocal(instruction.VRegB()); + current_block_->AddInstruction(new (arena_) HEqual(first, second)); + current_block_->AddInstruction(new (arena_) HIf(current_block_->last_instruction())); HBasicBlock* target = FindBlockStartingAt(instruction.GetTargetOffset() + dex_offset); DCHECK(target != nullptr); - current_block_->AddInstruction(new (arena_) HIf()); current_block_->AddSuccessor(target); target = FindBlockStartingAt(dex_offset + instruction.SizeInCodeUnits()); DCHECK(target != nullptr); @@ -144,4 +177,37 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, int32_ return true; } +HIntConstant* HGraphBuilder::GetConstant0() { + if (constant0_ != nullptr) return constant0_; + HIntConstant* constant = new(arena_) HIntConstant(0); + entry_block_->AddInstruction(constant); + return constant; +} + +HIntConstant* HGraphBuilder::GetConstant(int constant) { + switch (constant) { + case 0: return GetConstant0(); + default: { + HIntConstant* instruction = new (arena_) HIntConstant(constant); + entry_block_->AddInstruction(instruction); + return instruction; + } + } +} + +HLocal* HGraphBuilder::GetLocalAt(int register_index) const { + return locals_.Get(register_index); +} + +void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const { + HLocal* local = GetLocalAt(register_index); + current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction)); +} + +HInstruction* HGraphBuilder::LoadLocal(int register_index) const { + HLocal* local = GetLocalAt(register_index); + current_block_->AddInstruction(new (arena_) HLoadLocal(local)); + return current_block_->last_instruction(); +} + } // namespace art |