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