Subzero: Minor refactoring/additions in preparation for phi edge splitting.

The only functional change (though not actually visible at this point) is that redundant assignment elimination is moved into a separate pass.

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/672393003
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index ed962d1..04e7acd 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -284,6 +284,19 @@
   return Valid;
 }
 
+// Deletes redundant assignments like "var=var".  This includes
+// architecturally redundant moves like "var1:eax=var2:eax".  As such,
+// this needs to be done very late in the translation to avoid
+// liveness inconsistencies.
+void Cfg::deleteRedundantAssignments() {
+  for (CfgNode *Node : Nodes) {
+    // Ignore Phi instructions.
+    for (Inst *I : Node->getInsts())
+      if (I->isRedundantAssign())
+        I->setDeleted();
+  }
+}
+
 void Cfg::doBranchOpt() {
   TimerMarker T(TimerStack::TT_doBranchOpt, this);
   for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
diff --git a/src/IceCfg.h b/src/IceCfg.h
index 606f785..93aa159 100644
--- a/src/IceCfg.h
+++ b/src/IceCfg.h
@@ -119,6 +119,7 @@
   void livenessLightweight();
   void liveness(LivenessMode Mode);
   bool validateLiveness() const;
+  void deleteRedundantAssignments();
   void doBranchOpt();
 
   // Manage the CurrentNode field, which is used for validating the
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index d715767..a1804d5 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -506,10 +506,6 @@
   for (Inst *I : Insts) {
     if (I->isDeleted())
       continue;
-    // Here we detect redundant assignments like "mov eax, eax" and
-    // suppress them.
-    if (I->isRedundantAssign())
-      continue;
     if (Func->useIntegratedAssembler()) {
       I->emitIAS(Func);
     } else {
diff --git a/src/IceCfgNode.h b/src/IceCfgNode.h
index 97ce69c..031c76c 100644
--- a/src/IceCfgNode.h
+++ b/src/IceCfgNode.h
@@ -52,6 +52,7 @@
 
   // Manage the instruction list.
   InstList &getInsts() { return Insts; }
+  PhiList &getPhis() { return Phis; }
   void appendInst(Inst *Inst);
   void renumberInstructions();
   // Rough and generally conservative estimate of the number of
diff --git a/src/IceClFlags.h b/src/IceClFlags.h
index d610c6a..eebca45 100644
--- a/src/IceClFlags.h
+++ b/src/IceClFlags.h
@@ -27,7 +27,7 @@
         UseIntegratedAssembler(false), UseSandboxing(false), DumpStats(false),
         AllowUninitializedGlobals(false), TimeEachFunction(false),
         DefaultGlobalPrefix(""), DefaultFunctionPrefix(""), TimingFocusOn(""),
-        VerboseFocusOn("") {}
+        VerboseFocusOn(""), TranslateOnly("") {}
   bool DisableInternal;
   bool SubzeroTimingEnabled;
   bool DisableTranslation;
diff --git a/src/IceInst.h b/src/IceInst.h
index bbd817b..0a47e1a 100644
--- a/src/IceInst.h
+++ b/src/IceInst.h
@@ -554,6 +554,7 @@
   }
   void addArgument(Operand *Source, CfgNode *Label);
   Operand *getOperandForTarget(CfgNode *Target) const;
+  CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
   void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
                           Liveness *Liveness);
   Inst *lower(Cfg *Func);
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h
index 81d3fd8..1778437 100644
--- a/src/IceInstX8632.h
+++ b/src/IceInstX8632.h
@@ -342,6 +342,7 @@
   // Create a conditional branch to a node.
   static InstX8632Br *create(Cfg *Func, CfgNode *TargetTrue,
                              CfgNode *TargetFalse, CondX86::BrCond Condition) {
+    assert(Condition != CondX86::Br_None);
     const InstX8632Label *NoLabel = NULL;
     return new (Func->allocate<InstX8632Br>())
         InstX8632Br(Func, TargetTrue, TargetFalse, NoLabel, Condition);
@@ -358,6 +359,7 @@
   // used for switch lowering.
   static InstX8632Br *create(Cfg *Func, CfgNode *Target,
                              CondX86::BrCond Condition) {
+    assert(Condition != CondX86::Br_None);
     const CfgNode *NoUncondTarget = NULL;
     const InstX8632Label *NoLabel = NULL;
     return new (Func->allocate<InstX8632Br>())
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index bcc6290..b18999f 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -54,6 +54,7 @@
 
 void LoweringContext::insert(Inst *Inst) {
   getNode()->getInsts().insert(Next, Inst);
+  LastInserted = Inst;
 }
 
 void LoweringContext::skipDeleted(InstList::iterator &I) const {
@@ -68,17 +69,9 @@
   }
 }
 
-void LoweringContext::advanceBackward(InstList::iterator &I) const {
-  assert(I != Begin);
-  do {
-    --I;
-  } while (I != Begin && (*I)->isDeleted());
-}
-
 Inst *LoweringContext::getLastInserted() const {
-  InstList::iterator Cursor = Next;
-  advanceBackward(Cursor);
-  return *Cursor;
+  assert(LastInserted);
+  return LastInserted;
 }
 
 TargetLowering *TargetLowering::createLowering(TargetArch Target, Cfg *Func) {
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index 6e172a2..e46399d 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -39,7 +39,7 @@
   LoweringContext &operator=(const LoweringContext &) = delete;
 
 public:
-  LoweringContext() : Node(NULL) {}
+  LoweringContext() : Node(NULL), LastInserted(NULL) {}
   ~LoweringContext() {}
   void init(CfgNode *Node);
   Inst *getNextInst() const {
@@ -69,6 +69,7 @@
 private:
   // Node is the argument to Inst::updateVars().
   CfgNode *Node;
+  Inst *LastInserted;
   // Cur points to the current instruction being considered.  It is
   // guaranteed to point to a non-deleted instruction, or to be End.
   InstList::iterator Cur;
@@ -88,7 +89,6 @@
 
   void skipDeleted(InstList::iterator &I) const;
   void advanceForward(InstList::iterator &I) const;
-  void advanceBackward(InstList::iterator &I) const;
 };
 
 class TargetLowering {
@@ -145,8 +145,10 @@
   // Returns a variable pre-colored to the specified physical
   // register.  This is generally used to get very direct access to
   // the register such as in the prolog or epilog or for marking
-  // scratch registers as killed by a call.
-  virtual Variable *getPhysicalRegister(SizeT RegNum) = 0;
+  // scratch registers as killed by a call.  If a Type is not
+  // provided, a target-specific default type is used.
+  virtual Variable *getPhysicalRegister(SizeT RegNum,
+                                        Type Ty = IceType_void) = 0;
   // Returns a printable name for the register.
   virtual IceString getRegName(SizeT RegNum, Type Ty) const = 0;
 
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index 8ea5882..8082c52 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -384,6 +384,8 @@
     return;
   Func->dump("After stack frame mapping");
 
+  Func->deleteRedundantAssignments();
+
   // Branch optimization.  This needs to be done just before code
   // emission.  In particular, no transformations that insert or
   // reorder CfgNodes should be done after branch optimization.  We go
@@ -423,6 +425,8 @@
     return;
   Func->dump("After stack frame mapping");
 
+  Func->deleteRedundantAssignments();
+
   // Nop insertion
   if (shouldDoNopInsertion()) {
     Func->doNopInsertion();
@@ -444,11 +448,13 @@
 #undef X
 };
 
-Variable *TargetX8632::getPhysicalRegister(SizeT RegNum) {
+Variable *TargetX8632::getPhysicalRegister(SizeT RegNum, Type Ty) {
+  if (Ty == IceType_void)
+    Ty = IceType_i32;
   assert(RegNum < PhysicalRegisters.size());
   Variable *Reg = PhysicalRegisters[RegNum];
   if (Reg == NULL) {
-    Reg = Func->makeVariable(IceType_i32);
+    Reg = Func->makeVariable(Ty);
     Reg->setRegNum(RegNum);
     PhysicalRegisters[RegNum] = Reg;
     // Specially mark esp as an "argument" so that it is considered
diff --git a/src/IceTargetLoweringX8632.h b/src/IceTargetLoweringX8632.h
index 20d7150..88b75ac 100644
--- a/src/IceTargetLoweringX8632.h
+++ b/src/IceTargetLoweringX8632.h
@@ -35,7 +35,7 @@
   void translateO2() override;
   bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
 
-  Variable *getPhysicalRegister(SizeT RegNum) override;
+  Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
   IceString getRegName(SizeT RegNum, Type Ty) const override;
   llvm::SmallBitVector getRegisterSet(RegSetMask Include,
                                       RegSetMask Exclude) const override;