Move BB succ_iterator to be inside TerminatorInst. NFC.

To get the successors of a BB we currently do successors(BB) which
ultimately walks the successors of the BB's terminator.

This moves the iterator to TerminatorInst as thats what we're actually
using to do the iteration, and adds a member function to TerminatorInst
to allow us to iterate directly over successors given an instruction.

For example, we can now do

  for (auto *Succ : BI->successors())

instead of

  for (unsigned i = 0, e = BI->getNumSuccessors(); i != e; ++i)

Reviewed by Tobias Grosser.

llvm-svn: 244074
This commit is contained in:
Pete Cooper 2015-08-05 17:43:01 +00:00
parent dfcecdeeb2
commit 3ae0ee5453
3 changed files with 186 additions and 145 deletions

View File

@ -107,149 +107,13 @@ inline pred_const_range predecessors(const BasicBlock *BB) {
}
//===----------------------------------------------------------------------===//
// BasicBlock succ_iterator definition
// BasicBlock succ_iterator helpers
//===----------------------------------------------------------------------===//
template <class Term_, class BB_> // Successor Iterator
class SuccIterator : public std::iterator<std::random_access_iterator_tag, BB_,
int, BB_ *, BB_ *> {
typedef std::iterator<std::random_access_iterator_tag, BB_, int, BB_ *, BB_ *>
super;
public:
typedef typename super::pointer pointer;
typedef typename super::reference reference;
private:
Term_ Term;
unsigned idx;
typedef SuccIterator<Term_, BB_> Self;
inline bool index_is_valid(int idx) {
return idx >= 0 && (unsigned) idx < Term->getNumSuccessors();
}
/// \brief Proxy object to allow write access in operator[]
class SuccessorProxy {
Self it;
public:
explicit SuccessorProxy(const Self &it) : it(it) {}
SuccessorProxy(const SuccessorProxy&) = default;
SuccessorProxy &operator=(SuccessorProxy r) {
*this = reference(r);
return *this;
}
SuccessorProxy &operator=(reference r) {
it.Term->setSuccessor(it.idx, r);
return *this;
}
operator reference() const { return *it; }
};
public:
explicit inline SuccIterator(Term_ T) : Term(T), idx(0) {// begin iterator
}
inline SuccIterator(Term_ T, bool) // end iterator
: Term(T) {
if (Term)
idx = Term->getNumSuccessors();
else
// Term == NULL happens, if a basic block is not fully constructed and
// consequently getTerminator() returns NULL. In this case we construct a
// SuccIterator which describes a basic block that has zero successors.
// Defining SuccIterator for incomplete and malformed CFGs is especially
// useful for debugging.
idx = 0;
}
/// getSuccessorIndex - This is used to interface between code that wants to
/// operate on terminator instructions directly.
unsigned getSuccessorIndex() const { return idx; }
inline bool operator==(const Self& x) const { return idx == x.idx; }
inline bool operator!=(const Self& x) const { return !operator==(x); }
inline reference operator*() const { return Term->getSuccessor(idx); }
inline pointer operator->() const { return operator*(); }
inline Self& operator++() { ++idx; return *this; } // Preincrement
inline Self operator++(int) { // Postincrement
Self tmp = *this; ++*this; return tmp;
}
inline Self& operator--() { --idx; return *this; } // Predecrement
inline Self operator--(int) { // Postdecrement
Self tmp = *this; --*this; return tmp;
}
inline bool operator<(const Self& x) const {
assert(Term == x.Term && "Cannot compare iterators of different blocks!");
return idx < x.idx;
}
inline bool operator<=(const Self& x) const {
assert(Term == x.Term && "Cannot compare iterators of different blocks!");
return idx <= x.idx;
}
inline bool operator>=(const Self& x) const {
assert(Term == x.Term && "Cannot compare iterators of different blocks!");
return idx >= x.idx;
}
inline bool operator>(const Self& x) const {
assert(Term == x.Term && "Cannot compare iterators of different blocks!");
return idx > x.idx;
}
inline Self& operator+=(int Right) {
unsigned new_idx = idx + Right;
assert(index_is_valid(new_idx) && "Iterator index out of bound");
idx = new_idx;
return *this;
}
inline Self operator+(int Right) const {
Self tmp = *this;
tmp += Right;
return tmp;
}
inline Self& operator-=(int Right) {
return operator+=(-Right);
}
inline Self operator-(int Right) const {
return operator+(-Right);
}
inline int operator-(const Self& x) const {
assert(Term == x.Term && "Cannot work on iterators of different blocks!");
int distance = idx - x.idx;
return distance;
}
inline SuccessorProxy operator[](int offset) {
Self tmp = *this;
tmp += offset;
return SuccessorProxy(tmp);
}
/// Get the source BB of this iterator.
inline BB_ *getSource() {
assert(Term && "Source not available, if basic block was malformed");
return Term->getParent();
}
};
typedef SuccIterator<TerminatorInst*, BasicBlock> succ_iterator;
typedef SuccIterator<const TerminatorInst*,
const BasicBlock> succ_const_iterator;
typedef TerminatorInst::SuccIterator<TerminatorInst *, BasicBlock>
succ_iterator;
typedef TerminatorInst::SuccIterator<const TerminatorInst *, const BasicBlock>
succ_const_iterator;
typedef llvm::iterator_range<succ_iterator> succ_range;
typedef llvm::iterator_range<succ_const_iterator> succ_const_range;
@ -275,8 +139,8 @@ inline succ_const_range successors(const BasicBlock *BB) {
return succ_const_range(succ_begin(BB), succ_end(BB));
}
template <typename T, typename U> struct isPodLike<SuccIterator<T, U> > {
template <typename T, typename U>
struct isPodLike<TerminatorInst::SuccIterator<T, U>> {
static const bool value = isPodLike<T>::value;
};

View File

@ -91,6 +91,183 @@ public:
return false;
}
}
//===--------------------------------------------------------------------===//
// succ_iterator definition
//===--------------------------------------------------------------------===//
template <class Term, class BB> // Successor Iterator
class SuccIterator : public std::iterator<std::random_access_iterator_tag, BB,
int, BB *, BB *> {
typedef std::iterator<std::random_access_iterator_tag, BB, int, BB *, BB *>
super;
public:
typedef typename super::pointer pointer;
typedef typename super::reference reference;
private:
Term TermInst;
unsigned idx;
typedef SuccIterator<Term, BB> Self;
inline bool index_is_valid(unsigned idx) {
return idx >= 0 && idx < TermInst->getNumSuccessors();
}
/// \brief Proxy object to allow write access in operator[]
class SuccessorProxy {
Self it;
public:
explicit SuccessorProxy(const Self &it) : it(it) {}
SuccessorProxy(const SuccessorProxy &) = default;
SuccessorProxy &operator=(SuccessorProxy r) {
*this = reference(r);
return *this;
}
SuccessorProxy &operator=(reference r) {
it.TermInst->setSuccessor(it.idx, r);
return *this;
}
operator reference() const { return *it; }
};
public:
// begin iterator
explicit inline SuccIterator(Term T) : TermInst(T), idx(0) {}
// end iterator
inline SuccIterator(Term T, bool) : TermInst(T) {
if (TermInst)
idx = TermInst->getNumSuccessors();
else
// Term == NULL happens, if a basic block is not fully constructed and
// consequently getTerminator() returns NULL. In this case we construct
// a SuccIterator which describes a basic block that has zero
// successors.
// Defining SuccIterator for incomplete and malformed CFGs is especially
// useful for debugging.
idx = 0;
}
/// This is used to interface between code that wants to
/// operate on terminator instructions directly.
unsigned getSuccessorIndex() const { return idx; }
inline bool operator==(const Self &x) const { return idx == x.idx; }
inline bool operator!=(const Self &x) const { return !operator==(x); }
inline reference operator*() const { return TermInst->getSuccessor(idx); }
inline pointer operator->() const { return operator*(); }
inline Self &operator++() {
++idx;
return *this;
} // Preincrement
inline Self operator++(int) { // Postincrement
Self tmp = *this;
++*this;
return tmp;
}
inline Self &operator--() {
--idx;
return *this;
} // Predecrement
inline Self operator--(int) { // Postdecrement
Self tmp = *this;
--*this;
return tmp;
}
inline bool operator<(const Self &x) const {
assert(TermInst == x.TermInst &&
"Cannot compare iterators of different blocks!");
return idx < x.idx;
}
inline bool operator<=(const Self &x) const {
assert(TermInst == x.TermInst &&
"Cannot compare iterators of different blocks!");
return idx <= x.idx;
}
inline bool operator>=(const Self &x) const {
assert(TermInst == x.TermInst &&
"Cannot compare iterators of different blocks!");
return idx >= x.idx;
}
inline bool operator>(const Self &x) const {
assert(TermInst == x.TermInst &&
"Cannot compare iterators of different blocks!");
return idx > x.idx;
}
inline Self &operator+=(int Right) {
unsigned new_idx = idx + Right;
assert(index_is_valid(new_idx) && "Iterator index out of bound");
idx = new_idx;
return *this;
}
inline Self operator+(int Right) const {
Self tmp = *this;
tmp += Right;
return tmp;
}
inline Self &operator-=(int Right) { return operator+=(-Right); }
inline Self operator-(int Right) const { return operator+(-Right); }
inline int operator-(const Self &x) const {
assert(TermInst == x.TermInst &&
"Cannot work on iterators of different blocks!");
int distance = idx - x.idx;
return distance;
}
inline SuccessorProxy operator[](int offset) {
Self tmp = *this;
tmp += offset;
return SuccessorProxy(tmp);
}
/// Get the source BB of this iterator.
inline BB *getSource() {
assert(TermInst && "Source not available, if basic block was malformed");
return TermInst->getParent();
}
};
typedef SuccIterator<TerminatorInst *, BasicBlock> succ_iterator;
typedef SuccIterator<const TerminatorInst *, const BasicBlock>
succ_const_iterator;
typedef llvm::iterator_range<succ_iterator> succ_range;
typedef llvm::iterator_range<succ_const_iterator> succ_const_range;
private:
inline succ_iterator succ_begin() { return succ_iterator(this); }
inline succ_const_iterator succ_begin() const {
return succ_const_iterator(this);
}
inline succ_iterator succ_end() { return succ_iterator(this, true); }
inline succ_const_iterator succ_end() const {
return succ_const_iterator(this, true);
}
public:
inline succ_range successors() {
return succ_range(succ_begin(), succ_end());
}
inline succ_const_range successors() const {
return succ_const_range(succ_begin(), succ_end());
}
};

View File

@ -2447,8 +2447,8 @@ bool AArch64FastISel::selectIndirectBr(const Instruction *I) {
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II).addReg(AddrReg);
// Make sure the CFG is up-to-date.
for (unsigned i = 0, e = BI->getNumSuccessors(); i != e; ++i)
FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[BI->getSuccessor(i)]);
for (auto *Succ : BI->successors())
FuncInfo.MBB->addSuccessor(FuncInfo.MBBMap[Succ]);
return true;
}