llvm.org GIT mirror llvm / 627e0f9
[IR] Make SwitchInst::CaseIt almost a normal iterator. This moves it to the iterator facade utilities giving it full random access semantics, etc. It can also now be used with standard algorithms like std::all_of and std::any_of and range adaptors like llvm::reverse. Also make the semantics of iterating match what every other iterator uses and forbid decrementing past the begin iterator. This was used as a hacky way to work around iterator invalidation. However, every instance trying to do this failed to actually avoid touching invalid iterators despite the clear documentation that the removed and all subsequent iterators become invalid including the end iterator. So I've added a return of the next iterator to removeCase and rewritten the loops that were doing this to correctly follow the iterator pattern of either incremneting or removing and assigning fresh values to the iterator and the end. In one case we were trying to go backwards to make this cleaner but it doesn't actually work. I've made that code match the code we use everywhere else to remove cases as we iterate. This changes the order of cases in one test output and I moved that test to CHECK-DAG so it wouldn't care -- the order isn't semantically meaningful anyways. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298791 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 2 years ago
6 changed file(s) with 59 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
30933093 static const unsigned DefaultPseudoIndex = static_cast(~0L-1);
30943094
30953095 template
3096 class CaseIteratorT {
3096 class CaseIteratorT
3097 : public iterator_facade_base<
3098 CaseIteratorT,
3099 std::random_access_iterator_tag,
3100 CaseIteratorT> {
30973101 protected:
30983102 SwitchInstTy *SI;
3099 unsigned Index;
3103 ptrdiff_t Index;
31003104
31013105 public:
31023106 typedef CaseIteratorT Self;
3107
3108 /// Default constructed iterator is in an invalid state until assigned to
3109 /// a case for a particular switch.
3110 CaseIteratorT() : SI(nullptr) {}
31033111
31043112 /// Initializes case iterator for given SwitchInst and for given
31053113 /// case number.
31423150 return Index != DefaultPseudoIndex ? Index + 1 : 0;
31433151 }
31443152
3145 Self operator++() {
3146 // Check index correctness after increment.
3153 Self &operator+=(ptrdiff_t N) {
3154 // Check index correctness after addition.
31473155 // Note: Index == getNumCases() means end().
3148 assert(Index+1 <= SI->getNumCases() && "Index out the number of cases.");
3149 ++Index;
3156 assert(Index + N >= 0 && Index + N <= SI->getNumCases() &&
3157 "Index out the number of cases.");
3158 Index += N;
31503159 return *this;
31513160 }
3152 Self operator++(int) {
3153 Self tmp = *this;
3154 ++(*this);
3155 return tmp;
3156 }
3157 Self operator--() {
3158 // Check index correctness after decrement.
3161 Self &operator-=(ptrdiff_t N) {
3162 // Check index correctness after subtraction.
31593163 // Note: Index == getNumCases() means end().
3160 // Also allow "-1" iterator here. That will became valid after ++.
3161 assert((Index == 0 || Index-1 <= SI->getNumCases()) &&
3164 assert(Index - N >= 0 && Index - N <= SI->getNumCases() &&
31623165 "Index out the number of cases.");
3163 --Index;
3166 Index -= N;
31643167 return *this;
31653168 }
3166 Self operator--(int) {
3167 Self tmp = *this;
3168 --(*this);
3169 return tmp;
3169 bool operator==(const Self& RHS) const {
3170 assert(SI == RHS.SI && "Incompatible operators.");
3171 return Index == RHS.Index;
31703172 }
3171 bool operator==(const Self& RHS) const {
3172 assert(RHS.SI == SI && "Incompatible operators.");
3173 return RHS.Index == Index;
3173 bool operator<(const Self& RHS) const {
3174 assert(SI == RHS.SI && "Incompatible operators.");
3175 return Index < RHS.Index;
31743176 }
3175 bool operator!=(const Self& RHS) const {
3176 assert(RHS.SI == SI && "Incompatible operators.");
3177 return RHS.Index != Index;
3178 }
3179 Self &operator*() {
3180 return *this;
3181 }
3177 Self &operator*() { return *this; }
3178 const Self &operator*() const { return *this; }
31823179 };
31833180
31843181 typedef CaseIteratorT
33243321 /// index idx and above.
33253322 /// Note:
33263323 /// This action invalidates iterators for all cases following the one removed,
3327 /// including the case_end() iterator.
3328 void removeCase(CaseIt i);
3324 /// including the case_end() iterator. It returns an iterator for the next
3325 /// case.
3326 CaseIt removeCase(CaseIt i);
33293327
33303328 unsigned getNumSuccessors() const { return getNumOperands()/2; }
33313329 BasicBlock *getSuccessor(unsigned idx) const {
36613661
36623662 /// removeCase - This method removes the specified case and its successor
36633663 /// from the switch instruction.
3664 void SwitchInst::removeCase(CaseIt i) {
3664 SwitchInst::CaseIt SwitchInst::removeCase(CaseIt i) {
36653665 unsigned idx = i.getCaseIndex();
36663666
36673667 assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!");
36793679 OL[NumOps-2].set(nullptr);
36803680 OL[NumOps-2+1].set(nullptr);
36813681 setNumHungOffUseOperands(NumOps-2);
3682
3683 return CaseIt(this, idx);
36823684 }
36833685
36843686 /// growOperands - grow operands - This grows the operand list in response
234234 // Analyse each switch case in turn. This is done in reverse order so that
235235 // removing a case doesn't cause trouble for the iteration.
236236 bool Changed = false;
237 for (SwitchInst::CaseIt CI = SI->case_end(), CE = SI->case_begin(); CI-- != CE;
238 ) {
237 for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
239238 ConstantInt *Case = CI.getCaseValue();
240239
241240 // Check to see if the switch condition is equal to/not equal to the case
270269 if (State == LazyValueInfo::False) {
271270 // This case never fires - remove it.
272271 CI.getCaseSuccessor()->removePredecessor(BB);
273 SI->removeCase(CI); // Does not invalidate the iterator.
272 CI = SI->removeCase(CI);
273 CE = SI->case_end();
274274
275275 // The condition can be modified by removePredecessor's PHI simplification
276276 // logic.
278278
279279 ++NumDeadCases;
280280 Changed = true;
281 } else if (State == LazyValueInfo::True) {
281 continue;
282 }
283 if (State == LazyValueInfo::True) {
282284 // This case always fires. Arrange for the switch to be turned into an
283285 // unconditional branch by replacing the switch condition with the case
284286 // value.
287289 Changed = true;
288290 break;
289291 }
292
293 // Increment the case iterator sense we didn't delete it.
294 ++CI;
290295 }
291296
292297 if (Changed)
129129 }
130130
131131 // Figure out which case it goes to.
132 for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end();
133 i != e; ++i) {
132 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
134133 // Found case matching a constant operand?
135134 if (i.getCaseValue() == CI) {
136135 TheOnlyDest = i.getCaseSuccessor();
164163 }
165164 // Remove this entry.
166165 DefaultDest->removePredecessor(SI->getParent());
167 SI->removeCase(i);
168 --i; --e;
166 i = SI->removeCase(i);
167 e = SI->case_end();
169168 continue;
170169 }
171170
173172 // We do this by reseting "TheOnlyDest" to null when we find two non-equal
174173 // destinations.
175174 if (i.getCaseSuccessor() != TheOnlyDest) TheOnlyDest = nullptr;
175
176 // Increment this iterator as we haven't removed the case.
177 ++i;
176178 }
177179
178180 if (CI && !TheOnlyDest) {
41554155 }
41564156 }
41574157 } else if (auto *SI = dyn_cast(TI)) {
4158 for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e;
4159 ++i)
4160 if (i.getCaseSuccessor() == BB) {
4161 BB->removePredecessor(SI->getParent());
4162 SI->removeCase(i);
4163 --i;
4164 --e;
4165 Changed = true;
4158 for (auto i = SI->case_begin(), e = SI->case_end(); i != e;) {
4159 if (i.getCaseSuccessor() != BB) {
4160 ++i;
4161 continue;
41664162 }
4163 BB->removePredecessor(SI->getParent());
4164 i = SI->removeCase(i);
4165 e = SI->case_end();
4166 Changed = true;
4167 }
41674168 } else if (auto *II = dyn_cast(TI)) {
41684169 if (II->getUnwindDest() == BB) {
41694170 removeUnwindEdge(TI->getParent());
114114 i32 1, label %out
115115 ; CHECK-NOT: i32 1
116116 i32 -1, label %next
117 ; CHECK: i32 -1, label %next
117 ; CHECK-DAG: i32 -1, label %next
118118 i32 -2, label %next
119 ; CHECK: i32 -2, label %next
119 ; CHECK-DAG: i32 -2, label %next
120120 i32 2, label %out
121121 ; CHECK-NOT: i32 2
122122 i32 3, label %out