Subzero: Implementation of "advanced Phi lowering".

Delays Phi lowering until after register allocation.  This lets the Phi assignment order take register allocation into account and avoid creating false dependencies.

All edges that lead to Phi instructions are split, and the new node gets mov instructions in the correct topological order, using available physical registers as needed.

This lowering style is controllable under -O2 using -phi-edge-split (enabled by default).

The result is faster translation time (due to fewer temporaries leading to faster liveness analysis and register allocation) as well as better code quality (due to better register allocation and fewer phi-based assignments).

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/680733002
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index e46399d..7aa2483 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -64,6 +64,7 @@
   Inst *getLastInserted() const;
   void advanceCur() { Cur = Next; }
   void advanceNext() { advanceForward(Next); }
+  void rewind();
   void setInsertPoint(const InstList::iterator &Position) { Next = Position; }
 
 private:
@@ -134,8 +135,18 @@
   void doAddressOpt();
   // Randomly insert NOPs.
   void doNopInsertion();
-  // Lowers a single instruction.
+  // Lowers a single non-Phi instruction.
   void lower();
+  // Does preliminary lowering of the set of Phi instructions in the
+  // current node.  The main intention is to do what's needed to keep
+  // the unlowered Phi instructions consistent with the lowered
+  // non-Phi instructions, e.g. to lower 64-bit operands on a 32-bit
+  // target.
+  virtual void prelowerPhis() {}
+  // Lowers a list of "parallel" assignment instructions representing
+  // a topological sort of the Phi instructions.
+  virtual void lowerPhiAssignments(CfgNode *Node,
+                                   const AssignList &Assignments) = 0;
   // Tries to do branch optimization on a single instruction.  Returns
   // true if some optimization was done.
   virtual bool doBranchOpt(Inst * /*I*/, const CfgNode * /*NextNode*/) {