std::vector<MachineBasicBlock *> Predecessors;
std::vector<MachineBasicBlock *> Successors;
-
/// Weights - Keep track of the weights to the successors. This vector
/// has the same order as Successors, or it is empty if we don't use it
/// (disable optimization).
/// target of an indirect branch.
bool AddressTaken;
+ /// \brief since getSymbol is a relatively heavy-weight operation, the symbol
+ /// is only computed once and is cached.
+ mutable MCSymbol *CachedMCSymbol;
+
// Intrusive list support
MachineBasicBlock() {}
template<class OtherTy, class OtherIterTy>
bundle_iterator(const bundle_iterator<OtherTy, OtherIterTy> &I)
: MII(I.getInstrIterator()) {}
- bundle_iterator() : MII(0) {}
+ bundle_iterator() : MII(nullptr) {}
Ty &operator*() const { return *MII; }
Ty *operator->() const { return &operator*(); }
unsigned size() const { return (unsigned)Insts.size(); }
bool empty() const { return Insts.empty(); }
- MachineInstr& front() { return Insts.front(); }
- MachineInstr& back() { return Insts.back(); }
- const MachineInstr& front() const { return Insts.front(); }
- const MachineInstr& back() const { return Insts.back(); }
+ MachineInstr &instr_front() { return Insts.front(); }
+ MachineInstr &instr_back() { return Insts.back(); }
+ const MachineInstr &instr_front() const { return Insts.front(); }
+ const MachineInstr &instr_back() const { return Insts.back(); }
+
+ MachineInstr &front() { return Insts.front(); }
+ MachineInstr &back() { return *--end(); }
+ const MachineInstr &front() const { return Insts.front(); }
+ const MachineInstr &back() const { return *--end(); }
instr_iterator instr_begin() { return Insts.begin(); }
const_instr_iterator instr_begin() const { return Insts.begin(); }
reverse_iterator rend () { return instr_rend(); }
const_reverse_iterator rend () const { return instr_rend(); }
+ inline iterator_range<iterator> terminators() {
+ return iterator_range<iterator>(getFirstTerminator(), end());
+ }
+ inline iterator_range<const_iterator> terminators() const {
+ return iterator_range<const_iterator>(getFirstTerminator(), end());
+ }
// Machine-CFG iterators
typedef std::vector<MachineBasicBlock *>::iterator pred_iterator;
succ_reverse_iterator;
typedef std::vector<MachineBasicBlock *>::const_reverse_iterator
const_succ_reverse_iterator;
-
pred_iterator pred_begin() { return Predecessors.begin(); }
const_pred_iterator pred_begin() const { return Predecessors.begin(); }
pred_iterator pred_end() { return Predecessors.end(); }
}
bool succ_empty() const { return Successors.empty(); }
+ inline iterator_range<pred_iterator> predecessors() {
+ return iterator_range<pred_iterator>(pred_begin(), pred_end());
+ }
+ inline iterator_range<const_pred_iterator> predecessors() const {
+ return iterator_range<const_pred_iterator>(pred_begin(), pred_end());
+ }
+ inline iterator_range<succ_iterator> successors() {
+ return iterator_range<succ_iterator>(succ_begin(), succ_end());
+ }
+ inline iterator_range<const_succ_iterator> successors() const {
+ return iterator_range<const_succ_iterator>(succ_begin(), succ_end());
+ }
+
// LiveIn management methods.
- /// addLiveIn - Add the specified register as a live in. Note that it
- /// is an error to add the same register to the same set more than once.
- void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); }
+ /// Adds the specified register as a live in. Note that it is an error to add
+ /// the same register to the same set more than once unless the intention is
+ /// to call sortUniqueLiveIns after all registers are added.
+ void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); }
+
+ /// Sorts and uniques the LiveIns vector. It can be significantly faster to do
+ /// this than repeatedly calling isLiveIn before calling addLiveIn for every
+ /// LiveIn insertion.
+ void sortUniqueLiveIns() {
+ std::sort(LiveIns.begin(), LiveIns.end());
+ LiveIns.erase(std::unique(LiveIns.begin(), LiveIns.end()), LiveIns.end());
+ }
+
+ /// Add PhysReg as live in to this block, and ensure that there is a copy of
+ /// PhysReg to a virtual register of class RC. Return the virtual register
+ /// that is a copy of the live in PhysReg.
+ unsigned addLiveIn(unsigned PhysReg, const TargetRegisterClass *RC);
/// removeLiveIn - Remove the specified register from the live in set.
///
///
void addSuccessor(MachineBasicBlock *succ, uint32_t weight = 0);
+ /// Set successor weight of a given iterator.
+ void setSuccWeight(succ_iterator I, uint32_t weight);
+
/// removeSuccessor - Remove successor from the successors list of this
/// MachineBasicBlock. The Predecessors list of succ is automatically updated.
///
/// branch to do so (e.g., a table jump). True is a conservative answer.
bool canFallThrough();
- /// Returns a pointer to the first instructon in this block that is not a
- /// PHINode instruction. When adding instruction to the beginning of the
+ /// Returns a pointer to the first instruction in this block that is not a
+ /// PHINode instruction. When adding instructions to the beginning of the
/// basic block, they should be added before the returned value, not before
/// the first instruction, which might be PHI.
/// Returns end() is there's no non-PHI instruction.
/// instruction of this basic block. If a terminator does not exist,
/// it returns end()
iterator getFirstTerminator();
- const_iterator getFirstTerminator() const;
+ const_iterator getFirstTerminator() const {
+ return const_cast<MachineBasicBlock *>(this)->getFirstTerminator();
+ }
/// getFirstInstrTerminator - Same getFirstTerminator but it ignores bundles
/// and return an instr_iterator instead.
/// getLastNonDebugInstr - returns an iterator to the last non-debug
/// instruction in the basic block, or end()
iterator getLastNonDebugInstr();
- const_iterator getLastNonDebugInstr() const;
+ const_iterator getLastNonDebugInstr() const {
+ return const_cast<MachineBasicBlock *>(this)->getLastNonDebugInstr();
+ }
/// SplitCriticalEdge - Split the critical edge from this block to the
/// given successor block, and return the newly created block, or null
/// Insert a range of instructions into the instruction list before I.
template<typename IT>
void insert(iterator I, IT S, IT E) {
+ assert((I == end() || I->getParent() == this) &&
+ "iterator points outside of basic block");
Insts.insert(I.getInstrIterator(), S, E);
}
/// Insert MI into the instruction list before I.
iterator insert(iterator I, MachineInstr *MI) {
+ assert((I == end() || I->getParent() == this) &&
+ "iterator points outside of basic block");
assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() &&
"Cannot insert instruction with bundle flags");
return Insts.insert(I.getInstrIterator(), MI);
/// Insert MI into the instruction list after I.
iterator insertAfter(iterator I, MachineInstr *MI) {
+ assert((I == end() || I->getParent() == this) &&
+ "iterator points outside of basic block");
assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() &&
"Cannot insert instruction with bundle flags");
return Insts.insertAfter(I.getInstrIterator(), MI);
///
/// If I points to a bundle of instructions, they are all erased.
iterator erase(iterator I) {
- return erase(I, llvm::next(I));
+ return erase(I, std::next(I));
}
/// Remove an instruction from the instruction list and delete it.
void splice(iterator Where, MachineBasicBlock *Other, iterator From) {
// The range splice() doesn't allow noop moves, but this one does.
if (Where != From)
- splice(Where, Other, From, llvm::next(From));
+ splice(Where, Other, From, std::next(From));
}
/// Take a block of instructions from MBB 'Other' in the range [From, To),
///< neighborhood.
};
- /// computeRegisterLiveness - Return whether (physical) register \c Reg
- /// has been <def>ined and not <kill>ed as of just before \c MI.
- ///
- /// Search is localised to a neighborhood of
- /// \c Neighborhood instructions before (searching for defs or kills) and
- /// Neighborhood instructions after (searching just for defs) MI.
+ /// Return whether (physical) register \p Reg has been <def>ined and not
+ /// <kill>ed as of just before \p Before.
+ ///
+ /// Search is localised to a neighborhood of \p Neighborhood instructions
+ /// before (searching for defs or kills) and \p Neighborhood instructions
+ /// after (searching just for defs) \p Before.
///
- /// \c Reg must be a physical register.
+ /// \p Reg must be a physical register.
LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI,
- unsigned Reg, MachineInstr *MI,
- unsigned Neighborhood=10);
+ unsigned Reg,
+ const_iterator Before,
+ unsigned Neighborhood=10) const;
// Debugging methods.
void dump() const;
- void print(raw_ostream &OS, SlotIndexes* = 0) const;
+ void print(raw_ostream &OS, SlotIndexes* = nullptr) const;
+
+ // Printing method used by LoopInfo.
+ void printAsOperand(raw_ostream &OS, bool PrintType = true) const;
/// getNumber - MachineBasicBlocks are uniquely numbered at the function
/// level, unless they're not in a MachineFunction yet, in which case this
raw_ostream& operator<<(raw_ostream &OS, const MachineBasicBlock &MBB);
-void WriteAsOperand(raw_ostream &, const MachineBasicBlock*, bool t);
-
// This is useful when building IndexedMaps keyed on basic block pointers.
struct MBB2NumberFunctor :
public std::unary_function<const MachineBasicBlock*, unsigned> {
}
};
+
+
+/// MachineInstrSpan provides an interface to get an iteration range
+/// containing the instruction it was initialized with, along with all
+/// those instructions inserted prior to or following that instruction
+/// at some point after the MachineInstrSpan is constructed.
+class MachineInstrSpan {
+ MachineBasicBlock &MBB;
+ MachineBasicBlock::iterator I, B, E;
+public:
+ MachineInstrSpan(MachineBasicBlock::iterator I)
+ : MBB(*I->getParent()),
+ I(I),
+ B(I == MBB.begin() ? MBB.end() : std::prev(I)),
+ E(std::next(I)) {}
+
+ MachineBasicBlock::iterator begin() {
+ return B == MBB.end() ? MBB.begin() : std::next(B);
+ }
+ MachineBasicBlock::iterator end() { return E; }
+ bool empty() { return begin() == end(); }
+
+ MachineBasicBlock::iterator getInitial() { return I; }
+};
+
} // End llvm namespace
#endif