Skip to content

Commit f947c3a

Browse files
committed
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. llvm-svn: 280128
1 parent 982a3bc commit f947c3a

16 files changed

+107
-86
lines changed

llvm/include/llvm/ADT/ilist.h

+37-7
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,57 @@
3333

3434
namespace llvm {
3535

36-
/// A fragment for template traits for intrusive list that provides default
37-
/// node related operations.
36+
/// Use new/delete by default for iplist and ilist.
3837
///
39-
/// TODO: Split up (alloc vs. callback) and delete.
40-
template <typename NodeTy> struct ilist_node_traits {
38+
/// Specialize this to get different behaviour for allocation-related API. (If
39+
/// you really want new/delete, consider just using std::list.)
40+
///
41+
/// \see ilist_noalloc_traits
42+
template <typename NodeTy> struct ilist_alloc_traits {
4143
static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); }
4244
static void deleteNode(NodeTy *V) { delete V; }
45+
};
46+
47+
/// Custom traits to disable node creation and do nothing on deletion.
48+
///
49+
/// Specialize ilist_alloc_traits to inherit from this to disable the
50+
/// non-intrusive parts of iplist and/or ilist. It has no createNode function,
51+
/// and deleteNode does nothing.
52+
///
53+
/// \code
54+
/// template <>
55+
/// struct ilist_alloc_traits<MyType> : ilist_noalloc_traits<MyType> {};
56+
/// \endcode
57+
template <typename NodeTy> struct ilist_noalloc_traits {
58+
static void deleteNode(NodeTy *V) {}
59+
};
4360

61+
/// Callbacks do nothing by default in iplist and ilist.
62+
///
63+
/// Specialize this for to use callbacks for when nodes change their list
64+
/// membership.
65+
template <typename NodeTy> struct ilist_callback_traits {
4466
void addNodeToList(NodeTy *) {}
4567
void removeNodeFromList(NodeTy *) {}
4668

4769
/// Callback before transferring nodes to this list.
4870
///
4971
/// \pre \c this!=&OldList
50-
void transferNodesFromList(ilist_node_traits &OldList,
51-
ilist_iterator<NodeTy> /*first*/,
52-
ilist_iterator<NodeTy> /*last*/) {
72+
template <class Iterator>
73+
void transferNodesFromList(ilist_callback_traits &OldList, Iterator /*first*/,
74+
Iterator /*last*/) {
5375
(void)OldList;
5476
}
5577
};
5678

79+
/// A fragment for template traits for intrusive list that provides default
80+
/// node related operations.
81+
///
82+
/// TODO: Remove this layer of indirection. It's not necessary.
83+
template <typename NodeTy>
84+
struct ilist_node_traits : ilist_alloc_traits<NodeTy>,
85+
ilist_callback_traits<NodeTy> {};
86+
5787
/// Default template traits for intrusive list.
5888
///
5989
/// By inheriting from this, you can easily use default implementations for all

llvm/include/llvm/CodeGen/MachineBasicBlock.h

+12-14
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,20 @@ class MachineBranchProbabilityInfo;
3838
// Forward declaration to avoid circular include problem with TargetRegisterInfo
3939
typedef unsigned LaneBitmask;
4040

41-
template <>
42-
struct ilist_traits<MachineInstr> : public ilist_default_traits<MachineInstr> {
41+
template <> struct ilist_traits<MachineInstr> {
4342
private:
44-
// this is only set by the MachineBasicBlock owning the LiveList
45-
friend class MachineBasicBlock;
46-
MachineBasicBlock* Parent;
43+
friend class MachineBasicBlock; // Set by the owning MachineBasicBlock.
44+
MachineBasicBlock *Parent;
4745

4846
public:
49-
void addNodeToList(MachineInstr* N);
50-
void removeNodeFromList(MachineInstr* N);
51-
void transferNodesFromList(ilist_traits &SrcTraits,
52-
ilist_iterator<MachineInstr> First,
53-
ilist_iterator<MachineInstr> Last);
54-
void deleteNode(MachineInstr *N);
55-
private:
56-
void createNode(const MachineInstr &);
47+
void addNodeToList(MachineInstr *N);
48+
void removeNodeFromList(MachineInstr *N);
49+
template <class Iterator>
50+
void transferNodesFromList(ilist_traits &OldList, Iterator First,
51+
Iterator Last);
52+
53+
void deleteNode(MachineInstr *MI);
54+
// Leave out createNode...
5755
};
5856

5957
class MachineBasicBlock
@@ -697,7 +695,7 @@ class MachineBasicBlock
697695
BranchProbability getSuccProbability(const_succ_iterator Succ) const;
698696

699697
// Methods used to maintain doubly linked list of blocks...
700-
friend struct ilist_traits<MachineBasicBlock>;
698+
friend struct ilist_callback_traits<MachineBasicBlock>;
701699

702700
// Machine-CFG mutators
703701

llvm/include/llvm/CodeGen/MachineFunction.h

+11-6
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,19 @@ class TargetRegisterClass;
4848
struct MachinePointerInfo;
4949
struct WinEHFuncInfo;
5050

51-
template <>
52-
struct ilist_traits<MachineBasicBlock>
53-
: public ilist_default_traits<MachineBasicBlock> {
51+
template <> struct ilist_alloc_traits<MachineBasicBlock> {
52+
void deleteNode(MachineBasicBlock *MBB);
53+
// Disallow createNode...
54+
};
55+
56+
template <> struct ilist_callback_traits<MachineBasicBlock> {
5457
void addNodeToList(MachineBasicBlock* MBB);
5558
void removeNodeFromList(MachineBasicBlock* MBB);
56-
void deleteNode(MachineBasicBlock *MBB);
57-
private:
58-
void createNode(const MachineBasicBlock &);
59+
60+
template <class Iterator>
61+
void transferNodesFromList(ilist_callback_traits &OldList, Iterator, Iterator) {
62+
llvm_unreachable("Never transfer between lists");
63+
}
5964
};
6065

6166
/// MachineFunctionInfo - This class can be derived from and used by targets to

llvm/include/llvm/CodeGen/MachineInstr.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class MachineInstr
118118

119119
// Intrusive list support
120120
friend struct ilist_traits<MachineInstr>;
121-
friend struct ilist_traits<MachineBasicBlock>;
121+
friend struct ilist_callback_traits<MachineBasicBlock>;
122122
void setParent(MachineBasicBlock *P) { Parent = P; }
123123

124124
/// This constructor creates a copy of the given

llvm/include/llvm/CodeGen/SelectionDAG.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,11 @@ template<> struct FoldingSetTrait<SDVTListNode> : DefaultFoldingSetTrait<SDVTLis
8181
}
8282
};
8383

84-
template <> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
84+
template <> struct ilist_alloc_traits<SDNode> {
8585
static void deleteNode(SDNode *) {
8686
llvm_unreachable("ilist_traits<SDNode> shouldn't see a deleteNode call!");
8787
}
88-
private:
89-
static void createNode(const SDNode &);
88+
// Don't implement createNode...
9089
};
9190

9291
/// Keeps track of dbg_value information through SDISel. We do

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ class Value;
4949
class MCSymbol;
5050
template <typename T> struct DenseMapInfo;
5151
template <typename T> struct simplify_type;
52-
template <typename T> struct ilist_traits;
5352

5453
void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr,
5554
bool force = false);
@@ -503,7 +502,6 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
503502
static const EVT *getValueTypeList(EVT VT);
504503

