Give sentinel traits the right to determine the policy where the sentinel is kept.
authorGabor Greif <ggreif@gmail.com>
Wed, 4 Mar 2009 20:36:44 +0000 (20:36 +0000)
committerGabor Greif <ggreif@gmail.com>
Wed, 4 Mar 2009 20:36:44 +0000 (20:36 +0000)
This should result in less indirect memory accesses, less dead writes and tighter code.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@66061 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/ilist.h
include/llvm/BasicBlock.h
include/llvm/CodeGen/MachineBasicBlock.h
include/llvm/CodeGen/MachineFunction.h
include/llvm/CodeGen/SelectionDAG.h
include/llvm/Function.h
include/llvm/Support/Recycler.h

index ee7d199230cdcd737da9332a866484435d90f9b7..51442e35630acd63fca7ab07d022c8973b4805e4 100644 (file)
@@ -60,13 +60,45 @@ struct ilist_nextprev_traits {
   static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); }
 };
 
+template<typename NodeTy>
+struct ilist_traits;
+
 /// ilist_sentinel_traits - A fragment for template traits for intrusive list
 /// that provides default sentinel implementations for common operations.
 ///
+/// ilist_sentinel_traits implements a lazy dynamic sentinel allocation
+/// strategy. The sentinel is stored in the prev field of ilist's Head.
+///
 template<typename NodeTy>
 struct ilist_sentinel_traits {
+  /// createSentinel - create the dynamic sentinel
   static NodeTy *createSentinel() { return new NodeTy(); }
+
+  /// destroySentinel - deallocate the dynamic sentinel
   static void destroySentinel(NodeTy *N) { delete N; }
+
+  /// provideInitialHead - when constructing an ilist, provide a starting
+  /// value for its Head
+  /// @return null node to indicate that it needs to be allocated later
+  static NodeTy *provideInitialHead() { return 0; }
+
+  /// ensureHead - make sure that Head is either already
+  /// initialized or assigned a fresh sentinel
+  /// @return the sentinel
+  static NodeTy *ensureHead(NodeTy *&Head) {
+    if (!Head) {
+      Head = ilist_traits<NodeTy>::createSentinel();
+      ilist_traits<NodeTy>::noteHead(Head, Head);
+      ilist_traits<NodeTy>::setNext(Head, 0);
+      return Head;
+    }
+    return ilist_traits<NodeTy>::getPrev(Head);
+  }
+
+  /// noteHead - stash the sentinel into its default location
+  static void noteHead(NodeTy *NewHead, NodeTy *Sentinel) {
+    ilist_traits<NodeTy>::setPrev(NewHead, Sentinel);
+  }
 };
 
 /// ilist_node_traits - A fragment for template traits for intrusive list
@@ -284,17 +316,14 @@ class iplist : public Traits {
   // circularly linked list where we snip the 'next' link from the sentinel node
   // back to the first node in the list (to preserve assertions about going off
   // the end of the list).
-  NodeTy *getTail() { return this->getPrev(Head); }
-  const NodeTy *getTail() const { return this->getPrev(Head); }
-  void setTail(NodeTy *N) const { this->setPrev(Head, N); }
+  NodeTy *getTail() { return this->ensureHead(Head); }
+  const NodeTy *getTail() const { return this->ensureHead(Head); }
+  void setTail(NodeTy *N) const { this->noteHead(Head, N); }
 
   /// CreateLazySentinel - This method verifies whether the sentinel for the
   /// list has been created and lazily makes it if not.
   void CreateLazySentinel() const {
-    if (Head != 0) return;
-    Head = Traits::createSentinel();
-    this->setNext(Head, 0);
-    setTail(Head);
+    this->Traits::ensureHead(Head);
   }
 
   static bool op_less(NodeTy &L, NodeTy &R) { return L < R; }
@@ -318,7 +347,7 @@ public:
   typedef std::reverse_iterator<const_iterator>  const_reverse_iterator;
   typedef std::reverse_iterator<iterator>  reverse_iterator;
 
-  iplist() : Head(0) {}
+  iplist() : Head(this->Traits::provideInitialHead()) {}
   ~iplist() {
     if (!Head) return;
     clear();
index 521815f53c298191024f47be13d4c8e331b3db05..561dbb27910acd278d38822d8d5c11594a672834 100644 (file)
@@ -41,6 +41,10 @@ template<> struct ilist_traits<Instruction>
     return static_cast<Instruction*>(&Sentinel);
   }
   static void destroySentinel(Instruction*) {}
+
+  Instruction *provideInitialHead() const { return createSentinel(); }
+  Instruction *ensureHead(Instruction*) const { return createSentinel(); }
+
   static iplist<Instruction> &getList(BasicBlock *BB);
   static ValueSymbolTable *getSymTab(BasicBlock *ItemParent);
   static int getListOffset();
index 5a9f3991f2c13f0ccba582ae7b87fe4edcbfe804..de0a4c40f1d3f79a144277a0781fcdc3e55227ce 100644 (file)
@@ -38,6 +38,9 @@ public:
   }
   void destroySentinel(MachineInstr *) const {}
 
