llvm.org GIT mirror llvm / a266197
Switch from using an ilist for uses to using a custom doubly linked list. This list does not provide the ability to go backwards in the list (its more of an unordered collection, stored in the shape of a list). This change means that use iterators are now only forward iterators, not bidirectional. This improves the memory usage of use lists from '5 + 4*#use' per value to '1 + 4*#use'. While it would be better to reduce the multiplied factor, I'm not smart enough to do so. This list also has slightly more efficient operators for manipulating list nodes (a few less loads/stores), due to not needing to be able to iterate backwards through the list. This change reduces the memory footprint required to hold 176.gcc from 66.025M -> 57.687M, a 14% reduction. It also speeds up the compiler, 7.73% in the case of bytecode loading alone (release build loading 176.gcc). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@19956 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 15 years ago
3 changed file(s) with 83 addition(s) and 122 deletion(s). Raw diff Collapse all Expand all
2626 //===--------------------------------------------------------------------===//
2727
2828 template // Predecessor Iterator
29 class PredIterator : public bidirectional_iterator<_Ptr, ptrdiff_t> {
30 typedef bidirectional_iterator<_Ptr, ptrdiff_t> super;
29 class PredIterator : public forward_iterator<_Ptr, ptrdiff_t> {
30 typedef forward_iterator<_Ptr, ptrdiff_t> super;
3131 _Ptr *BB;
3232 _USE_iterator It;
3333 public:
3434 typedef PredIterator<_Ptr,_USE_iterator> _Self;
3535 typedef typename super::pointer pointer;
3636
37 inline void advancePastConstants() {
37 inline void advancePastNonTerminators() {
3838 // Loop to ignore non terminator uses (for example PHI nodes)...
3939 while (It != BB->use_end() && !isa(*It))
4040 ++It;
4141 }
4242
4343 inline PredIterator(_Ptr *bb) : BB(bb), It(bb->use_begin()) {
44 advancePastConstants();
44 advancePastNonTerminators();
4545 }
4646 inline PredIterator(_Ptr *bb, bool) : BB(bb), It(bb->use_end()) {}
4747
5656
5757 inline _Self& operator++() { // Preincrement
5858 assert(It != BB->use_end() && "pred_iterator out of range!");
59 ++It; advancePastConstants();
59 ++It; advancePastNonTerminators();
6060 return *this;
6161 }
6262
6363 inline _Self operator++(int) { // Postincrement
6464 _Self tmp = *this; ++*this; return tmp;
65 }
66
67 inline _Self& operator--() { --It; return *this; } // Predecrement
68 inline _Self operator--(int) { // Postdecrement
69 _Self tmp = *this; --*this; return tmp;
7065 }
7166 };
7267
1515 #ifndef LLVM_USE_H
1616 #define LLVM_USE_H
1717
18 #include "llvm/ADT/ilist"
18 #include "llvm/Support/Casting.h"
19 #include "llvm/ADT/iterator"
1920
2021 namespace llvm {
2122
22 template struct ilist_traits;
2323 class Value;
2424 class User;
2525
6161 Value *operator->() { return Val; }
6262 const Value *operator->() const { return Val; }
6363
64 Use *getNext() const { return Next; }
6465 private:
65 // NOTE!! The Next/Prev fields MUST stay at the start of this structure. The
66 // end-token for the ilist is allocated as JUST the next/prev pair to reduce
67 // memory usage instead of allocating an entire Use.
68 struct NextPrevPtrs {
69 Use *Next, *Prev;
70 } UseLinks;
71
66 Use *Next, **Prev;
7267 Value *Val;
7368 User *U;
74 friend struct ilist_traits;
69
70 void addToList(Use **List) {
71 Next = *List;
72 if (Next) Next->Prev = &Next;
73 Prev = List;
74 *List = this;
75 }
76 void removeFromList() {
77 *Prev = Next;
78 if (Next) Next->Prev = Prev;
79 }
80
81 friend class Value;
7582 };
7683
77 template<>
78 struct ilist_traits {
79 static Use *getPrev(Use *N) { return N->UseLinks.Prev; }
80 static Use *getNext(Use *N) { return N->UseLinks.Next; }
81 static const Use *getPrev(const Use *N) { return N->UseLinks.Prev; }
82 static const Use *getNext(const Use *N) { return N->UseLinks.Next; }
83 static void setPrev(Use *N, Use *Prev) { N->UseLinks.Prev = Prev; }
84 static void setNext(Use *N, Use *Next) { N->UseLinks.Next = Next; }
85
86 /// createSentinel - this is used to create the end marker for the use list.
87 /// Note that we only allocate a UseLinks structure, which is just enough to
88 /// hold the next/prev pointers. This saves us 8 bytes of memory for every
89 /// Value allocated.
90 static Use *createSentinel() { return (Use*)new Use::NextPrevPtrs(); }
91 static void destroySentinel(Use *S) { delete (Use::NextPrevPtrs*)S; }
92
93 void addNodeToList(Use *NTy) {}
94 void removeNodeFromList(Use *NTy) {}
95 void transferNodesFromList(iplist &L2,
96 ilist_iterator first,
97 ilist_iterator last) {}
98 };
99
100
84 // simplify_type - Allow clients to treat uses just like values when using
85 // casting operators.
10186 template<> struct simplify_type {
10287 typedef Value* SimpleType;
10388 static SimpleType getSimplifiedValue(const Use &Val) {
11196 }
11297 };
11398
114 struct UseListIteratorWrapper : public iplist::iterator {
115 typedef iplist::iterator Super;
116 UseListIteratorWrapper() {}
117 UseListIteratorWrapper(const Super &RHS) : Super(RHS) {}
11899
119 UseListIteratorWrapper &operator=(const Super &RHS) {
120 Super::operator=(RHS);
121 return *this;
100
101 template // UserTy == 'User' or 'const User'
102 class value_use_iterator : public forward_iterator {
103 typedef forward_iterator super;
104 typedef value_use_iterator _Self;
105
106 Use *U;
107 value_use_iterator(Use *u) : U(u) {}
108 friend class Value;
109 public:
110 typedef typename super::reference reference;
111 typedef typename super::pointer pointer;
112
113 value_use_iterator(const _Self &I) : U(I.U) {}
114 value_use_iterator() {}
115
116 bool operator==(const _Self &x) const {
117 return U == x.U;
118 }
119 bool operator!=(const _Self &x) const {
120 return !operator==(x);
122121 }
123122
124 inline User *operator*() const;
125 User *operator->() const { return operator*(); }
126
127 UseListIteratorWrapper operator--() { return Super::operator--(); }
128 UseListIteratorWrapper operator++() { return Super::operator++(); }
129
130 UseListIteratorWrapper operator--(int) { // postdecrement operators...
131 UseListIteratorWrapper tmp = *this;
132 --*this;
133 return tmp;
123 // Iterator traversal: forward iteration only
124 _Self &operator++() { // Preincrement
125 assert(U && "Cannot increment end iterator!");
126 U = U->getNext();
127 return *this;
134128 }
135 UseListIteratorWrapper operator++(int) { // postincrement operators...
136 UseListIteratorWrapper tmp = *this;
137 ++*this;
138 return tmp;
139 }
140 };
141
142 struct UseListConstIteratorWrapper : public iplist::const_iterator {
143 typedef iplist::const_iterator Super;
144 UseListConstIteratorWrapper() {}
145 UseListConstIteratorWrapper(const Super &RHS) : Super(RHS) {}
146
147 // Allow conversion from non-const to const iterators
148 UseListConstIteratorWrapper(const UseListIteratorWrapper &RHS) : Super(RHS) {}
149 UseListConstIteratorWrapper(const iplist::iterator &RHS) : Super(RHS) {}
150
151 UseListConstIteratorWrapper &operator=(const Super &RHS) {
152 Super::operator=(RHS);
153 return *this;
129 _Self operator++(int) { // Postincrement
130 _Self tmp = *this; ++*this; return tmp;
154131 }
155132
156 inline const User *operator*() const;
157 const User *operator->() const { return operator*(); }
133 // Retrieve a reference to the current SCC
134 UserTy *operator*() const {
135 assert(U && "Cannot increment end iterator!");
136 return U->getUser();
137 }
158138
159 UseListConstIteratorWrapper operator--() { return Super::operator--(); }
160 UseListConstIteratorWrapper operator++() { return Super::operator++(); }
139 UserTy *operator->() const { return operator*(); }
161140
162 UseListConstIteratorWrapper operator--(int) { // postdecrement operators...
163 UseListConstIteratorWrapper tmp = *this;
164 --*this;
165 return tmp;
166 }
167 UseListConstIteratorWrapper operator++(int) { // postincrement operators...
168 UseListConstIteratorWrapper tmp = *this;
169 ++*this;
170 return tmp;
171 }
141 Use &getUse() const { return *U; }
172142 };
173143
174144 } // End llvm namespace
4242 class Value {
4343 unsigned SubclassID; // Subclass identifier (for isa/dyn_cast)
4444 PATypeHolder Ty;
45 iplist Uses;
45 Use *UseList;
4646 std::string Name;
4747
4848 void operator=(const Value &); // Do not implement
8585 //----------------------------------------------------------------------
8686 // Methods for handling the vector of uses of this Value.
8787 //
88 typedef UseListIteratorWrapper use_iterator;
89 typedef UseListConstIteratorWrapper use_const_iterator;
90 typedef iplist::size_type size_type;
91
92 size_type use_size() const { return Uses.size(); }
93 bool use_empty() const { return Uses.empty(); }
94 use_iterator use_begin() { return Uses.begin(); }
95 use_const_iterator use_begin() const { return Uses.begin(); }
96 use_iterator use_end() { return Uses.end(); }
97 use_const_iterator use_end() const { return Uses.end(); }
98 User *use_back() { return Uses.back().getUser(); }
99 const User *use_back() const { return Uses.back().getUser(); }
88 typedef value_use_iterator use_iterator;
89 typedef value_use_iterator use_const_iterator;
90
91 bool use_empty() const { return UseList == 0; }
92 use_iterator use_begin() { return use_iterator(UseList); }
93 use_const_iterator use_begin() const { return use_const_iterator(UseList); }
94 use_iterator use_end() { return use_iterator(0); }
95 use_const_iterator use_end() const { return use_const_iterator(0); }
96 User *use_back() { return *use_begin(); }
97 const User *use_back() const { return *use_begin(); }
10098
10199 /// hasOneUse - Return true if there is exactly one user of this value. This
102100 /// is specialized because it is a common request and does not require
103101 /// traversing the whole use list.
104102 ///
105103 bool hasOneUse() const {
106 iplist::const_iterator I = Uses.begin(), E = Uses.end();
104 use_const_iterator I = use_begin(), E = use_end();
107105 if (I == E) return false;
108106 return ++I == E;
109107 }
110108
109 /// hasNUses - Return true if this Value has exactly N users.
110 ///
111 bool hasNUses(unsigned N) const;
112
113 /// getNumUses - This method computes the number of uses of this Value. This
114 /// is a linear time operation. Use hasOneUse or hasNUses to check for
115 /// specific values.
116 unsigned getNumUses() const;
117
111118 /// addUse/killUse - These two methods should only be used by the Use class.
112119 ///
113 void addUse(Use &U) { Uses.push_back(&U); }
114 void killUse(Use &U) { Uses.remove(&U); }
120 void addUse(Use &U) { U.addToList(&UseList); }
115121
116122 /// getValueType - Return an ID for the concrete type of this object. This is
117123 /// used to implement the classof checks. This should not be used for any
156162 return OS;
157163 }
158164
159
160 inline User *UseListIteratorWrapper::operator*() const {
161 return Super::operator*().getUser();
162 }
163
164 inline const User *UseListConstIteratorWrapper::operator*() const {
165 return Super::operator*().getUser();
166 }
167
168
169165 void Use::init(Value *v, User *user) {
170166 Val = v;
171167 U = user;
173169 }
174170
175171 Use::~Use() {
176 if (Val) Val->killUse(*this);
172 if (Val) removeFromList();
177173 }
178174
179175 void Use::set(Value *V) {
180 if (Val) Val->killUse(*this);
176 if (Val) removeFromList();
181177 Val = V;
182178 if (V) V->addUse(*this);
183179 }