Skip to content

Commit f50c98b

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

File tree

10 files changed

+126
-39
lines changed

10 files changed

+126
-39
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: 2 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
///

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: 26 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,8 @@ template <class Tag> struct ilist_tag {};
3939
/// iterator class to store that information.
4040
template <bool ExtraIteratorBits> struct ilist_iterator_bits {};
4141

42+
template <class ParentTy> struct ilist_node_parent {};
43+
4244
namespace ilist_detail {
4345

4446
/// Helper trait for recording whether an option is specified explicitly.
@@ -114,6 +116,21 @@ template <> struct extract_iterator_bits<> : std::false_type, is_implicit {};
114116
template <bool IteratorBits>
115117
struct is_valid_option<ilist_iterator_bits<IteratorBits>> : std::true_type {};
116118

119+
/// Extract node parent option.
120+
///
121+
/// Look through \p Options for the \a ilist_node_parent option, pulling out the
122+
/// custom parnet type, using void as a default.
123+
template <class... Options> struct extract_parent;
124+
template <class ParentTy, class... Options>
125+
struct extract_parent<ilist_node_parent<ParentTy>, Options...> {
126+
typedef ParentTy *type;
127+
};
128+
template <class Option1, class... Options>
129+
struct extract_parent<Option1, Options...> : extract_parent<Options...> {};
130+
template <> struct extract_parent<> { typedef void type; };
131+
template <class ParentTy>
132+
struct is_valid_option<ilist_node_parent<ParentTy>> : std::true_type {};
133+
117134
/// Check whether options are valid.
118135
///
119136
/// The conjunction of \a is_valid_option on each individual option.
@@ -128,7 +145,7 @@ struct check_options<Option1, Options...>
128145
///
129146
/// This is usually computed via \a compute_node_options.
130147
template <class T, bool EnableSentinelTracking, bool IsSentinelTrackingExplicit,
131-
class TagT, bool HasIteratorBits>
148+
class TagT, bool HasIteratorBits, class ParentPtrTy>
132149
struct node_options {
133150
typedef T value_type;
134151
typedef T *pointer;
@@ -140,15 +157,18 @@ struct node_options {
140157
static const bool is_sentinel_tracking_explicit = IsSentinelTrackingExplicit;
141158
static const bool has_iterator_bits = HasIteratorBits;
142159
typedef TagT tag;
143-
typedef ilist_node_base<enable_sentinel_tracking> node_base_type;
144-
typedef ilist_base<enable_sentinel_tracking> list_base_type;
160+
typedef ParentPtrTy parent_ptr_ty;
161+
typedef ilist_node_base<enable_sentinel_tracking, parent_ptr_ty>
162+
node_base_type;
163+
typedef ilist_base<enable_sentinel_tracking, parent_ptr_ty> list_base_type;
145164
};
146165

147166
template <class T, class... Options> struct compute_node_options {
148167
typedef node_options<T, extract_sentinel_tracking<Options...>::value,
149168
extract_sentinel_tracking<Options...>::is_explicit,
150169
typename extract_tag<Options...>::type,
151-
extract_iterator_bits<Options...>::value>
170+
extract_iterator_bits<Options...>::value,
171+
typename extract_parent<Options...>::type>
152172
type;
153173
};
154174

llvm/include/llvm/IR/BasicBlock.h

Lines changed: 6 additions & 3 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_node_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;
@@ -173,9 +174,11 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
173174
friend BasicBlock::iterator Instruction::insertInto(BasicBlock *BB,
174175
BasicBlock::iterator It);
175176
friend class llvm::SymbolTableListTraits<llvm::Instruction,
176-
ilist_iterator_bits<true>>;
177+
ilist_iterator_bits<true>,
178+
ilist_node_parent<BasicBlock>>;
177179
friend class llvm::ilist_node_with_parent<llvm::Instruction, llvm::BasicBlock,
178-
ilist_iterator_bits<true>>;
180+
ilist_iterator_bits<true>,
181+
ilist_node_parent<BasicBlock>>;
179182

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

llvm/include/llvm/IR/Instruction.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ template <> struct ilist_alloc_traits<Instruction> {
4444
iterator_range<simple_ilist<DbgRecord>::iterator>
4545
getDbgRecordRange(DbgMarker *);
4646

47-
class Instruction : public User,
48-
public ilist_node_with_parent<Instruction, BasicBlock,
49-
ilist_iterator_bits<true>> {
47+
class Instruction
48+
: public User,
49+
public ilist_node_with_parent<Instruction, BasicBlock,
50+
ilist_iterator_bits<true>,
51+
ilist_node_parent<BasicBlock>> {
5052
public:
51-
using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>>;
53+
using InstListType = SymbolTableList<Instruction, ilist_iterator_bits<true>,
54+
ilist_node_parent<BasicBlock>>;
55+
5256
private:
53-
BasicBlock *Parent;
5457
DebugLoc DbgLoc; // 'dbg' Metadata cache.
5558

5659
/// Relative order of this instruction in its parent basic block. Used for
@@ -149,8 +152,8 @@ class Instruction : public User,
149152
Instruction *user_back() { return cast<Instruction>(*user_begin());}
150153
const Instruction *user_back() const { return cast<Instruction>(*user_begin());}
151154

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

155158
/// Return the module owning the function this instruction belongs to
156159
/// or nullptr it the function does not have a module.
@@ -980,7 +983,8 @@ class Instruction : public User,
980983
};
981984

982985
private:
983-
friend class SymbolTableListTraits<Instruction, ilist_iterator_bits<true>>;
986+
friend class SymbolTableListTraits<Instruction, ilist_iterator_bits<true>,
987+
ilist_node_parent<BasicBlock>>;
984988
friend class BasicBlock; // For renumbering.
985989

986990
// 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_node_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_node_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_node_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);

llvm/lib/IR/Instruction.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ using namespace llvm;
2727

2828
Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
2929
InstListType::iterator InsertBefore)
30-
: User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) {
31-
30+
: User(ty, Value::InstructionVal + it, Ops, NumOps) {
31+
setParent(nullptr);
3232
// When called with an iterator, there must be a block to insert into.
3333
BasicBlock *BB = InsertBefore->getParent();
3434
assert(BB && "Instruction to insert before is not in a basic block!");
@@ -37,7 +37,8 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
3737

3838
Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
3939
Instruction *InsertBefore)
40-
: User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) {
40+
: User(ty, Value::InstructionVal + it, Ops, NumOps) {
41+
setParent(nullptr);
4142

4243
// If requested, insert this instruction into a basic block...
4344
if (InsertBefore) {
@@ -49,15 +50,15 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
4950

5051
Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
5152
BasicBlock *InsertAtEnd)
52-
: User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) {
53-
53+
: User(ty, Value::InstructionVal + it, Ops, NumOps) {
54+
setParent(nullptr);
5455
// If requested, append this instruction into the basic block.
5556
if (InsertAtEnd)
5657
insertInto(InsertAtEnd, InsertAtEnd->end());
5758
}
5859

5960
Instruction::~Instruction() {
60-
assert(!Parent && "Instruction still linked in the program!");
61+
assert(!getParent() && "Instruction still linked in the program!");
6162

6263
// Replace any extant metadata uses of this instruction with undef to
6364
// preserve debug info accuracy. Some alternatives include:
@@ -76,9 +77,7 @@ Instruction::~Instruction() {
7677
setMetadata(LLVMContext::MD_DIAssignID, nullptr);
7778
}
7879

79-
void Instruction::setParent(BasicBlock *P) {
80-
Parent = P;
81-
}
80+
void Instruction::setParent(BasicBlock *P) { setNodeBaseParent(P); }
8281

8382
const Module *Instruction::getModule() const {
8483
return getParent()->getModule();
@@ -96,7 +95,7 @@ void Instruction::removeFromParent() {
9695
}
9796

9897
void Instruction::handleMarkerRemoval() {
99-
if (!Parent->IsNewDbgInfoFormat || !DebugMarker)
98+
if (!getParent()->IsNewDbgInfoFormat || !DebugMarker)
10099
return;
101100

102101
DebugMarker->removeMarker();
@@ -329,11 +328,12 @@ void Instruction::dropOneDbgRecord(DbgRecord *DVR) {
329328
}
330329

331330
bool Instruction::comesBefore(const Instruction *Other) const {
332-
assert(Parent && Other->Parent &&
331+
assert(getParent() && Other->getParent() &&
333332
"instructions without BB parents have no order");
334-
assert(Parent == Other->Parent && "cross-BB instruction order comparison");
335-
if (!Parent->isInstrOrderValid())
336-
Parent->renumberInstructions();
333+
assert(getParent() == Other->getParent() &&
334+
"cross-BB instruction order comparison");
335+
if (!getParent()->isInstrOrderValid())
336+
const_cast<BasicBlock *>(getParent())->renumberInstructions();
337337
return Order < Other->Order;
338338
}
339339

0 commit comments

Comments
 (0)