[PATCH] Consolidate duplicated ghostly sentinel code

Tristan Schmelcher tristan_schmelcher at alumni.uwaterloo.ca
Sun Jul 7 15:43:37 PDT 2013


On second thought, a better comment for ilist_ghostly_sentinel_traits
would be "As a result, it is invalid to call getPrevNode on the list
front or getNextNode on the list back." Here's an updated patch with
that minor change.
-------------- next part --------------
diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h
index 7a10f85..4514b2d 100644
--- a/include/llvm/ADT/SparseBitVector.h
+++ b/include/llvm/ADT/SparseBitVector.h
@@ -264,18 +264,9 @@ public:
 
 template <unsigned ElementSize>
 struct ilist_traits<SparseBitVectorElement<ElementSize> >
-  : public ilist_default_traits<SparseBitVectorElement<ElementSize> > {
-  typedef SparseBitVectorElement<ElementSize> Element;
-
-  Element *createSentinel() const { return static_cast<Element *>(&Sentinel); }
-  static void destroySentinel(Element *) {}
-
-  Element *provideInitialHead() const { return createSentinel(); }
-  Element *ensureHead(Element *) const { return createSentinel(); }
-  static void noteHead(Element *, Element *) {}
-
-private:
-  mutable ilist_half_node<Element> Sentinel;
+  : public ilist_nextprev_traits<SparseBitVectorElement<ElementSize> >,
+    public ilist_ghostly_sentinel_traits<SparseBitVectorElement<ElementSize> >,
+    public ilist_node_traits<SparseBitVectorElement<ElementSize> > {
 };
 
 template <unsigned ElementSize = 128>
diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h
index 71dab2e..d84d888 100644
--- a/include/llvm/ADT/ilist.h
+++ b/include/llvm/ADT/ilist.h
@@ -104,6 +104,58 @@ struct ilist_sentinel_traits {
   }
 };
 
+template<typename NodeTy>
+class ilist_half_node;
+
+/// ilist_ghostly_sentinel_traits - Alternate fragment for template traits that
+/// provides a "ghostly sentinel" implementation. The sentinel consists of a
+/// single pointer in the ilist object itself with no separate dynamic
+/// allocation.
+///
+/// Using this sentinel implementation results in some differences in the list
+/// structure:
+/// - The prev pointer of the list head is null rather than a pointer to the
+///   sentinel.
+/// - Accessing the next pointer of the sentinel is invalid.
+/// As a result, it is invalid to use getPrevNode/getNextNode on ilist_node
+/// objects from such a list.
+template<typename NodeTy, typename SentinelTy = ilist_half_node<NodeTy> >
+struct ilist_ghostly_sentinel_traits {
+private:
+  mutable SentinelTy Sentinel;
+
+public:
+  /// createSentinel - return the ghostly sentinel
+  ///
+  /// The sentinel is relative to this instance, so we use a non-static method.
+  NodeTy *createSentinel() const {
+    // Since i(p)lists always publicly derive from their corresponding traits,
+    // placing a data member in this class will augment the i(p)list. But since
+    // the NodeTy is expected to be derived from SentinelTy, there is a legal
+    // viable downcast from it to NodeTy. We use this trick to superimpose an
+    // i(p)list with a "ghostly" NodeTy, which becomes the sentinel.
+    // Dereferencing the sentinel is forbidden (save as SentinelTy), so no one
+    // will ever notice the superposition.
+    return static_cast<NodeTy *>(&Sentinel);
+  }
+
+  /// destroySentinel - no-op because the sentinel is not a separate object
+  static void destroySentinel(NodeTy *) {}
+
+  /// provideInitialHead - initialize head to the ghostly sentinel
+  NodeTy *provideInitialHead() const { return createSentinel(); }
+
+  /// ensureHead - returns the ghostly sentinel
+  NodeTy *ensureHead(NodeTy *) const { return createSentinel(); }
+
+  /// noteHead - no-op
+  ///
+  /// We don't need to store the sentinel pointer anywhere because the sentinel
+  /// is already a field. We leave the prev pointer of the head null all the
+  /// time.
+  static void noteHead(NodeTy *, NodeTy *) {}
+};
+
 /// ilist_node_traits - A fragment for template traits for intrusive list
 /// that provides default node related operations.
 ///
diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h
index 0361244..c2f73d2 100644
--- a/include/llvm/ADT/ilist_node.h
+++ b/include/llvm/ADT/ilist_node.h
@@ -17,14 +17,14 @@
 
 namespace llvm {
 
-template<typename NodeTy>
-struct ilist_traits;
+template<typename NodeTy, typename SentinelTy>
+struct ilist_ghostly_sentinel_traits;
 
 /// ilist_half_node - Base class that provides prev services for sentinels.
 ///
 template<typename NodeTy>
 class ilist_half_node {
-  friend struct ilist_traits<NodeTy>;
+  friend struct ilist_ghostly_sentinel_traits<NodeTy, ilist_half_node<NodeTy> >;
   NodeTy *Prev;
 protected:
   NodeTy *getPrev() { return Prev; }
@@ -36,11 +36,15 @@ protected:
 template<typename NodeTy>
 struct ilist_nextprev_traits;
 
+template<typename NodeTy>
+struct ilist_traits;
+
 /// ilist_node - Base class that provides next/prev services for nodes
 /// that use ilist_nextprev_traits or ilist_default_traits.
 ///
 template<typename NodeTy>
 class ilist_node : private ilist_half_node<NodeTy> {
+  friend struct ilist_ghostly_sentinel_traits<NodeTy, ilist_half_node<NodeTy> >;
   friend struct ilist_nextprev_traits<NodeTy>;
   friend struct ilist_traits<NodeTy>;
   NodeTy *Next;
diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h
index c982801..380dc6a 100644
--- a/include/llvm/Analysis/IVUsers.h
+++ b/include/llvm/Analysis/IVUsers.h
@@ -90,30 +90,9 @@ private:
 };
 
 template<> struct ilist_traits<IVStrideUse>
-  : public ilist_default_traits<IVStrideUse> {
-  // createSentinel is used to get hold of a node that marks the end of
-  // the list...
-  // The sentinel is relative to this instance, so we use a non-static
-  // method.
-  IVStrideUse *createSentinel() const {
-    // since i(p)lists always publicly derive from the corresponding
-    // traits, placing a data member in this class will augment i(p)list.
-    // But since the NodeTy is expected to publicly derive from
-    // ilist_node<NodeTy>, there is a legal viable downcast from it
-    // to NodeTy. We use this trick to superpose i(p)list with a "ghostly"
-    // NodeTy, which becomes the sentinel. Dereferencing the sentinel is
-    // forbidden (save the ilist_node<NodeTy>) so no one will ever notice
-    // the superposition.
-    return static_cast<IVStrideUse*>(&Sentinel);
-  }
-  static void destroySentinel(IVStrideUse*) {}
-
-  IVStrideUse *provideInitialHead() const { return createSentinel(); }
-  IVStrideUse *ensureHead(IVStrideUse*) const { return createSentinel(); }
-  static void noteHead(IVStrideUse*, IVStrideUse*) {}
-
-private:
-  mutable ilist_node<IVStrideUse> Sentinel;
+  : public ilist_nextprev_traits<IVStrideUse>,
+    public ilist_ghostly_sentinel_traits<IVStrideUse>,
+    public ilist_node_traits<IVStrideUse> {
 };
 
 class IVUsers : public LoopPass {
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index d6f5883..52423b6 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -31,24 +31,16 @@ class raw_ostream;
 class MachineBranchProbabilityInfo;
 
 template <>
-struct ilist_traits<MachineInstr> : public ilist_default_traits<MachineInstr> {
+struct ilist_traits<MachineInstr>
+  : public ilist_nextprev_traits<MachineInstr>,
+    public ilist_ghostly_sentinel_traits<MachineInstr>,
+    public ilist_node_traits<MachineInstr> {
 private:
-  mutable ilist_half_node<MachineInstr> Sentinel;
-
   // this is only set by the MachineBasicBlock owning the LiveList
   friend class MachineBasicBlock;
   MachineBasicBlock* Parent;
 
 public:
-  MachineInstr *createSentinel() const {
-    return static_cast<MachineInstr*>(&Sentinel);
-  }
-  void destroySentinel(MachineInstr *) const {}
-
-  MachineInstr *provideInitialHead() const { return createSentinel(); }
-  MachineInstr *ensureHead(MachineInstr*) const { return createSentinel(); }
-  static void noteHead(MachineInstr*, MachineInstr*) {}
-
   void addNodeToList(MachineInstr* N);
   void removeNodeFromList(MachineInstr* N);
   void transferNodesFromList(ilist_traits &SrcTraits,
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index c886e25..05c0970 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -43,19 +43,9 @@ struct MachinePointerInfo;
 
 template <>
 struct ilist_traits<MachineBasicBlock>
-    : public ilist_default_traits<MachineBasicBlock> {
-  mutable ilist_half_node<MachineBasicBlock> Sentinel;
-public:
-  MachineBasicBlock *createSentinel() const {
-    return static_cast<MachineBasicBlock*>(&Sentinel);
-  }
-  void destroySentinel(MachineBasicBlock *) const {}
-
-  MachineBasicBlock *provideInitialHead() const { return createSentinel(); }
-  MachineBasicBlock *ensureHead(MachineBasicBlock*) const {
-    return createSentinel();
-  }
-  static void noteHead(MachineBasicBlock*, MachineBasicBlock*) {}
+    : public ilist_nextprev_traits<MachineBasicBlock>,
+      public ilist_ghostly_sentinel_traits<MachineBasicBlock>,
+      public ilist_node_traits<MachineBasicBlock> {
 
   void addNodeToList(MachineBasicBlock* MBB);
   void removeNodeFromList(MachineBasicBlock* MBB);
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index 79e533e..2350fc0 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -38,19 +38,10 @@ class TargetLowering;
 class TargetSelectionDAGInfo;
 class TargetTransformInfo;
 
-template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
-private:
-  mutable ilist_half_node<SDNode> Sentinel;
-public:
-  SDNode *createSentinel() const {
-    return static_cast<SDNode*>(&Sentinel);
-  }
-  static void destroySentinel(SDNode *) {}
-
-  SDNode *provideInitialHead() const { return createSentinel(); }
-  SDNode *ensureHead(SDNode*) const { return createSentinel(); }
-  static void noteHead(SDNode*, SDNode*) {}
-
+template<> struct ilist_traits<SDNode>
+  : public ilist_nextprev_traits<SDNode>,
+    public ilist_ghostly_sentinel_traits<SDNode>,
+    public ilist_node_traits<SDNode> {
   static void deleteNode(SDNode *) {
     llvm_unreachable("ilist_traits<SDNode> shouldn't see a deleteNode call!");
   }
diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h
index 676cdaf..27eeb35 100644
--- a/include/llvm/CodeGen/SlotIndexes.h
+++ b/include/llvm/CodeGen/SlotIndexes.h
@@ -70,18 +70,10 @@ namespace llvm {
   };
 
   template <>
-  struct ilist_traits<IndexListEntry> : public ilist_default_traits<IndexListEntry> {
-  private:
-    mutable ilist_half_node<IndexListEntry> Sentinel;
-  public:
-    IndexListEntry *createSentinel() const {
-      return static_cast<IndexListEntry*>(&Sentinel);
-    }
-    void destroySentinel(IndexListEntry *) const {}
-
-    IndexListEntry *provideInitialHead() const { return createSentinel(); }
-    IndexListEntry *ensureHead(IndexListEntry*) const { return createSentinel(); }
-    static void noteHead(IndexListEntry*, IndexListEntry*) {}
+  struct ilist_traits<IndexListEntry>
+    : public ilist_nextprev_traits<IndexListEntry>,
+      public ilist_ghostly_sentinel_traits<IndexListEntry>,
+      public ilist_node_traits<IndexListEntry> {
     void deleteNode(IndexListEntry *N) {}
 
   private:
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index 3bdc95d..808934d 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -30,28 +30,6 @@ class BlockAddress;
 
 template<> struct ilist_traits<Instruction>
   : public SymbolTableListTraits<Instruction, BasicBlock> {
-
-  /// \brief Return a node that marks the end of a list.
-  ///
-  /// The sentinel is relative to this instance, so we use a non-static
-  /// method.
-  Instruction *createSentinel() const {
-    // Since i(p)lists always publicly derive from their corresponding traits,
-    // placing a data member in this class will augment the i(p)list.  But since
-    // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>,
-    // there is a legal viable downcast from it to NodeTy. We use this trick to
-    // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the
-    // sentinel. Dereferencing the sentinel is forbidden (save the
-    // ilist_node<NodeTy>), so no one will ever notice the superposition.
-    return static_cast<Instruction*>(&Sentinel);
-  }
-  static void destroySentinel(Instruction*) {}
-
-  Instruction *provideInitialHead() const { return createSentinel(); }
-  Instruction *ensureHead(Instruction*) const { return createSentinel(); }
-  static void noteHead(Instruction*, Instruction*) {}
-private:
-  mutable ilist_half_node<Instruction> Sentinel;
 };
 
 /// \brief LLVM Basic Block Representation
diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h
index 455469d..e6cea92 100644
--- a/include/llvm/IR/Function.h
+++ b/include/llvm/IR/Function.h
@@ -34,37 +34,13 @@ class LLVMContext;
 template<> struct ilist_traits<BasicBlock>
   : public SymbolTableListTraits<BasicBlock, Function> {
 
-  // createSentinel is used to get hold of the node that marks the end of the
-  // list... (same trick used here as in ilist_traits<Instruction>)
-  BasicBlock *createSentinel() const {
-    return static_cast<BasicBlock*>(&Sentinel);
-  }
-  static void destroySentinel(BasicBlock*) {}
-
-  BasicBlock *provideInitialHead() const { return createSentinel(); }
-  BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); }
-  static void noteHead(BasicBlock*, BasicBlock*) {}
-
   static ValueSymbolTable *getSymTab(Function *ItemParent);
-private:
-  mutable ilist_half_node<BasicBlock> Sentinel;
 };
 
 template<> struct ilist_traits<Argument>
   : public SymbolTableListTraits<Argument, Function> {
 
-  Argument *createSentinel() const {
-    return static_cast<Argument*>(&Sentinel);
-  }
-  static void destroySentinel(Argument*) {}
-
-  Argument *provideInitialHead() const { return createSentinel(); }
-  Argument *ensureHead(Argument*) const { return createSentinel(); }
-  static void noteHead(Argument*, Argument*) {}
-
   static ValueSymbolTable *getSymTab(Function *ItemParent);
-private:
-  mutable ilist_half_node<Argument> Sentinel;
 };
 
 class Function : public GlobalValue,
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index d414405..a40b099 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -34,68 +34,22 @@ template<typename KeyT, typename ValueT, typename KeyInfoT> class DenseMap;
 
 template<> struct ilist_traits<Function>
   : public SymbolTableListTraits<Function, Module> {
-
-  // createSentinel is used to get hold of the node that marks the end of the
-  // list... (same trick used here as in ilist_traits<Instruction>)
-  Function *createSentinel() const {
-    return static_cast<Function*>(&Sentinel);
-  }
-  static void destroySentinel(Function*) {}
-
-  Function *provideInitialHead() const { return createSentinel(); }
-  Function *ensureHead(Function*) const { return createSentinel(); }
-  static void noteHead(Function*, Function*) {}
-
-private:
-  mutable ilist_node<Function> Sentinel;
 };
 
 template<> struct ilist_traits<GlobalVariable>
   : public SymbolTableListTraits<GlobalVariable, Module> {
-  // createSentinel is used to create a node that marks the end of the list.
-  GlobalVariable *createSentinel() const {
-    return static_cast<GlobalVariable*>(&Sentinel);
-  }
-  static void destroySentinel(GlobalVariable*) {}
-
-  GlobalVariable *provideInitialHead() const { return createSentinel(); }
-  GlobalVariable *ensureHead(GlobalVariable*) const { return createSentinel(); }
-  static void noteHead(GlobalVariable*, GlobalVariable*) {}
-private:
-  mutable ilist_node<GlobalVariable> Sentinel;
 };
 
 template<> struct ilist_traits<GlobalAlias>
   : public SymbolTableListTraits<GlobalAlias, Module> {
-  // createSentinel is used to create a node that marks the end of the list.
-  GlobalAlias *createSentinel() const {
-    return static_cast<GlobalAlias*>(&Sentinel);
-  }
-  static void destroySentinel(GlobalAlias*) {}
-
-  GlobalAlias *provideInitialHead() const { return createSentinel(); }
-  GlobalAlias *ensureHead(GlobalAlias*) const { return createSentinel(); }
-  static void noteHead(GlobalAlias*, GlobalAlias*) {}
-private:
-  mutable ilist_node<GlobalAlias> Sentinel;
 };
 
 template<> struct ilist_traits<NamedMDNode>
-  : public ilist_default_traits<NamedMDNode> {
-  // createSentinel is used to get hold of a node that marks the end of
-  // the list...
-  NamedMDNode *createSentinel() const {
-    return static_cast<NamedMDNode*>(&Sentinel);
-  }
-  static void destroySentinel(NamedMDNode*) {}
-
-  NamedMDNode *provideInitialHead() const { return createSentinel(); }
-  NamedMDNode *ensureHead(NamedMDNode*) const { return createSentinel(); }
-  static void noteHead(NamedMDNode*, NamedMDNode*) {}
+  : public ilist_nextprev_traits<NamedMDNode>,
+    public ilist_ghostly_sentinel_traits<NamedMDNode>,
+    public ilist_node_traits<NamedMDNode> {
   void addNodeToList(NamedMDNode *) {}
   void removeNodeFromList(NamedMDNode *) {}
-private:
-  mutable ilist_node<NamedMDNode> Sentinel;
 };
 
 /// A Module instance is used to store all the information related to an
diff --git a/include/llvm/IR/SymbolTableListTraits.h b/include/llvm/IR/SymbolTableListTraits.h
index 561ce01..c791e3d 100644
--- a/include/llvm/IR/SymbolTableListTraits.h
+++ b/include/llvm/IR/SymbolTableListTraits.h
@@ -38,7 +38,10 @@ template<typename Ty> struct ilist_traits;
 // ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
 //
 template<typename ValueSubClass, typename ItemParentClass>
-class SymbolTableListTraits : public ilist_default_traits<ValueSubClass> {
+class SymbolTableListTraits
+  : public ilist_nextprev_traits<ValueSubClass>,
+    public ilist_ghostly_sentinel_traits<ValueSubClass>,
+    public ilist_node_traits<ValueSubClass> {
   typedef ilist_traits<ValueSubClass> TraitsClass;
 public:
   SymbolTableListTraits() {}
-- 
1.7.10.4



More information about the llvm-commits mailing list