llvm.org GIT mirror llvm / 9c80b35
ADT: Split ilist_node_traits into alloc and callback, NFC Many lists want to override only allocation semantics, or callbacks for iplist. Split these up to prevent code duplication. - Specialize ilist_alloc_traits to change the implementations of deleteNode() and createNode(). - One common desire is to do nothing deleteNode() and disable createNode(). Specialize ilist_alloc_traits to inherit from ilist_noalloc_traits for that behaviour. - Specialize ilist_callback_traits to use the addNodeToList(), removeNodeFromList(), and transferNodesFromList() callbacks. As a drive-by, add some coverage to the callback-related unit tests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280128 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan P. N. Exon Smith 3 years ago
16 changed file(s) with 111 addition(s) and 90 deletion(s). Raw diff Collapse all Expand all
3232
3333 namespace llvm {
3434
35 /// A fragment for template traits for intrusive list that provides default
36 /// node related operations.
37 ///
38 /// TODO: Split up (alloc vs. callback) and delete.
39 template struct ilist_node_traits {
35 /// Use new/delete by default for iplist and ilist.
36 ///
37 /// Specialize this to get different behaviour for allocation-related API. (If
38 /// you really want new/delete, consider just using std::list.)
39 ///
40 /// \see ilist_noalloc_traits
41 template struct ilist_alloc_traits {
4042 static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); }
4143 static void deleteNode(NodeTy *V) { delete V; }
42
44 };
45
46 /// Custom traits to disable node creation and do nothing on deletion.
47 ///
48 /// Specialize ilist_alloc_traits to inherit from this to disable the
49 /// non-intrusive parts of iplist and/or ilist. It has no createNode function,
50 /// and deleteNode does nothing.
51 ///
52 /// \code
53 /// template <>
54 /// struct ilist_alloc_traits : ilist_noalloc_traits {};
55 /// \endcode
56 template struct ilist_noalloc_traits {
57 static void deleteNode(NodeTy *V) {}
58 };
59
60 /// Callbacks do nothing by default in iplist and ilist.
61 ///
62 /// Specialize this for to use callbacks for when nodes change their list
63 /// membership.
64 template struct ilist_callback_traits {
4365 void addNodeToList(NodeTy *) {}
4466 void removeNodeFromList(NodeTy *) {}
4567
4668 /// Callback before transferring nodes to this list.
4769 ///
4870 /// \pre \c this!=&OldList
49 void transferNodesFromList(ilist_node_traits &OldList,
50 ilist_iterator /*first*/,
51 ilist_iterator /*last*/) {
71 template
72 void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/,
73 Iterator /*last*/) {
5274 (void)OldList;
5375 }
5476 };
77
78 /// A fragment for template traits for intrusive list that provides default
79 /// node related operations.
80 ///
81 /// TODO: Remove this layer of indirection. It's not necessary.
82 template
83 struct ilist_node_traits : ilist_alloc_traits,
84 ilist_callback_traits {};
5585
5686 /// Default template traits for intrusive list.
5787 ///
3737 // Forward declaration to avoid circular include problem with TargetRegisterInfo
3838 typedef unsigned LaneBitmask;
3939
40 template <>
41 struct ilist_traits : public ilist_default_traits {
40 template <> struct ilist_traits {
4241 private:
43 // this is only set by the MachineBasicBlock owning the LiveList
44 friend class MachineBasicBlock;
45 MachineBasicBlock* Parent;
42 friend class MachineBasicBlock; // Set by the owning MachineBasicBlock.
43 MachineBasicBlock *Parent;
4644
4745 public:
48 void addNodeToList(MachineInstr* N);
49 void removeNodeFromList(MachineInstr* N);
50 void transferNodesFromList(ilist_traits &SrcTraits,
51 ilist_iterator First,
52 ilist_iterator Last);
53 void deleteNode(MachineInstr *N);
54 private:
55 void createNode(const MachineInstr &);
46 void addNodeToList(MachineInstr *N);
47 void removeNodeFromList(MachineInstr *N);
48 template
49 void transferNodesFromList(ilist_traits &OldList, Iterator First,
50 Iterator Last);
51
52 void deleteNode(MachineInstr *MI);
53 // Leave out createNode...
5654 };
5755
5856 class MachineBasicBlock
696694 BranchProbability getSuccProbability(const_succ_iterator Succ) const;
697695
698696 // Methods used to maintain doubly linked list of blocks...
699 friend struct ilist_traits;
697 friend struct ilist_callback_traits;
700698
701699 // Machine-CFG mutators
702700
4747 struct MachinePointerInfo;
4848 struct WinEHFuncInfo;
4949
50 template <>
51 struct ilist_traits
52 : public ilist_default_traits {
50 template <> struct ilist_alloc_traits {
51 void deleteNode(MachineBasicBlock *MBB);
52 // Disallow createNode...
53 };
54
55 template <> struct ilist_callback_traits {
5356 void addNodeToList(MachineBasicBlock* MBB);
5457 void removeNodeFromList(MachineBasicBlock* MBB);
55 void deleteNode(MachineBasicBlock *MBB);
56 private:
57 void createNode(const MachineBasicBlock &);
58
59 template
60 void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) {
61 llvm_unreachable("Never transfer between lists");
62 }
5863 };
5964
6065 /// MachineFunctionInfo - This class can be derived from and used by targets to
117117
118118 // Intrusive list support
119119 friend struct ilist_traits;
120 friend struct ilist_traits;
120 friend struct ilist_callback_traits;
121121 void setParent(MachineBasicBlock *P) { Parent = P; }
122122
123123 /// This constructor creates a copy of the given
8080 }
8181 };
8282
83 template <> struct ilist_traits : public ilist_default_traits {
83 template <> struct ilist_alloc_traits {
8484 static void deleteNode(SDNode *) {
8585 llvm_unreachable("ilist_traits shouldn't see a deleteNode call!");
8686 }
87 private:
88 static void createNode(const SDNode &);
87 // Don't implement createNode...
8988 };
9089
9190 /// Keeps track of dbg_value information through SDISel. We do
4848 class MCSymbol;
4949 template struct DenseMapInfo;
5050 template struct simplify_type;
51 template struct ilist_traits;
5251
5352 void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr,
5453 bool force = false);
502501 static const EVT *getValueTypeList(EVT VT);
503502
504503 friend class SelectionDAG;
505 friend struct ilist_traits;
506504 // TODO: unfriend HandleSDNode once we fix its operand handling.
507505 friend class HandleSDNode;
508506
6868 };
6969
7070 template <>
71 struct ilist_traits
72 : public ilist_default_traits {
73 void deleteNode(IndexListEntry *N) {}
74
75 private:
76 void createNode(const IndexListEntry &);
77 };
71 struct ilist_alloc_traits
72 : public ilist_noalloc_traits {};
7873
7974 /// SlotIndex - An opaque wrapper around machine indexes.
8075 class SlotIndex {
12461246 ///
12471247 /// TODO: Inherit from Metadata.
12481248 class NamedMDNode : public ilist_node {
1249 friend struct ilist_traits;
12501249 friend class LLVMContextImpl;
12511250 friend class Module;
12521251 NamedMDNode(const NamedMDNode &) = delete;
3535 class RandomNumberGenerator;
3636 class StructType;
3737 template class SmallPtrSetImpl;
38
39 template<> struct ilist_traits
40 : public ilist_default_traits {
41 void addNodeToList(NamedMDNode *) {}
42 void removeNodeFromList(NamedMDNode *) {}
43 };
4438
4539 /// A Module instance is used to store all the information related to an
4640 /// LLVM module. Modules are the top level container of all other LLVM
5959 // ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
6060 //
6161 template
62 class SymbolTableListTraits : public ilist_node_traits {
62 class SymbolTableListTraits : public ilist_alloc_traits {
6363 typedef SymbolTableList ListTy;
6464 typedef ilist_iterator iterator;
6565 typedef
3030 class MCSymbol;
3131 class raw_ostream;
3232
33 template<>
34 struct ilist_node_traits {
35 MCFragment *createNode(const MCFragment &V);
33 template <> struct ilist_alloc_traits {
3634 static void deleteNode(MCFragment *V);
37
38 void addNodeToList(MCFragment *) {}
39 void removeNodeFromList(MCFragment *) {}
40 void transferNodesFromList(ilist_node_traits & /*SrcTraits*/,
41 ilist_iterator /*first*/,
42 ilist_iterator /*last*/) {}
35 // Leave out createNode...
4336 };
4437
4538 /// Instances of this class represent a uniqued identifier for a section in the
7373 /// MBBs start out as #-1. When a MBB is added to a MachineFunction, it
7474 /// gets the next available unique MBB number. If it is removed from a
7575 /// MachineFunction, it goes back to being #-1.
76 void ilist_traits::addNodeToList(MachineBasicBlock *N) {
76 void ilist_callback_traits::addNodeToList(
77 MachineBasicBlock *N) {
7778 MachineFunction &MF = *N->getParent();
7879 N->Number = MF.addToMBBNumbering(N);
7980
8485 I->AddRegOperandsToUseLists(RegInfo);
8586 }
8687
87 void ilist_traits::removeNodeFromList(MachineBasicBlock *N) {
88 void ilist_callback_traits::removeNodeFromList(
89 MachineBasicBlock *N) {
8890 N->getParent()->removeFromMBBNumbering(N->Number);
8991 N->Number = -1;
9092 }
115117
116118 /// When moving a range of instructions from one MBB list to another, we need to
117119 /// update the parent pointers and the use/def lists.
118 void ilist_traits::
119 transferNodesFromList(ilist_traits &FromList,
120 ilist_iterator First,
121 ilist_iterator Last) {
120 template <>
121 void ilist_traits::transferNodesFromList<
122 ilist::iterator>(ilist_traits &FromList,
123 ilist::iterator First,
124 ilist::iterator Last) {
122125 assert(Parent->getParent() == FromList.Parent->getParent() &&
123126 "MachineInstr parent mismatch!");
124127 assert(this != &FromList && "Called without a real transfer...");
130133 First->setParent(Parent);
131134 }
132135
133 void ilist_traits::deleteNode(MachineInstr* MI) {
136 void ilist_traits::deleteNode(MachineInstr *MI) {
134137 assert(!MI->getParent() && "MI is still in a block!");
135138 Parent->getParent()->DeleteMachineInstr(MI);
136139 }
8585 // Out-of-line virtual method.
8686 MachineFunctionInfo::~MachineFunctionInfo() {}
8787
88 void ilist_traits::deleteNode(MachineBasicBlock *MBB) {
88 void ilist_alloc_traits::deleteNode(MachineBasicBlock *MBB) {
8989 MBB->getParent()->DeleteMachineBasicBlock(MBB);
9090 }
9191
231231
232232 /* *** */
233233
234 void ilist_node_traits::deleteNode(MCFragment *V) {
235 V->destroy();
236 }
234 void ilist_alloc_traits::deleteNode(MCFragment *V) { V->destroy(); }
237235
238236 MCFragment::~MCFragment() { }
239237
148148 }
149149
150150 namespace llvm {
151 template<>
152 struct ilist_node_traits {
151 template <> struct ilist_alloc_traits {
153152 Token *createNode(const Token &V) {
154153 return new (Alloc.Allocate()) Token(V);
155154 }
156155 static void deleteNode(Token *V) { V->~Token(); }
157156
158 void addNodeToList(Token *) {}
159 void removeNodeFromList(Token *) {}
160 void transferNodesFromList(ilist_node_traits & /*SrcTraits*/,
161 ilist_iterator /*first*/,
162 ilist_iterator /*last*/) {}
163
164157 BumpPtrAllocator Alloc;
165158 };
166 }
159 } // end namespace llvm
167160
168161 typedef ilist TokenQueueT;
169162
166166 struct NodeWithCallback : ilist_node {
167167 int Value = 0;
168168 bool IsInList = false;
169 bool WasTransferred = false;
169170
170171 NodeWithCallback() = default;
171172 NodeWithCallback(int Value) : Value(Value) {}
175176 } // end namespace
176177
177178 namespace llvm {
178 template <>
179 struct ilist_traits
180 : public ilist_node_traits {
179 template <> struct ilist_callback_traits {
181180 void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }
182181 void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }
182 template
183 void transferNodesFromList(ilist_callback_traits &Other, Iterator First,
184 Iterator Last) {
185 for (; First != Last; ++First) {
186 First->WasTransferred = true;
187 Other.removeNodeFromList(&*First);
188 addNodeToList(&*First);
189 }
190 }
183191 };
184192 } // end namespace llvm
185193
186194 namespace {
187195
188196 TEST(IListTest, addNodeToList) {
189 ilist L;
197 ilist L1, L2;
190198 NodeWithCallback N(7);
191199 ASSERT_FALSE(N.IsInList);
192
193 L.insert(L.begin(), &N);
194 ASSERT_EQ(1u, L.size());
195 ASSERT_EQ(&N, &*L.begin());
200 ASSERT_FALSE(N.WasTransferred);
201
202 L1.insert(L1.begin(), &N);
203 ASSERT_EQ(1u, L1.size());
204 ASSERT_EQ(&N, &L1.front());
196205 ASSERT_TRUE(N.IsInList);
197
198 L.remove(&N);
199 ASSERT_EQ(0u, L.size());
206 ASSERT_FALSE(N.WasTransferred);
207
208 L2.splice(L2.end(), L1);
209 ASSERT_EQ(&N, &L2.front());
210 ASSERT_TRUE(N.IsInList);
211 ASSERT_TRUE(N.WasTransferred);
212
213 L1.remove(&N);
214 ASSERT_EQ(0u, L1.size());
200215 ASSERT_FALSE(N.IsInList);
216 ASSERT_TRUE(N.WasTransferred);
201217 }
202218
203219 struct PrivateNode : private ilist_node {