505504
friend class SelectionDAG;
506-
friend struct ilist_traits<SDNode>;
507505
// TODO: unfriend HandleSDNode once we fix its operand handling.
508506
friend class HandleSDNode;
509507

llvm/include/llvm/CodeGen/SlotIndexes.h

+2-7
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,8 @@ namespace llvm {
6969
};
7070

7171
template <>
72-
struct ilist_traits<IndexListEntry>
73-
: public ilist_default_traits<IndexListEntry> {
74-
void deleteNode(IndexListEntry *N) {}
75-
76-
private:
77-
void createNode(const IndexListEntry &);
78-
};
72+
struct ilist_alloc_traits<IndexListEntry>
73+
: public ilist_noalloc_traits<IndexListEntry> {};
7974

8075
/// SlotIndex - An opaque wrapper around machine indexes.
8176
class SlotIndex {

llvm/include/llvm/IR/Metadata.h

-1
Original file line numberDiff line numberDiff line change
@@ -1247,7 +1247,6 @@ class DistinctMDOperandPlaceholder : public Metadata {
12471247
///
12481248
/// TODO: Inherit from Metadata.
12491249
class NamedMDNode : public ilist_node<NamedMDNode> {
1250-
friend struct ilist_traits<NamedMDNode>;
12511250
friend class LLVMContextImpl;
12521251
friend class Module;
12531252
NamedMDNode(const NamedMDNode &) = delete;

llvm/include/llvm/IR/Module.h

-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,6 @@ class RandomNumberGenerator;
3737
class StructType;
3838
template <class PtrType> class SmallPtrSetImpl;
3939

40-
template<> struct ilist_traits<NamedMDNode>
41-
: public ilist_default_traits<NamedMDNode> {
42-
void addNodeToList(NamedMDNode *) {}
43-
void removeNodeFromList(NamedMDNode *) {}
44-
};
45-
4640
/// A Module instance is used to store all the information related to an
4741
/// LLVM module. Modules are the top level container of all other LLVM
4842
/// Intermediate Representation (IR) objects. Each module directly contains a

llvm/include/llvm/IR/SymbolTableListTraits.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ template <typename NodeTy> class SymbolTableList;
6060
// ItemParentClass - The type of object that owns the list, e.g. BasicBlock.
6161
//
6262
template <typename ValueSubClass>
63-
class SymbolTableListTraits : public ilist_node_traits<ValueSubClass> {
63+
class SymbolTableListTraits : public ilist_alloc_traits<ValueSubClass> {
6464
typedef SymbolTableList<ValueSubClass> ListTy;
6565
typedef ilist_iterator<ValueSubClass, false> iterator;
6666
typedef

llvm/include/llvm/MC/MCSection.h

+2-9
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,9 @@ class MCSection;
3131
class MCSymbol;
3232
class raw_ostream;
3333

34-
template<>
35-
struct ilist_node_traits<MCFragment> {
36-
MCFragment *createNode(const MCFragment &V);
34+
template <> struct ilist_alloc_traits<MCFragment> {
3735
static void deleteNode(MCFragment *V);
38-
39-
void addNodeToList(MCFragment *) {}
40-
void removeNodeFromList(MCFragment *) {}
41-
void transferNodesFromList(ilist_node_traits & /*SrcTraits*/,
42-
ilist_iterator<MCFragment> /*first*/,
43-
ilist_iterator<MCFragment> /*last*/) {}
36+
// Leave out createNode...
4437
};
4538

4639
/// Instances of this class represent a uniqued identifier for a section in the

llvm/lib/CodeGen/MachineBasicBlock.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineBasicBlock &MBB) {
7474
/// MBBs start out as #-1. When a MBB is added to a MachineFunction, it
7575
/// gets the next available unique MBB number. If it is removed from a
7676
/// MachineFunction, it goes back to being #-1.
77-
void ilist_traits<MachineBasicBlock>::addNodeToList(MachineBasicBlock *N) {
77+
void ilist_callback_traits<MachineBasicBlock>::addNodeToList(
78+
MachineBasicBlock *N) {
7879
MachineFunction &MF = *N->getParent();
7980
N->Number = MF.addToMBBNumbering(N);
8081

@@ -85,7 +86,8 @@ void ilist_traits<MachineBasicBlock>::addNodeToList(MachineBasicBlock *N) {
8586
I->AddRegOperandsToUseLists(RegInfo);
8687
}
8788

88-
void ilist_traits<MachineBasicBlock>::removeNodeFromList(MachineBasicBlock *N) {
89+
void ilist_callback_traits<MachineBasicBlock>::removeNodeFromList(
90+
MachineBasicBlock *N) {
8991
N->getParent()->removeFromMBBNumbering(N->Number);
9092
N->Number = -1;
9193
}
@@ -116,10 +118,11 @@ void ilist_traits<MachineInstr>::removeNodeFromList(MachineInstr *N) {
116118

117119
/// When moving a range of instructions from one MBB list to another, we need to
118120
/// update the parent pointers and the use/def lists.
119-
void ilist_traits<MachineInstr>::
120-
transferNodesFromList(ilist_traits<MachineInstr> &FromList,
121-
ilist_iterator<MachineInstr> First,
122-
ilist_iterator<MachineInstr> Last) {
121+
template <>
122+
void ilist_traits<MachineInstr>::transferNodesFromList<
123+
ilist<MachineInstr>::iterator>(ilist_traits<MachineInstr> &FromList,
124+
ilist<MachineInstr>::iterator First,
125+
ilist<MachineInstr>::iterator Last) {
123126
assert(Parent->getParent() == FromList.Parent->getParent() &&
124127
"MachineInstr parent mismatch!");
125128
assert(this != &FromList && "Called without a real transfer...");
@@ -131,7 +134,7 @@ transferNodesFromList(ilist_traits<MachineInstr> &FromList,
131134
First->setParent(Parent);
132135
}
133136

134-
void ilist_traits<MachineInstr>::deleteNode(MachineInstr* MI) {
137+
void ilist_traits<MachineInstr>::deleteNode(MachineInstr *MI) {
135138
assert(!MI->getParent() && "MI is still in a block!");
136139
Parent->getParent()->DeleteMachineInstr(MI);
137140
}

llvm/lib/CodeGen/MachineFunction.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ void MachineFunctionProperties::print(raw_ostream &OS) const {
8686
// Out-of-line virtual method.
8787
MachineFunctionInfo::~MachineFunctionInfo() {}
8888

89-
void ilist_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) {
89+
void ilist_alloc_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) {
9090
MBB->getParent()->DeleteMachineBasicBlock(MBB);
9191
}
9292

llvm/lib/MC/MCFragment.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,7 @@ uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler,
232232

233233
/* *** */
234234

235-
void ilist_node_traits<MCFragment>::deleteNode(MCFragment *V) {
236-
V->destroy();
237-
}
235+
void ilist_alloc_traits<MCFragment>::deleteNode(MCFragment *V) { V->destroy(); }
238236

239237
MCFragment::~MCFragment() { }
240238

llvm/lib/Support/YAMLParser.cpp

+2-9
Original file line numberDiff line numberDiff line change
@@ -149,22 +149,15 @@ struct Token : ilist_node<Token> {
149149
}
150150

151151
namespace llvm {
152-
template<>
153-
struct ilist_node_traits<Token> {
152+
template <> struct ilist_alloc_traits<Token> {
154153
Token *createNode(const Token &V) {
155154
return new (Alloc.Allocate<Token>()) Token(V);
156155
}
157156
static void deleteNode(Token *V) { V->~Token(); }
158157

159-
void addNodeToList(Token *) {}
160-
void removeNodeFromList(Token *) {}
161-
void transferNodesFromList(ilist_node_traits & /*SrcTraits*/,
162-
ilist_iterator<Token> /*first*/,
163-
ilist_iterator<Token> /*last*/) {}
164-
165158
BumpPtrAllocator Alloc;
166159
};
167-
}
160+
} // end namespace llvm
168161

169162
typedef ilist<Token> TokenQueueT;
170163

llvm/unittests/ADT/IListTest.cpp

+25-9
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ TEST(IListTest, HasCreateSentinelTrait) {
167167
struct NodeWithCallback : ilist_node<NodeWithCallback> {
168168
int Value = 0;
169169
bool IsInList = false;
170+
bool WasTransferred = false;
170171

171172
NodeWithCallback() = default;
172173
NodeWithCallback(int Value) : Value(Value) {}
@@ -176,29 +177,44 @@ struct NodeWithCallback : ilist_node<NodeWithCallback> {
176177
} // end namespace
177178

178179
namespace llvm {
179-
template <>
180-
struct ilist_traits<NodeWithCallback>
181-
: public ilist_node_traits<NodeWithCallback> {
180+
template <> struct ilist_callback_traits<NodeWithCallback> {
182181
void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }
183182
void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }
183+
template <class Iterator>
184+
void transferNodesFromList(ilist_callback_traits &Other, Iterator First,
185+
Iterator Last) {
186+
for (; First != Last; ++First) {
187+
First->WasTransferred = true;
188+
Other.removeNodeFromList(&*First);
189+
addNodeToList(&*First);
190+
}
191+
}
184192
};
185193
} // end namespace llvm
186194

187195
namespace {
188196

189197
TEST(IListTest, addNodeToList) {
190-
ilist<NodeWithCallback> L;
198+
ilist<NodeWithCallback> L1, L2;
191199
NodeWithCallback N(7);
192200
ASSERT_FALSE(N.IsInList);
201+
ASSERT_FALSE(N.WasTransferred);
193202

194-
L.insert(L.begin(), &N);
195-
ASSERT_EQ(1u, L.size());
196-
ASSERT_EQ(&N, &*L.begin());
203+
L1.insert(L1.begin(), &N);
204+
ASSERT_EQ(1u, L1.size());
205+
ASSERT_EQ(&N, &L1.front());
206+
ASSERT_TRUE(N.IsInList);
207+
ASSERT_FALSE(N.WasTransferred);
208+
209+
L2.splice(L2.end(), L1);
210+
ASSERT_EQ(&N, &L2.front());
197211
ASSERT_TRUE(N.IsInList);
212+
ASSERT_TRUE(N.WasTransferred);
198213

199-
L.remove(&N);
200-
ASSERT_EQ(0u, L.size());
214+
L1.remove(&N);
215+
ASSERT_EQ(0u, L1.size());
201216
ASSERT_FALSE(N.IsInList);
217+
ASSERT_TRUE(N.WasTransferred);
202218
}
203219

204220
struct PrivateNode : private ilist_node<PrivateNode> {

0 commit comments

Comments
 (0)