Skip to content

Commit 537c8f8

Browse files
committed
Add option to store Parent-pointer in ilist_node_base
1 parent b2bd024 commit 537c8f8

10 files changed

+140
-38
lines changed

llvm/include/llvm/ADT/ilist_base.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
namespace llvm {
1616

1717
/// Implementations of list algorithms using ilist_node_base.
18-
template <bool EnableSentinelTracking> class ilist_base {
18+
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_base {
1919
public:
20-
using node_base_type = ilist_node_base<EnableSentinelTracking>;
20+
using node_base_type = ilist_node_base<EnableSentinelTracking, ParentPtrTy>;
2121

2222
static void insertBeforeImpl(node_base_type &Next, node_base_type &N) {
2323
node_base_type &Prev = *Next.getPrev();

llvm/include/llvm/ADT/ilist_iterator.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
7070
using iterator_category = std::bidirectional_iterator_tag;
7171
using const_pointer = typename OptionsT::const_pointer;
7272
using const_reference = typename OptionsT::const_reference;
73+
using parent_ptr_ty = typename OptionsT::parent_ptr_ty;
7374

7475
private:
7576
using node_pointer = typename Traits::node_pointer;
@@ -101,6 +102,8 @@ class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
101102
return *this;
102103
}
103104

105+
parent_ptr_ty getNodeParent() { return NodePtr->getNodeBaseParent(); }
106+
104107
/// Explicit conversion between forward/reverse iterators.
105108
///
106109
/// Translate between forward and reverse iterators without changing range
@@ -168,6 +171,8 @@ class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
168171
return tmp;
169172
}
170173

174+
bool isValid() const { return NodePtr; }
175+
171176
/// Get the underlying ilist_node.
172177
node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
173178

@@ -195,6 +200,7 @@ class ilist_iterator_w_bits : ilist_detail::SpecificNodeAccess<OptionsT> {
195200
using iterator_category = std::bidirectional_iterator_tag;
196201
using const_pointer = typename OptionsT::const_pointer;
197202
using const_reference = typename OptionsT::const_reference;
203+
using parent_ptr_ty = typename OptionsT::parent_ptr_ty;
198204

199205
private:
200206
using node_pointer = typename Traits::node_pointer;
@@ -319,6 +325,10 @@ class ilist_iterator_w_bits : ilist_detail::SpecificNodeAccess<OptionsT> {
319325
return tmp;
320326
}
321327

328+
parent_ptr_ty getNodeParent() { return NodePtr->getNodeBaseParent(); }
329+
330+
bool isValid() const { return NodePtr; }
331+
322332
/// Get the underlying ilist_node.
323333
node_pointer getNodePtr() const { return static_cast<node_pointer>(NodePtr); }
324334

llvm/include/llvm/ADT/ilist_node.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type {
118118
}
119119

120120
// Under-approximation, but always available for assertions.
121+
using node_base_type::getNodeBaseParent;
121122
using node_base_type::isKnownSentinel;
123+
using node_base_type::setNodeBaseParent;
122124

123125
/// Check whether this is the sentinel node.
124126
///
@@ -171,6 +173,15 @@ template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type {
171173
/// }
172174
/// \endexample
173175
///
176+
/// When the \a ilist_parent<ParentTy> option is passed to an ilist_node and the
177+
/// owning ilist, each node contains a pointer to the ilist's owner. This
178+
/// pointer does not have any automatic behaviour; set it manually, including
179+
/// for the sentinel node when the list is created. The primary benefit of this
180+
/// over declaring and using this pointer in the final node class is that the
181+
/// pointer will be added in the sentinel, meaning that you can safely use \a
182+
/// ilist_iterator::getNodeParent() to get the node parent from any valid (i.e.
183+
/// non-null) iterator, even a sentinel value.
184+
///
174185
/// See \a is_valid_option for steps on adding a new option.
175186
template <class T, class... Options>
176187
class ilist_node

llvm/include/llvm/ADT/ilist_node_base.h

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ namespace llvm {
1616
/// Base class for ilist nodes.
1717
///
1818
/// Optionally tracks whether this node is the sentinel.
19-
template <bool EnableSentinelTracking> class ilist_node_base;
19+
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_node_base;
2020

21-
template <> class ilist_node_base<false> {
21+
template <> class ilist_node_base<false, void> {
2222
ilist_node_base *Prev = nullptr;
2323
ilist_node_base *Next = nullptr;
2424

@@ -28,11 +28,14 @@ template <> class ilist_node_base<false> {
2828
ilist_node_base *getPrev() const { return Prev; }
2929
ilist_node_base *getNext() const { return Next; }
3030

31+
void setNodeBaseParent(void) {}
32+
inline void getNodeBaseParent() const {}
33+
3134
bool isKnownSentinel() const { return false; }
3235
void initializeSentinel() {}
3336
};
3437

35-
template <> class ilist_node_base<true> {
38+
template <> class ilist_node_base<true, void> {
3639
PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;
3740
ilist_node_base *Next = nullptr;
3841

@@ -42,6 +45,48 @@ template <> class ilist_node_base<true> {
4245
ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }
4346
ilist_node_base *getNext() const { return Next; }
4447

48+
void setNodeBaseParent(void) {}
49+
inline void getNodeBaseParent() const {}
50+
51+
bool isSentinel() const { return PrevAndSentinel.getInt(); }
52+
bool isKnownSentinel() const { return isSentinel(); }
53+
void initializeSentinel() { PrevAndSentinel.setInt(true); }
54+
};
55+
56+
template <class ParentPtrTy> class ilist_node_base<false, ParentPtrTy> {
57+
ilist_node_base *Prev = nullptr;
58+
ilist_node_base *Next = nullptr;
59+
ParentPtrTy Parent = nullptr;
60+
61+
public:
62+
void setPrev(ilist_node_base *Prev) { this->Prev = Prev; }
63+
void setNext(ilist_node_base *Next) { this->Next = Next; }
64+
ilist_node_base *getPrev() const { return Prev; }
65+
ilist_node_base *getNext() const { return Next; }
66+
67+
void setNodeBaseParent(ParentPtrTy Parent) { this->Parent = Parent; }
68+
inline const ParentPtrTy getNodeBaseParent() const { return Parent; }
69+
inline ParentPtrTy getNodeBaseParent() { return Parent; }
70+
71+
bool isKnownSentinel() const { return false; }
72+
void initializeSentinel() {}
73+
};
74+
75+
template <class ParentPtrTy> class ilist_node_base<true, ParentPtrTy> {
76+
PointerIntPair<ilist_node_base *, 1> PrevAndSentinel;
77+
ilist_node_base *Next = nullptr;
78+
ParentPtrTy Parent = nullptr;
79+
80+
public:
81+
void setPrev(ilist_node_base *Prev) { PrevAndSentinel.setPointer(Prev); }
82+
void setNext(ilist_node_base *Next) { this->Next = Next; }
83+
ilist_node_base *getPrev() const { return PrevAndSentinel.getPointer(); }
84+
ilist_node_base *getNext() const { return Next; }
85+
86+
void setNodeBaseParent(ParentPtrTy Parent) { this->Parent = Parent; }
87+
inline const ParentPtrTy getNodeBaseParent() const { return Parent; }
88+
inline ParentPtrTy getNodeBaseParent() { return Parent; }
89+
4590
bool isSentinel() const { return PrevAndSentinel.getInt(); }
4691
bool isKnownSentinel() const { return isSentinel(); }
4792
void initializeSentinel() { PrevAndSentinel.setInt(true); }

llvm/include/llvm/ADT/ilist_node_options.h

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
namespace llvm {
1717

18-
template <bool EnableSentinelTracking> class ilist_node_base;
19-
template <bool EnableSentinelTracking> class ilist_base;
18+
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_node_base;
19+
template <bool EnableSentinelTracking, class ParentPtrTy> class ilist_base;
2020

2121
/// Option to choose whether to track sentinels.
2222
///
@@ -39,6 +39,19 @@ template <class Tag> struct ilist_tag {};
3939
/// iterator class to store that information.
4040
template <bool ExtraIteratorBits> struct ilist_iterator_bits {};
4141

42+
/// Option to add a pointer to this list's owner in every node.
43+
///
44+
/// This option causes the \a ilist_base_node for this list to contain a pointer
45+
/// ParentTy *Parent, returned by \a ilist_base_node::getNodeBaseParent() and
46+
/// set by \a ilist_base_node::setNodeBaseParent(ParentTy *Parent). The parent
47+
/// value is not set automatically; the ilist owner should set itself as the
48+
/// parent of the list sentinel, and the parent should be set on each node
49+
/// inserted into the list. This value is also not used by
50+
/// \a ilist_node_with_parent::getNodeParent(), but is used by \a
51+
/// ilist_iterator::getNodeParent(), which allows the parent to be fetched from
52+
/// any valid (non-null) iterator to this list, including the sentinel.
53+
template <class ParentTy> struct ilist_parent {};
54+
4255
namespace ilist_detail {
4356

4457
/// Helper trait for recording whether an option is specified explicitly.
@@ -114,6 +127,21 @@ template <> struct extract_iterator_bits<> : std::false_type, is_implicit {};
114127
template <bool IteratorBits>
115128
struct is_valid_option<ilist_iterator_bits<IteratorBits>> : std::true_type {};
116129

130+
/// Extract node parent option.
131+
///
132+
/// Look through \p Options for the \a ilist_parent option, pulling out the
133+
/// custom parent type, using void as a default.
134+
template <class... Options> struct extract_parent;
135+
template <class ParentTy, class... Options>
136+
struct extract_parent<ilist_parent<ParentTy>, Options...> {
137+
typedef ParentTy *type;
138+
};
139+
template <class Option1, class... Options>
140+
struct extract_parent<Option1, Options...> : extract_parent<Options...> {};
141+
template <> struct extract_parent<> { typedef void type; };
142+
template <class ParentTy>
143+
struct is_valid_option<ilist_parent<ParentTy>> : std::true_type {};
144+
117145
/// Check whether options are valid.
118146
///
119147
/// The conjunction of \a is_valid_option on each individual option.
@@ -128,7 +156,7 @@ struct check_options<Option1, Options...>
128156
///
129157
/// This is usually computed via \a compute_node_options.
130158
template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit,
131-
class TagT, bool HasIteratorBits>
159+
class TagT, bool HasIteratorBits, class ParentPtrTy>
132160
struct node_options {
133161
typedef T value_type;
134162
typedef T *pointer;
@@ -140,15 +168,18 @@ struct node_options {
140168
static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit;
141169
static const bool has_iterator_bits = HasIteratorBits;
142170
typedef TagT tag;
143-
typedef ilist_node_base<enable_sentinel_tracking> node_base_type;
144-
typedef ilist_base<enable_sentinel_tracking> list_base_type;
171+
typedef ParentPtrTy parent_ptr_ty;
172+
typedef ilist_node_base<enable_sentinel_tracking, parent_ptr_ty>
173+
node_base_type;
174+
typedef ilist_base<enable_sentinel_tracking, parent_ptr_ty> list_base_type;
145175
};
146176

147177
template <class T, class... Options> struct compute_node_options {
148178
typedef node_options<T, extract_sentinel_tracking<Options...>::value,
149179
extract_sentinel_tracking<Options...>::is_explicit,
150180
typename extract_tag<Options...>::type,
151-
extract_iterator_bits<Options...>::value>
181+
extract_iterator_bits<Options...>::value,
182+
typename extract_parent<Options...>::type>
152183
type;
153184
};
154185

llvm/include/llvm/IR/BasicBlock.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class DbgMarker;
5959
class BasicBlock final : public Value, // Basic blocks are data objects also
6060
public ilist_node_with_parent<BasicBlock, Function> {
6161
public:
62-
using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>>;
62+
using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>,
63+
ilist_parent<BasicBlock>>;
6364
/// Flag recording whether or not this block stores debug-info in the form
6465
/// of intrinsic instructions (false) or non-instruction records (true).
6566
bool IsNewDbgInfoFormat;
@@ -172,10 +173,11 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
172173
friend BasicBlock::iterator Instruction::eraseFromParent();
173174
friend BasicBlock::iterator Instruction::insertInto(BasicBlock *BB,
174175
BasicBlock::iterator It);
175-
friend class llvm::SymbolTableListTraits<llvm::Instruction,
176-
ilist_iterator_bits<true>>;
176+
friend class llvm::SymbolTableListTraits<
177+
llvm::Instruction, ilist_iterator_bits<true>, ilist_parent<BasicBlock>>;
177178
friend class llvm::ilist_node_with_parent<llvm::Instruction, llvm::BasicBlock,
178-
ilist_iterator_bits<true>>;
179+
ilist_iterator_bits<true>,
180+
ilist_parent<BasicBlock>>;
179181

180182
// Friendly methods that need to access us for the maintenence of
181183
// debug-info attachments.

llvm/include/llvm/IR/Instruction.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ getDbgRecordRange(DbgMarker *);
4646

4747
class Instruction : public User,
4848
public ilist_node_with_parent<Instruction, BasicBlock,
49-
ilist_iterator_bits<true>> {
49+
ilist_iterator_bits<true>,
50+
ilist_parent<BasicBlock>> {
5051
public:
51-
using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>>;
52+
using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>,
53+
ilist_parent<BasicBlock>>;
54+
5255
private:
53-
BasicBlock *Parent;
5456
DebugLoc DbgLoc; // 'dbg' Metadata cache.
5557

5658
/// Relative order of this instruction in its parent basic block. Used for
@@ -149,8 +151,8 @@ class Instruction : public User,
149151
Instruction *user_back() { return cast<Instruction>(*user_begin());}
150152
const Instruction *user_back() const { return cast<Instruction>(*user_begin());}
151153

152-
inline const BasicBlock *getParent() const { return Parent; }
153-
inline BasicBlock *getParent() { return Parent; }
154+
inline const BasicBlock *getParent() const { return getNodeBaseParent(); }
155+
inline BasicBlock *getParent() { return getNodeBaseParent(); }
154156

155157
/// Return the module owning the function this instruction belongs to
156158
/// or nullptr it the function does not have a module.
@@ -980,7 +982,8 @@ class Instruction : public User,
980982
};
981983

982984
private:
983-
friend class SymbolTableListTraits<Instruction, ilist_iterator_bits<true>>;
985+
friend class SymbolTableListTraits<Instruction, ilist_iterator_bits<true>,
986+
ilist_parent<BasicBlock>>;
984987
friend class BasicBlock; // For renumbering.
985988

986989
// Shadow Value::setValueSubclassData with a private forwarding method so that

llvm/include/llvm/IR/ValueSymbolTable.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class GlobalIFunc;
2828
class GlobalVariable;
2929
class Instruction;
3030
template <bool ExtraIteratorBits> struct ilist_iterator_bits;
31+
template <class ParentTy> struct ilist_parent;
3132
template <unsigned InternalLen> class SmallString;
3233
template <typename ValueSubClass, typename ... Args> class SymbolTableListTraits;
3334

@@ -42,7 +43,8 @@ class ValueSymbolTable {
4243
friend class SymbolTableListTraits<GlobalAlias>;
4344
friend class SymbolTableListTraits<GlobalIFunc>;
4445
friend class SymbolTableListTraits<GlobalVariable>;
45-
friend class SymbolTableListTraits<Instruction, ilist_iterator_bits<true>>;
46+
friend class SymbolTableListTraits<Instruction, ilist_iterator_bits<true>,
47+
ilist_parent<BasicBlock>>;
4648
friend class Value;
4749

4850
/// @name Types

llvm/lib/IR/BasicBlock.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ template <> void llvm::invalidateParentIListOrdering(BasicBlock *BB) {
175175

176176
// Explicit instantiation of SymbolTableListTraits since some of the methods
177177
// are not in the public header file...
178-
template class llvm::SymbolTableListTraits<Instruction,
179-
ilist_iterator_bits<true>>;
178+
template class llvm::SymbolTableListTraits<
179+
Instruction, ilist_iterator_bits<true>, ilist_parent<BasicBlock>>;
180180

181181
BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
182182
BasicBlock *InsertBefore)
@@ -189,6 +189,7 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
189189
assert(!InsertBefore &&
190190
"Cannot insert block before another block with no function!");
191191

192+
end().getNodePtr()->setNodeBaseParent(this);
192193
setName(Name);
193194
if (NewParent)
194195
setIsNewDbgInfoFormat(NewParent->IsNewDbgInfoFormat);

0 commit comments

Comments
 (0)