Subzero: Implement InstList in terms of llvm::ilist<> .

Use LLVM's intrusive list ADT template to implement instruction lists.  This embeds prev/next pointers into the instruction, and as such, iterators essentially double as instruction pointers.  This means stripping off one level of indirection when dereferencing, and also the range-based for loop can't be used.

The performance difference in translation time seems to be 1-2%.

I tried to also do this for the much less used PhiList and AssignList, but ran into SFINAE problems.

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/709533002
diff --git a/src/IceCfg.cpp b/src/IceCfg.cpp
index 8e73499..b461d68 100644
--- a/src/IceCfg.cpp
+++ b/src/IceCfg.cpp
@@ -318,7 +318,8 @@
   Ostream &Str = Ctx->getStrDump();
   for (CfgNode *Node : Nodes) {
     Inst *FirstInst = NULL;
-    for (Inst *Inst : Node->getInsts()) {
+    for (auto Inst = Node->getInsts().begin(), E = Node->getInsts().end();
+         Inst != E; ++Inst) {
       if (Inst->isDeleted())
         continue;
       if (FirstInst == NULL)
@@ -337,7 +338,8 @@
           // temporary may be live at the end of the previous block,
           // and if it is also assigned in the first instruction of
           // this block, the adjacent live ranges get merged.
-          if (Inst != FirstInst && !Inst->isDestNonKillable() &&
+          if (static_cast<class Inst *>(Inst) != FirstInst &&
+              !Inst->isDestNonKillable() &&
               Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
             Invalid = true;
           if (Invalid) {
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 543f4e9..07246a2 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -59,7 +59,7 @@
   InstNumberT FirstNumber = Func->getNextInstNumber();
   for (InstPhi *I : Phis)
     I->renumber(Func);
-  for (Inst *I : Insts)
+  for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I)
     I->renumber(Func);
   InstCountEstimate = Func->getNextInstNumber() - FirstNumber;
 }
@@ -69,7 +69,7 @@
 // constructed, the computePredecessors() pass finalizes it by
 // creating the InEdges list.
 void CfgNode::computePredecessors() {
-  OutEdges = (*Insts.rbegin())->getTerminatorEdges();
+  OutEdges = Insts.rbegin()->getTerminatorEdges();
   for (CfgNode *Succ : OutEdges)
     Succ->InEdges.push_back(this);
 }
@@ -117,7 +117,7 @@
   // Confirm that InsertionPoint is a terminator instruction.  Calling
   // getTerminatorEdges() on a non-terminator instruction will cause
   // an llvm_unreachable().
-  (void)(*InsertionPoint)->getTerminatorEdges();
+  (void)InsertionPoint->getTerminatorEdges();
   // SafeInsertionPoint is always immediately before the terminator
   // instruction.  If the block ends in a compare and conditional
   // branch, it's better to place the Phi store before the compare so
@@ -167,13 +167,13 @@
   // instruction, and the previous instruction is a compare
   // instruction, then we move the insertion point before the compare
   // instruction so as not to interfere with compare/branch fusing.
-  if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) {
+  if (InstBr *Branch = llvm::dyn_cast<InstBr>(InsertionPoint)) {
     if (!Branch->isUnconditional()) {
       if (InsertionPoint != Insts.begin()) {
         --InsertionPoint;
-        if (llvm::isa<InstIcmp>(*InsertionPoint) ||
-            llvm::isa<InstFcmp>(*InsertionPoint)) {
-          CmpInstDest = (*InsertionPoint)->getDest();
+        if (llvm::isa<InstIcmp>(InsertionPoint) ||
+            llvm::isa<InstFcmp>(InsertionPoint)) {
+          CmpInstDest = InsertionPoint->getDest();
         } else {
           ++InsertionPoint;
         }
@@ -250,8 +250,8 @@
   Found = false;
   for (auto I = Pred->getInsts().rbegin(), E = Pred->getInsts().rend();
        !Found && I != E; ++I) {
-    if (!(*I)->isDeleted()) {
-      Found = (*I)->repointEdge(this, NewNode);
+    if (!I->isDeleted()) {
+      Found = I->repointEdge(this, NewNode);
     }
   }
   assert(Found);
@@ -530,9 +530,9 @@
   // Process regular instructions in reverse order.
   // TODO(stichnot): Use llvm::make_range with LLVM 3.5.
   for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) {
-    if ((*I)->isDeleted())
+    if (I->isDeleted())
       continue;
-    (*I)->livenessLightweight(Func, Live);
+    I->livenessLightweight(Func, Live);
   }
   for (InstPhi *I : Phis) {
     if (I->isDeleted())
@@ -573,9 +573,9 @@
 
   // Process regular instructions in reverse order.
   for (auto I = Insts.rbegin(), E = Insts.rend(); I != E; ++I) {
-    if ((*I)->isDeleted())
+    if (I->isDeleted())
       continue;
-    (*I)->liveness((*I)->getNumber(), Live, Liveness, LiveBegin, LiveEnd);
+    I->liveness(I->getNumber(), Live, Liveness, LiveBegin, LiveEnd);
   }
   // Process phis in forward order so that we can override the
   // instruction number to be that of the earliest phi instruction in
@@ -654,7 +654,7 @@
     LastInstNum = I->getNumber();
   }
   // Process instructions
-  for (Inst *I : Insts) {
+  for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
     I->deleteIfDead();
     if (I->isDeleted())
       continue;
@@ -753,7 +753,7 @@
   if (InEdges.empty())
     return;
   Inst *Branch = NULL;
-  for (Inst *I : Insts) {
+  for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
     if (I->isDeleted())
       continue;
     if (I->isUnconditionalBranch())
@@ -776,7 +776,8 @@
           OutEdges.front()->InEdges.push_back(Pred);
         }
       }
-      for (Inst *I : Pred->getInsts()) {
+      for (auto I = Pred->getInsts().begin(), E = Pred->getInsts().end();
+           I != E; ++I) {
         if (!I->isDeleted())
           I->repointEdge(this, OutEdges.front());
       }
@@ -795,7 +796,7 @@
   // first opportunity, unless there is some target lowering where we
   // have the possibility of multiple such optimizations per block
   // (currently not the case for x86 lowering).
-  for (Inst *I : Insts) {
+  for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
     if (!I->isDeleted()) {
       Target->doBranchOpt(I, NextNode);
     }
@@ -901,7 +902,7 @@
     Inst *Instr = Phi;
     Instr->emit(Func);
   }
-  for (Inst *I : Insts) {
+  for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
     if (I->isDeleted())
       continue;
     if (I->isRedundantAssign()) {
@@ -931,7 +932,7 @@
     Inst *Instr = Phi;
     Instr->emitIAS(Func);
   }
-  for (Inst *I : Insts) {
+  for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I) {
     if (I->isDeleted())
       continue;
     if (I->isRedundantAssign())
@@ -982,7 +983,7 @@
   if (Func->getContext()->isVerbose(IceV_Instructions)) {
     for (InstPhi *I : Phis)
       I->dumpDecorated(Func);
-    for (Inst *I : Insts)
+    for (auto I = Insts.begin(), E = Insts.end(); I != E; ++I)
       I->dumpDecorated(Func);
   }
   // Dump the live-out variables.
diff --git a/src/IceCfgNode.h b/src/IceCfgNode.h
index 9cde8c1..279b07f 100644
--- a/src/IceCfgNode.h
+++ b/src/IceCfgNode.h
@@ -17,6 +17,7 @@
 #define SUBZERO_SRC_ICECFGNODE_H
 
 #include "IceDefs.h"
+#include "IceInst.h" // InstList traits
 
 namespace Ice {
 
diff --git a/src/IceDefs.h b/src/IceDefs.h
index 2f0547e..9812e3e 100644
--- a/src/IceDefs.h
+++ b/src/IceDefs.h
@@ -28,6 +28,8 @@
 #include <vector>
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Casting.h"
@@ -56,7 +58,7 @@
 // TODO: Switch over to LLVM's ADT container classes.
 // http://llvm.org/docs/ProgrammersManual.html#picking-the-right-data-structure-for-a-task
 typedef std::string IceString;
-typedef std::list<Inst *> InstList;
+typedef llvm::ilist<Inst> InstList;
 typedef std::list<InstAssign *> AssignList;
 typedef std::list<InstPhi *> PhiList;
 typedef std::vector<Variable *> VarList;
diff --git a/src/IceInst.h b/src/IceInst.h
index 7c96e3f..71da0b3 100644
--- a/src/IceInst.h
+++ b/src/IceInst.h
@@ -34,7 +34,7 @@
 // InstHighLevel and InstTarget.  High-level ICE instructions inherit
 // from InstHighLevel, and low-level (target-specific) ICE
 // instructions inherit from InstTarget.
-class Inst {
+class Inst : public llvm::ilist_node<Inst> {
   Inst(const Inst &) = delete;
   Inst &operator=(const Inst &) = delete;
 
@@ -838,4 +838,22 @@
 
 } // end of namespace Ice
 
+// Override the default ilist traits so that Inst's private ctor and
+// deleted dtor aren't invoked.
+template <>
+struct llvm::ilist_traits<Ice::Inst> : public llvm::ilist_default_traits<
+                                           Ice::Inst> {
+  Ice::Inst *createSentinel() const {
+    return static_cast<Ice::Inst *>(&Sentinel);
+  }
+  static void destroySentinel(Ice::Inst *) {}
+  Ice::Inst *provideInitialHead() const { return createSentinel(); }
+  Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); }
+  static void noteHead(Ice::Inst *, Ice::Inst *) {}
+  void deleteNode(Ice::Inst *) {}
+
+private:
+  mutable ilist_half_node<Ice::Inst> Sentinel;
+};
+
 #endif // SUBZERO_SRC_ICEINST_H
diff --git a/src/IceOperand.cpp b/src/IceOperand.cpp
index 8cf181a..7870d180 100644
--- a/src/IceOperand.cpp
+++ b/src/IceOperand.cpp
@@ -347,7 +347,8 @@
     }
   }
 
-  for (Inst *I : Node->getInsts()) {
+  for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E;
+       ++I) {
     if (I->isDeleted())
       continue;
     // Note: The implicit definitions (and uses) from InstFakeKill are
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp
index 350605b..5661ad9 100644
--- a/src/IceTargetLowering.cpp
+++ b/src/IceTargetLowering.cpp
@@ -62,7 +62,7 @@
 }
 
 void LoweringContext::skipDeleted(InstList::iterator &I) const {
-  while (I != End && (*I)->isDeleted())
+  while (I != End && I->isDeleted())
     ++I;
 }
 
@@ -116,7 +116,7 @@
 bool TargetLowering::shouldDoNopInsertion() const { return DoNopInsertion; }
 
 void TargetLowering::doNopInsertion() {
-  Inst *I = *Context.getCur();
+  Inst *I = Context.getCur();
   bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
                     llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
                     I->isDeleted();
@@ -141,7 +141,7 @@
 // instructions it consumes.
 void TargetLowering::lower() {
   assert(!Context.atEnd());
-  Inst *Inst = *Context.getCur();
+  Inst *Inst = Context.getCur();
   // Mark the current instruction as deleted before lowering,
   // otherwise the Dest variable will likely get marked as non-SSA.
   // See Variable::setDefinition().
diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h
index 4bfe4b4..a8b0fcc 100644
--- a/src/IceTargetLowering.h
+++ b/src/IceTargetLowering.h
@@ -45,13 +45,13 @@
   Inst *getNextInst() const {
     if (Next == End)
       return NULL;
-    return *Next;
+    return Next;
   }
   Inst *getNextInst(InstList::iterator &Iter) const {
     advanceForward(Iter);
     if (Iter == End)
       return NULL;
-    return *Iter;
+    return Iter;
   }
   CfgNode *getNode() const { return Node; }
   bool atEnd() const { return Cur == End; }
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
index c975d88..ad80792 100644
--- a/src/IceTargetLoweringX8632.cpp
+++ b/src/IceTargetLoweringX8632.cpp
@@ -3826,7 +3826,7 @@
 }
 
 void TargetX8632::doAddressOptLoad() {
-  Inst *Inst = *Context.getCur();
+  Inst *Inst = Context.getCur();
   Variable *Dest = Inst->getDest();
   Operand *Addr = Inst->getSrc(0);
   Variable *Index = NULL;
@@ -4004,7 +4004,7 @@
 }
 
 void TargetX8632::doAddressOptStore() {
-  InstStore *Inst = llvm::cast<InstStore>(*Context.getCur());
+  InstStore *Inst = llvm::cast<InstStore>(Context.getCur());
   Operand *Data = Inst->getData();
   Operand *Addr = Inst->getAddr();
   Variable *Index = NULL;
@@ -4502,7 +4502,7 @@
   if (Ctx->getOptLevel() != Opt_m1) {
     // Find two-address non-SSA instructions where Dest==Src0, and set
     // the DestNonKillable flag to keep liveness analysis consistent.
-    for (Inst *Inst : Context) {
+    for (auto Inst = Context.begin(), E = Context.end(); Inst != E; ++Inst) {
       if (Inst->isDeleted())
         continue;
       if (Variable *Dest = Inst->getDest()) {
@@ -4529,7 +4529,7 @@
   // The first pass also keeps track of which instruction is the last
   // use for each infinite-weight variable.  After the last use, the
   // variable is released to the free list.
-  for (Inst *Inst : Context) {
+  for (auto Inst = Context.begin(), E = Context.end(); Inst != E; ++Inst) {
     if (Inst->isDeleted())
       continue;
     // Don't consider a FakeKill instruction, because (currently) it
@@ -4560,7 +4560,7 @@
   // The second pass colors infinite-weight variables.
   llvm::SmallBitVector AvailableRegisters = WhiteList;
   llvm::SmallBitVector FreedRegisters(WhiteList.size());
-  for (Inst *Inst : Context) {
+  for (auto Inst = Context.begin(), E = Context.end(); Inst != E; ++Inst) {
     FreedRegisters.reset();
     if (Inst->isDeleted())
       continue;