mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
Phase 1 of refactoring the MachineRegisterInfo iterators to make them suitable
for use with C++11 range-based for-loops. The gist of phase 1 is to remove the skipInstruction() and skipBundle() methods from these iterators, instead splitting each iterator into a version that walks operands, a version that walks instructions, and a version that walks bundles. This has the result of making some "clever" loops in lib/CodeGen more verbose, but also makes their iterator invalidation characteristics much more obvious to the casual reader. (Making them concise again in the future is a good motivating case for a pre-incrementing range adapter!) Phase 2 of this undertaking with consist of removing the getOperand() method, and changing operator*() of the operand-walker to return a MachineOperand&. At that point, it should be possible to add range views for them that work as one might expect. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203757 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -200,32 +200,78 @@ public:
|
||||
/// reg_begin/reg_end - Provide iteration support to walk over all definitions
|
||||
/// and uses of a register within the MachineFunction that corresponds to this
|
||||
/// MachineRegisterInfo object.
|
||||
template<bool Uses, bool Defs, bool SkipDebug>
|
||||
template<bool Uses, bool Defs, bool SkipDebug,
|
||||
bool ByOperand, bool ByInstr, bool ByBundle>
|
||||
class defusechain_iterator;
|
||||
|
||||
// Make it a friend so it can access getNextOperandForReg().
|
||||
template<bool, bool, bool> friend class defusechain_iterator;
|
||||
template<bool, bool, bool, bool, bool, bool>
|
||||
friend class defusechain_iterator;
|
||||
|
||||
/// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified
|
||||
/// register.
|
||||
typedef defusechain_iterator<true,true,false> reg_iterator;
|
||||
typedef defusechain_iterator<true,true,false,true,false,false>
|
||||
reg_iterator;
|
||||
reg_iterator reg_begin(unsigned RegNo) const {
|
||||
return reg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static reg_iterator reg_end() { return reg_iterator(0); }
|
||||
|
||||
/// reg_instr_iterator/reg_instr_begin/reg_instr_end - Walk all defs and uses
|
||||
/// of the specified register, stepping by MachineInstr.
|
||||
typedef defusechain_iterator<true,true,false,false,true,false>
|
||||
reg_instr_iterator;
|
||||
reg_instr_iterator reg_instr_begin(unsigned RegNo) const {
|
||||
return reg_instr_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static reg_instr_iterator reg_instr_end() { return reg_instr_iterator(0); }
|
||||
|
||||
/// reg_bundle_iterator/reg_bundle_begin/reg_bundle_end - Walk all defs and uses
|
||||
/// of the specified register, stepping by bundle.
|
||||
typedef defusechain_iterator<true,true,false,false,false,true>
|
||||
reg_bundle_iterator;
|
||||
reg_bundle_iterator reg_bundle_begin(unsigned RegNo) const {
|
||||
return reg_bundle_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static reg_bundle_iterator reg_bundle_end() { return reg_bundle_iterator(0); }
|
||||
|
||||
/// reg_empty - Return true if there are no instructions using or defining the
|
||||
/// specified register (it may be live-in).
|
||||
bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); }
|
||||
|
||||
/// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses
|
||||
/// of the specified register, skipping those marked as Debug.
|
||||
typedef defusechain_iterator<true,true,true> reg_nodbg_iterator;
|
||||
typedef defusechain_iterator<true,true,true,true,false,false>
|
||||
reg_nodbg_iterator;
|
||||
reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const {
|
||||
return reg_nodbg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static reg_nodbg_iterator reg_nodbg_end() { return reg_nodbg_iterator(0); }
|
||||
|
||||
/// reg_instr_nodbg_iterator/reg_instr_nodbg_begin/reg_instr_nodbg_end - Walk
|
||||
/// all defs and uses of the specified register, stepping by MachineInstr,
|
||||
/// skipping those marked as Debug.
|
||||
typedef defusechain_iterator<true,true,true,false,true,false>
|
||||
reg_instr_nodbg_iterator;
|
||||
reg_instr_nodbg_iterator reg_instr_nodbg_begin(unsigned RegNo) const {
|
||||
return reg_instr_nodbg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static reg_instr_nodbg_iterator reg_instr_nodbg_end() {
|
||||
return reg_instr_nodbg_iterator(0);
|
||||
}
|
||||
|
||||
/// reg_bundle_nodbg_iterator/reg_bundle_nodbg_begin/reg_bundle_nodbg_end - Walk
|
||||
/// all defs and uses of the specified register, stepping by bundle,
|
||||
/// skipping those marked as Debug.
|
||||
typedef defusechain_iterator<true,true,true,false,false,true>
|
||||
reg_bundle_nodbg_iterator;
|
||||
reg_bundle_nodbg_iterator reg_bundle_nodbg_begin(unsigned RegNo) const {
|
||||
return reg_bundle_nodbg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static reg_bundle_nodbg_iterator reg_bundle_nodbg_end() {
|
||||
return reg_bundle_nodbg_iterator(0);
|
||||
}
|
||||
|
||||
/// reg_nodbg_empty - Return true if the only instructions using or defining
|
||||
/// Reg are Debug instructions.
|
||||
bool reg_nodbg_empty(unsigned RegNo) const {
|
||||
@@ -233,12 +279,31 @@ public:
|
||||
}
|
||||
|
||||
/// def_iterator/def_begin/def_end - Walk all defs of the specified register.
|
||||
typedef defusechain_iterator<false,true,false> def_iterator;
|
||||
typedef defusechain_iterator<false,true,false,true,false,false>
|
||||
def_iterator;
|
||||
def_iterator def_begin(unsigned RegNo) const {
|
||||
return def_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static def_iterator def_end() { return def_iterator(0); }
|
||||
|
||||
/// def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the
|
||||
/// specified register, stepping by MachineInst.
|
||||
typedef defusechain_iterator<false,true,false,false,true,false>
|
||||
def_instr_iterator;
|
||||
def_instr_iterator def_instr_begin(unsigned RegNo) const {
|
||||
return def_instr_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static def_instr_iterator def_instr_end() { return def_instr_iterator(0); }
|
||||
|
||||
/// def_bundle_iterator/def_bundle_begin/def_bundle_end - Walk all defs of the
|
||||
/// specified register, stepping by bundle.
|
||||
typedef defusechain_iterator<false,true,false,false,false,true>
|
||||
def_bundle_iterator;
|
||||
def_bundle_iterator def_bundle_begin(unsigned RegNo) const {
|
||||
return def_bundle_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static def_bundle_iterator def_bundle_end() { return def_bundle_iterator(0); }
|
||||
|
||||
/// def_empty - Return true if there are no instructions defining the
|
||||
/// specified register (it may be live-in).
|
||||
bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); }
|
||||
@@ -253,12 +318,31 @@ public:
|
||||
}
|
||||
|
||||
/// use_iterator/use_begin/use_end - Walk all uses of the specified register.
|
||||
typedef defusechain_iterator<true,false,false> use_iterator;
|
||||
typedef defusechain_iterator<true,false,false,true,false,false>
|
||||
use_iterator;
|
||||
use_iterator use_begin(unsigned RegNo) const {
|
||||
return use_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static use_iterator use_end() { return use_iterator(0); }
|
||||
|
||||
/// use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the
|
||||
/// specified register, stepping by MachineInstr.
|
||||
typedef defusechain_iterator<true,false,false,false,true,false>
|
||||
use_instr_iterator;
|
||||
use_instr_iterator use_instr_begin(unsigned RegNo) const {
|
||||
return use_instr_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static use_instr_iterator use_instr_end() { return use_instr_iterator(0); }
|
||||
|
||||
/// use_bundle_iterator/use_bundle_begin/use_bundle_end - Walk all uses of the
|
||||
/// specified register, stepping by bundle.
|
||||
typedef defusechain_iterator<true,false,false,false,false,true>
|
||||
use_bundle_iterator;
|
||||
use_bundle_iterator use_bundle_begin(unsigned RegNo) const {
|
||||
return use_bundle_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static use_bundle_iterator use_bundle_end() { return use_bundle_iterator(0); }
|
||||
|
||||
/// use_empty - Return true if there are no instructions using the specified
|
||||
/// register.
|
||||
bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); }
|
||||
@@ -274,12 +358,37 @@ public:
|
||||
|
||||
/// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the
|
||||
/// specified register, skipping those marked as Debug.
|
||||
typedef defusechain_iterator<true,false,true> use_nodbg_iterator;
|
||||
typedef defusechain_iterator<true,false,true,true,false,false>
|
||||
use_nodbg_iterator;
|
||||
use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const {
|
||||
return use_nodbg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static use_nodbg_iterator use_nodbg_end() { return use_nodbg_iterator(0); }
|
||||
|
||||
/// use_instr_nodbg_iterator/use_instr_nodbg_begin/use_instr_nodbg_end - Walk
|
||||
/// all uses of the specified register, stepping by MachineInstr, skipping
|
||||
/// those marked as Debug.
|
||||
typedef defusechain_iterator<true,false,true,false,true,false>
|
||||
use_instr_nodbg_iterator;
|
||||
use_instr_nodbg_iterator use_instr_nodbg_begin(unsigned RegNo) const {
|
||||
return use_instr_nodbg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static use_instr_nodbg_iterator use_instr_nodbg_end() {
|
||||
return use_instr_nodbg_iterator(0);
|
||||
}
|
||||
|
||||
/// use_bundle_nodbg_iterator/use_bundle_nodbg_begin/use_bundle_nodbg_end - Walk
|
||||
/// all uses of the specified register, stepping by bundle, skipping
|
||||
/// those marked as Debug.
|
||||
typedef defusechain_iterator<true,false,true,false,false,true>
|
||||
use_bundle_nodbg_iterator;
|
||||
use_bundle_nodbg_iterator use_bundle_nodbg_begin(unsigned RegNo) const {
|
||||
return use_bundle_nodbg_iterator(getRegUseDefListHead(RegNo));
|
||||
}
|
||||
static use_bundle_nodbg_iterator use_bundle_nodbg_end() {
|
||||
return use_bundle_nodbg_iterator(0);
|
||||
}
|
||||
|
||||
/// use_nodbg_empty - Return true if there are no non-Debug instructions
|
||||
/// using the specified register.
|
||||
bool use_nodbg_empty(unsigned RegNo) const {
|
||||
@@ -552,7 +661,8 @@ public:
|
||||
/// returns defs. If neither are true then you are silly and it always
|
||||
/// returns end(). If SkipDebug is true it skips uses marked Debug
|
||||
/// when incrementing.
|
||||
template<bool ReturnUses, bool ReturnDefs, bool SkipDebug>
|
||||
template<bool ReturnUses, bool ReturnDefs, bool SkipDebug,
|
||||
bool ByOperand, bool ByInstr, bool ByBundle>
|
||||
class defusechain_iterator
|
||||
: public std::iterator<std::forward_iterator_tag, MachineInstr, ptrdiff_t> {
|
||||
MachineOperand *Op;
|
||||
@@ -567,6 +677,26 @@ public:
|
||||
}
|
||||
}
|
||||
friend class MachineRegisterInfo;
|
||||
|
||||
void advance() {
|
||||
assert(Op && "Cannot increment end iterator!");
|
||||
Op = getNextOperandForReg(Op);
|
||||
|
||||
// All defs come before the uses, so stop def_iterator early.
|
||||
if (!ReturnUses) {
|
||||
if (Op) {
|
||||
if (Op->isUse())
|
||||
Op = 0;
|
||||
else
|
||||
assert(!Op->isDebug() && "Can't have debug defs");
|
||||
}
|
||||
} else {
|
||||
// If this is an operand we don't care about, skip it.
|
||||
while (Op && ((!ReturnDefs && Op->isDef()) ||
|
||||
(SkipDebug && Op->isDebug())))
|
||||
Op = getNextOperandForReg(Op);
|
||||
}
|
||||
}
|
||||
public:
|
||||
typedef std::iterator<std::forward_iterator_tag,
|
||||
MachineInstr, ptrdiff_t>::reference reference;
|
||||
@@ -589,21 +719,18 @@ public:
|
||||
// Iterator traversal: forward iteration only
|
||||
defusechain_iterator &operator++() { // Preincrement
|
||||
assert(Op && "Cannot increment end iterator!");
|
||||
Op = getNextOperandForReg(Op);
|
||||
|
||||
// All defs come before the uses, so stop def_iterator early.
|
||||
if (!ReturnUses) {
|
||||
if (Op) {
|
||||
if (Op->isUse())
|
||||
Op = 0;
|
||||
else
|
||||
assert(!Op->isDebug() && "Can't have debug defs");
|
||||
}
|
||||
} else {
|
||||
// If this is an operand we don't care about, skip it.
|
||||
while (Op && ((!ReturnDefs && Op->isDef()) ||
|
||||
(SkipDebug && Op->isDebug())))
|
||||
Op = getNextOperandForReg(Op);
|
||||
if (ByOperand)
|
||||
advance();
|
||||
else if (ByInstr) {
|
||||
MachineInstr *P = Op->getParent();
|
||||
do {
|
||||
advance();
|
||||
} while (Op && Op->getParent() == P);
|
||||
} else if (ByBundle) {
|
||||
MachineInstr *P = getBundleStart(Op->getParent());
|
||||
do {
|
||||
advance();
|
||||
} while (Op && getBundleStart(Op->getParent()) == P);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -612,25 +739,6 @@ public:
|
||||
defusechain_iterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
/// skipInstruction - move forward until reaching a different instruction.
|
||||
/// Return the skipped instruction that is no longer pointed to, or NULL if
|
||||
/// already pointing to end().
|
||||
MachineInstr *skipInstruction() {
|
||||
if (!Op) return 0;
|
||||
MachineInstr *MI = Op->getParent();
|
||||
do ++*this;
|
||||
while (Op && Op->getParent() == MI);
|
||||
return MI;
|
||||
}
|
||||
|
||||
MachineInstr *skipBundle() {
|
||||
if (!Op) return 0;
|
||||
MachineInstr *MI = getBundleStart(Op->getParent());
|
||||
do ++*this;
|
||||
while (Op && getBundleStart(Op->getParent()) == MI);
|
||||
return MI;
|
||||
}
|
||||
|
||||
MachineOperand &getOperand() const {
|
||||
assert(Op && "Cannot dereference end iterator!");
|
||||
return *Op;
|
||||
|
Reference in New Issue
Block a user