Add register support to the optimizing compiler.
Also make if take an input and build the use list for instructions.
Change-Id: I1938cee7dce5bd4c66b259fa2b431d2c79b3cf82
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 @@
// 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 @@
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 @@
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