[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