+  MachineInstr *provideInitialHead() const { return createSentinel(); }
+  MachineInstr *ensureHead(MachineInstr*) const { return createSentinel(); }
+
   void addNodeToList(MachineInstr* N);
   void removeNodeFromList(MachineInstr* N);
   void transferNodesFromList(ilist_traits &SrcTraits,
index 1371f1d0cdf797014b52bba63a301e47ee54ec43..7386b2b1284c29fae887911e6695824048468449 100644 (file)
@@ -44,6 +44,11 @@ public:
   }
   void destroySentinel(MachineBasicBlock *) const {}
 
+  MachineBasicBlock *provideInitialHead() const { return createSentinel(); }
+  MachineBasicBlock *ensureHead(MachineBasicBlock*) const {
+    return createSentinel();
+  }
+
   void addNodeToList(MachineBasicBlock* MBB);
   void removeNodeFromList(MachineBasicBlock* MBB);
   void deleteNode(MachineBasicBlock *MBB);
@@ -363,8 +368,12 @@ template <> struct GraphTraits<const MachineFunction*> :
 
   // nodes_iterator/begin/end - Allow iteration over all nodes in the graph
   typedef MachineFunction::const_iterator nodes_iterator;
-  static nodes_iterator nodes_begin(const MachineFunction *F) { return F->begin(); }
-  static nodes_iterator nodes_end  (const MachineFunction *F) { return F->end(); }
+  static nodes_iterator nodes_begin(const MachineFunction *F) {
+    return F->begin();
+  }
+  static nodes_iterator nodes_end  (const MachineFunction *F) {
+    return F->end();
+  }
 };
 
 
index fe89fe0546018ad9845b56abca68b4f524761c98..b895242f57ed3b367e0b6648cc1e5518c7d650b3 100644 (file)
@@ -46,6 +46,9 @@ public:
   }
   static void destroySentinel(SDNode *) {}
 
+  SDNode *provideInitialHead() const { return createSentinel(); }
+  SDNode *ensureHead(SDNode*) const { return createSentinel(); }
+
   static void deleteNode(SDNode *) {
     assert(0 && "ilist_traits<SDNode> shouldn't see a deleteNode call!");
   }
@@ -112,7 +115,8 @@ class SelectionDAG {
   /// setGraphColorHelper - Implementation of setSubgraphColor.
   /// Return whether we had to truncate the search.
   ///
-  bool setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
+  bool setSubgraphColorHelper(SDNode *N, const char *Color,
+                              DenseSet<SDNode *> &visited,
                               int level, bool &printed);
 
 public:
index 37e8f19f6257c0aa13274f7aa2f089bdf0f2f2f1..cb3cc939d00ce931be934d8978a811a13310426a 100644 (file)
@@ -38,6 +38,10 @@ template<> struct ilist_traits<BasicBlock>
     return static_cast<BasicBlock*>(&Sentinel);
   }
   static void destroySentinel(BasicBlock*) {}
+
+  BasicBlock *provideInitialHead() const { return createSentinel(); }
+  BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
+
   static iplist<BasicBlock> &getList(Function *F);
   static ValueSymbolTable *getSymTab(Function *ItemParent);
   static int getListOffset();
@@ -52,6 +56,10 @@ template<> struct ilist_traits<Argument>
     return static_cast<Argument*>(&Sentinel);
   }
   static void destroySentinel(Argument*) {}
+
+  Argument *provideInitialHead() const { return createSentinel(); }
+  Argument *ensureHead(Argument*) const { return createSentinel(); }
+
   static iplist<Argument> &getList(Function *F);
   static ValueSymbolTable *getSymTab(Function *ItemParent);
   static int getListOffset();
index 3f235b6e72f407009739b4344ffd0085d2254334..39c992bc5370cddb82abbb959ed4b3dca6aab114 100644 (file)
@@ -46,6 +46,9 @@ struct ilist_traits<RecyclerStruct> : ilist_default_traits<RecyclerStruct> {
   }
   static void destroySentinel(RecyclerStruct *) {}
 
+  RecyclerStruct *provideInitialHead() const { return createSentinel(); }
+  RecyclerStruct *ensureHead(RecyclerStruct*) const { return createSentinel(); }
+
   static void deleteNode(RecyclerStruct *) {
     assert(0 && "Recycler's ilist_traits shouldn't see a deleteNode call!");
   }