Inline methods with multiple blocks.

Change-Id: I3431af60e97fae230e0b6e98bcf0acc0ee9abf8c
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 6f7bc0c..30d869d 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -73,6 +73,15 @@
   bool FoundBefore(const HInstruction* instruction1,
                    const HInstruction* instruction2) const;
 
+  bool IsEmpty() const { return first_instruction_ == nullptr; }
+  void Clear() { first_instruction_ = last_instruction_ = nullptr; }
+
+  // Update the block of all instructions to be `block`.
+  void SetBlockOfInstructions(HBasicBlock* block) const;
+
+  void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
+  void Add(const HInstructionList& instruction_list);
+
  private:
   HInstruction* first_instruction_;
   HInstruction* last_instruction_;
@@ -241,6 +250,10 @@
     return header_;
   }
 
+  void SetHeader(HBasicBlock* block) {
+    header_ = block;
+  }
+
   HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
   void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
   bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
@@ -288,6 +301,8 @@
 
   const ArenaBitVector& GetBlocks() const { return blocks_; }
 
+  void Add(HBasicBlock* block);
+
  private:
   // Internal recursive implementation of `Populate`.
   void PopulateRecursive(HBasicBlock* block);
@@ -351,6 +366,7 @@
   }
 
   HGraph* GetGraph() const { return graph_; }
+  void SetGraph(HGraph* graph) { graph_ = graph; }
 
   int GetBlockId() const { return block_id_; }
   void SetBlockId(int id) { block_id_ = id; }
@@ -358,6 +374,16 @@
   HBasicBlock* GetDominator() const { return dominator_; }
   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
   void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
+  void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
+    for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
+      if (dominated_blocks_.Get(i) == existing) {
+        dominated_blocks_.Put(i, new_block);
+        return;
+      }
+    }
+    LOG(FATAL) << "Unreachable";
+    UNREACHABLE();
+  }
 
   int NumberOfBackEdges() const {
     return loop_information_ == nullptr
@@ -384,10 +410,22 @@
     successors_.Put(successor_index, new_block);
   }
 
+  void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
+    size_t predecessor_index = GetPredecessorIndexOf(existing);
+    DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
+    existing->RemoveSuccessor(this);
+    new_block->successors_.Add(this);
+    predecessors_.Put(predecessor_index, new_block);
+  }
+
   void RemovePredecessor(HBasicBlock* block) {
     predecessors_.Delete(block);
   }
 
+  void RemoveSuccessor(HBasicBlock* block) {
+    successors_.Delete(block);
+  }
+
   void ClearAllPredecessors() {
     predecessors_.Reset();
   }
@@ -422,6 +460,26 @@
     return -1;
   }
 
+  // Split the block into two blocks just after `cursor`. Returns the newly
+  // created block. Note that this method just updates raw block information,
+  // like predecessors, successors, dominators, and instruction list. It does not
+  // update the graph, reverse post order, loop information, nor make sure the
+  // blocks are consistent (for example ending with a control flow instruction).
+  HBasicBlock* SplitAfter(HInstruction* cursor);
+
+  // Merge `other` at the end of `this`. Successors and dominated blocks of
+  // `other` are changed to be successors and dominated blocks of `this`. Note
+  // that this method does not update the graph, reverse post order, loop
+  // information, nor make sure the blocks are consistent (for example ending
+  // with a control flow instruction).
+  void MergeWith(HBasicBlock* other);
+
+  // Replace `this` with `other`. Predecessors, successors, and dominated blocks
+  // of `this` are moved to `other`.
+  // Note that this method does not update the graph, reverse post order, loop
+  // information, nor make sure the blocks are consistent (for example ending
+  void ReplaceWith(HBasicBlock* other);
+
   void AddInstruction(HInstruction* instruction);
   void RemoveInstruction(HInstruction* instruction);
   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
@@ -446,8 +504,9 @@
     return loop_information_;
   }
 
-  // Set the loop_information_ on this block. This method overrides the current
+  // Set the loop_information_ on this block. Overrides the current
   // loop_information if it is an outer loop of the passed loop information.
+  // Note that this method is called while creating the loop information.
   void SetInLoop(HLoopInformation* info) {
     if (IsLoopHeader()) {
       // Nothing to do. This just means `info` is an outer loop.
@@ -465,6 +524,11 @@
     }
   }
 
+  // Raw update of the loop information.
+  void SetLoopInformation(HLoopInformation* info) {
+    loop_information_ = info;
+  }
+
   bool IsInLoop() const { return loop_information_ != nullptr; }
 
   // Returns wheter this block dominates the blocked passed as parameter.
@@ -482,7 +546,7 @@
   void SetIsCatchBlock() { is_catch_block_ = true; }
 
  private:
-  HGraph* const graph_;
+  HGraph* graph_;
   GrowableArray<HBasicBlock*> predecessors_;
   GrowableArray<HBasicBlock*> successors_;
   HInstructionList instructions_;
@@ -2180,6 +2244,8 @@
   DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
 };
 
+static constexpr uint32_t kNoRegNumber = -1;
+
 class HPhi : public HInstruction {
  public:
   HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)