X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FMachineBasicBlock.h;h=fd786f68fb653b240015fd7cb58d351470dc50f6;hp=1138f92bf865c165a3c0e43cd9935797b10e0f84;hb=20a42bb20d43b80e322c95dd99b64a5a4566fe08;hpb=62c4d9799fa592ae4073d633802013d3aaf08d71 diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 1138f92bf86..fd786f68fb6 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -14,8 +14,10 @@ #ifndef LLVM_CODEGEN_MACHINEBASICBLOCK_H #define LLVM_CODEGEN_MACHINEBASICBLOCK_H -#include "llvm/CodeGen/MachineInstr.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/DataTypes.h" #include @@ -25,11 +27,15 @@ class Pass; class BasicBlock; class MachineFunction; class MCSymbol; +class MIPrinter; class SlotIndexes; class StringRef; class raw_ostream; class MachineBranchProbabilityInfo; +// Forward declaration to avoid circular include problem with TargetRegisterInfo +typedef unsigned LaneBitmask; + template <> struct ilist_traits : public ilist_default_traits { private: @@ -52,54 +58,80 @@ public: void addNodeToList(MachineInstr* N); void removeNodeFromList(MachineInstr* N); void transferNodesFromList(ilist_traits &SrcTraits, - ilist_iterator first, - ilist_iterator last); + ilist_iterator First, + ilist_iterator Last); void deleteNode(MachineInstr *N); private: void createNode(const MachineInstr &); }; -class MachineBasicBlock : public ilist_node { +class MachineBasicBlock + : public ilist_node_with_parent { +public: + /// Pair of physical register and lane mask. + /// This is not simply a std::pair typedef because the members should be named + /// clearly as they both have an integer type. + struct RegisterMaskPair { + public: + MCPhysReg PhysReg; + LaneBitmask LaneMask; + + RegisterMaskPair(MCPhysReg PhysReg, LaneBitmask LaneMask) + : PhysReg(PhysReg), LaneMask(LaneMask) {} + }; + +private: typedef ilist Instructions; Instructions Insts; const BasicBlock *BB; int Number; MachineFunction *xParent; - /// Predecessors/Successors - Keep track of the predecessor / successor - /// basicblocks. + /// Keep track of the predecessor / successor basic blocks. std::vector Predecessors; std::vector Successors; + /// Keep track of the probabilities to the successors. This vector has the + /// same order as Successors, or it is empty if we don't use it (disable + /// optimization). + std::vector Probs; + typedef std::vector::iterator probability_iterator; + typedef std::vector::const_iterator + const_probability_iterator; + + /// Keep track of the physical registers that are livein of the basicblock. + typedef std::vector LiveInVector; + LiveInVector LiveIns; + + /// Alignment of the basic block. Zero if the basic block does not need to be + /// aligned. The alignment is specified as log2(bytes). + unsigned Alignment = 0; + + /// Indicate that this basic block is entered via an exception handler. + bool IsEHPad = false; - /// 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). - std::vector Weights; - typedef std::vector::iterator weight_iterator; - typedef std::vector::const_iterator const_weight_iterator; + /// Indicate that this basic block is potentially the target of an indirect + /// branch. + bool AddressTaken = false; - /// LiveIns - Keep track of the physical registers that are livein of - /// the basicblock. - std::vector LiveIns; + /// Indicate that this basic block is the entry block of an EH funclet. + bool IsEHFuncletEntry = false; - /// Alignment - Alignment of the basic block. Zero if the basic block does - /// not need to be aligned. - /// The alignment is specified as log2(bytes). - unsigned Alignment; + /// Indicate that this basic block is the entry block of a cleanup funclet. + bool IsCleanupFuncletEntry = false; - /// IsLandingPad - Indicate that this basic block is entered via an - /// exception handler. - bool IsLandingPad; + /// \brief since getSymbol is a relatively heavy-weight operation, the symbol + /// is only computed once and is cached. + mutable MCSymbol *CachedMCSymbol = nullptr; - /// AddressTaken - Indicate that this basic block is potentially the - /// target of an indirect branch. - bool AddressTaken; + // XXX-update: A flag that checks whether we can eliminate this machine basic + // block. + bool canEliminateMachineBB; // Intrusive list support MachineBasicBlock() {} - explicit MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb); + explicit MachineBasicBlock(MachineFunction &MF, const BasicBlock *BB); ~MachineBasicBlock(); @@ -107,91 +139,93 @@ class MachineBasicBlock : public ilist_node { friend class MachineFunction; public: - /// getBasicBlock - Return the LLVM basic block that this instance - /// corresponded to originally. Note that this may be NULL if this instance - /// does not correspond directly to an LLVM basic block. - /// + // XXX-update: + void disableCanEliminateMachineBB() { + canEliminateMachineBB = false; + } + + bool getCanEliminateMachineBB() { + return canEliminateMachineBB; + } + + /// Return the LLVM basic block that this instance corresponded to originally. + /// Note that this may be NULL if this instance does not correspond directly + /// to an LLVM basic block. const BasicBlock *getBasicBlock() const { return BB; } - /// getName - Return the name of the corresponding LLVM basic block, or - /// "(null)". + /// Return the name of the corresponding LLVM basic block, or "(null)". StringRef getName() const; - /// hasAddressTaken - Test whether this block is potentially the target - /// of an indirect branch. + /// Return a formatted string to identify this block and its parent function. + std::string getFullName() const; + + /// Test whether this block is potentially the target of an indirect branch. bool hasAddressTaken() const { return AddressTaken; } - /// setHasAddressTaken - Set this block to reflect that it potentially - /// is the target of an indirect branch. + /// Set this block to reflect that it potentially is the target of an indirect + /// branch. void setHasAddressTaken() { AddressTaken = true; } - /// getParent - Return the MachineFunction containing this basic block. - /// + /// Return the MachineFunction containing this basic block. const MachineFunction *getParent() const { return xParent; } MachineFunction *getParent() { return xParent; } - - /// bundle_iterator - MachineBasicBlock iterator that automatically skips over - /// MIs that are inside bundles (i.e. walk top level MIs only). + /// MachineBasicBlock iterator that automatically skips over MIs that are + /// inside bundles (i.e. walk top level MIs only). template class bundle_iterator : public std::iterator { IterTy MII; public: - bundle_iterator(IterTy mii) : MII(mii) { - assert(!MII->isInsideBundle() && - "It's not legal to initialize bundle_iterator with a bundled MI"); - } + bundle_iterator(IterTy MI) : MII(MI) {} - bundle_iterator(Ty &mi) : MII(mi) { - assert(!mi.isInsideBundle() && + bundle_iterator(Ty &MI) : MII(MI) { + assert(!MI.isBundledWithPred() && "It's not legal to initialize bundle_iterator with a bundled MI"); } - bundle_iterator(Ty *mi) : MII(mi) { - assert((!mi || !mi->isInsideBundle()) && + bundle_iterator(Ty *MI) : MII(MI) { + assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize bundle_iterator with a bundled MI"); } - bundle_iterator(const bundle_iterator &I) : MII(I.MII) {} - bundle_iterator() : MII(0) {} + // Template allows conversion from const to nonconst. + template + bundle_iterator(const bundle_iterator &I) + : MII(I.getInstrIterator()) {} + bundle_iterator() : MII(nullptr) {} Ty &operator*() const { return *MII; } Ty *operator->() const { return &operator*(); } - operator Ty*() const { return MII; } + operator Ty *() const { return MII.getNodePtrUnchecked(); } - bool operator==(const bundle_iterator &x) const { - return MII == x.MII; + bool operator==(const bundle_iterator &X) const { + return MII == X.MII; } - bool operator!=(const bundle_iterator &x) const { - return !operator==(x); + bool operator!=(const bundle_iterator &X) const { + return !operator==(X); } // Increment and decrement operators... bundle_iterator &operator--() { // predecrement - Back up - do { - --MII; - } while (MII->isInsideBundle()); + do --MII; + while (MII->isBundledWithPred()); return *this; } bundle_iterator &operator++() { // preincrement - Advance - do { + while (MII->isBundledWithSucc()) ++MII; - } while (MII->isInsideBundle()); + ++MII; return *this; } bundle_iterator operator--(int) { // postdecrement operators... bundle_iterator tmp = *this; - do { - --MII; - } while (MII->isInsideBundle()); + --*this; return tmp; } bundle_iterator operator++(int) { // postincrement operators... bundle_iterator tmp = *this; - do { - ++MII; - } while (MII->isInsideBundle()); + ++*this; return tmp; } @@ -217,10 +251,15 @@ public: 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(); } @@ -231,43 +270,26 @@ public: reverse_instr_iterator instr_rend () { return Insts.rend(); } const_reverse_instr_iterator instr_rend () const { return Insts.rend(); } - iterator begin() { return Insts.begin(); } - const_iterator begin() const { return Insts.begin(); } - iterator end() { - instr_iterator II = instr_end(); - if (II != instr_begin()) { - while (II->isInsideBundle()) - --II; - } - return II; - } - const_iterator end() const { - const_instr_iterator II = instr_end(); - if (II != instr_begin()) { - while (II->isInsideBundle()) - --II; - } - return II; + iterator begin() { return instr_begin(); } + const_iterator begin() const { return instr_begin(); } + iterator end () { return instr_end(); } + const_iterator end () const { return instr_end(); } + reverse_iterator rbegin() { return instr_rbegin(); } + const_reverse_iterator rbegin() const { return instr_rbegin(); } + reverse_iterator rend () { return instr_rend(); } + const_reverse_iterator rend () const { return instr_rend(); } + + /// Support for MachineInstr::getNextNode(). + static Instructions MachineBasicBlock::*getSublistAccess(MachineInstr *) { + return &MachineBasicBlock::Insts; } - reverse_iterator rbegin() { - reverse_instr_iterator II = instr_rbegin(); - if (II != instr_rend()) { - while (II->isInsideBundle()) - ++II; - } - return II; + + inline iterator_range terminators() { + return make_range(getFirstTerminator(), end()); } - const_reverse_iterator rbegin() const { - const_reverse_instr_iterator II = instr_rbegin(); - if (II != instr_rend()) { - while (II->isInsideBundle()) - ++II; - } - return II; + inline iterator_range terminators() const { + return make_range(getFirstTerminator(), end()); } - reverse_iterator rend () { return Insts.rend(); } - const_reverse_iterator rend () const { return Insts.rend(); } - // Machine-CFG iterators typedef std::vector::iterator pred_iterator; @@ -282,7 +304,6 @@ public: succ_reverse_iterator; typedef std::vector::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(); } @@ -316,145 +337,242 @@ public: } bool succ_empty() const { return Successors.empty(); } + inline iterator_range predecessors() { + return make_range(pred_begin(), pred_end()); + } + inline iterator_range predecessors() const { + return make_range(pred_begin(), pred_end()); + } + inline iterator_range successors() { + return make_range(succ_begin(), succ_end()); + } + inline iterator_range successors() const { + return make_range(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(MCPhysReg PhysReg, LaneBitmask LaneMask = ~0u) { + LiveIns.push_back(RegisterMaskPair(PhysReg, LaneMask)); + } + void addLiveIn(const RegisterMaskPair &RegMaskPair) { + LiveIns.push_back(RegMaskPair); + } - /// removeLiveIn - Remove the specified register from the live in set. - /// - void removeLiveIn(unsigned 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(); - /// isLiveIn - Return true if the specified register is in the live in set. - /// - bool isLiveIn(unsigned Reg) const; + /// 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(MCPhysReg PhysReg, const TargetRegisterClass *RC); + + /// Remove the specified register from the live in set. + void removeLiveIn(MCPhysReg Reg, LaneBitmask LaneMask = ~0u); + + /// Return true if the specified register is in the live in set. + bool isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask = ~0u) const; // Iteration support for live in sets. These sets are kept in sorted // order by their register number. - typedef std::vector::const_iterator livein_iterator; + typedef LiveInVector::const_iterator livein_iterator; livein_iterator livein_begin() const { return LiveIns.begin(); } livein_iterator livein_end() const { return LiveIns.end(); } bool livein_empty() const { return LiveIns.empty(); } + iterator_range liveins() const { + return make_range(livein_begin(), livein_end()); + } - /// getAlignment - Return alignment of the basic block. - /// The alignment is specified as log2(bytes). - /// + /// Get the clobber mask for the start of this basic block. Funclets use this + /// to prevent register allocation across funclet transitions. + const uint32_t *getBeginClobberMask(const TargetRegisterInfo *TRI) const; + + /// Get the clobber mask for the end of the basic block. + /// \see getBeginClobberMask() + const uint32_t *getEndClobberMask(const TargetRegisterInfo *TRI) const; + + /// Return alignment of the basic block. The alignment is specified as + /// log2(bytes). unsigned getAlignment() const { return Alignment; } - /// setAlignment - Set alignment of the basic block. - /// The alignment is specified as log2(bytes). - /// + /// Set alignment of the basic block. The alignment is specified as + /// log2(bytes). void setAlignment(unsigned Align) { Alignment = Align; } - /// isLandingPad - Returns true if the block is a landing pad. That is - /// this basic block is entered via an exception handler. - bool isLandingPad() const { return IsLandingPad; } + /// Returns true if the block is a landing pad. That is this basic block is + /// entered via an exception handler. + bool isEHPad() const { return IsEHPad; } - /// setIsLandingPad - Indicates the block is a landing pad. That is - /// this basic block is entered via an exception handler. - void setIsLandingPad(bool V = true) { IsLandingPad = V; } + /// Indicates the block is a landing pad. That is this basic block is entered + /// via an exception handler. + void setIsEHPad(bool V = true) { IsEHPad = V; } - /// getLandingPadSuccessor - If this block has a successor that is a landing - /// pad, return it. Otherwise return NULL. + /// If this block has a successor that is a landing pad, return it. Otherwise + /// return NULL. const MachineBasicBlock *getLandingPadSuccessor() const; + bool hasEHPadSuccessor() const; + + /// Returns true if this is the entry block of an EH funclet. + bool isEHFuncletEntry() const { return IsEHFuncletEntry; } + + /// Indicates if this is the entry block of an EH funclet. + void setIsEHFuncletEntry(bool V = true) { IsEHFuncletEntry = V; } + + /// Returns true if this is the entry block of a cleanup funclet. + bool isCleanupFuncletEntry() const { return IsCleanupFuncletEntry; } + + /// Indicates if this is the entry block of a cleanup funclet. + void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; } + // Code Layout methods. - /// moveBefore/moveAfter - move 'this' block before or after the specified - /// block. This only moves the block, it does not modify the CFG or adjust - /// potential fall-throughs at the end of the block. + /// Move 'this' block before or after the specified block. This only moves + /// the block, it does not modify the CFG or adjust potential fall-throughs at + /// the end of the block. void moveBefore(MachineBasicBlock *NewAfter); void moveAfter(MachineBasicBlock *NewBefore); - /// updateTerminator - Update the terminator instructions in block to account - /// for changes to the layout. If the block previously used a fallthrough, - /// it may now need a branch, and if it previously used branching it may now - /// be able to use a fallthrough. + /// Update the terminator instructions in block to account for changes to the + /// layout. If the block previously used a fallthrough, it may now need a + /// branch, and if it previously used branching it may now be able to use a + /// fallthrough. void updateTerminator(); // Machine-CFG mutators - /// addSuccessor - Add succ as a successor of this MachineBasicBlock. - /// The Predecessors list of succ is automatically updated. WEIGHT - /// parameter is stored in Weights list and it may be used by - /// MachineBranchProbabilityInfo analysis to calculate branch probability. - /// - void addSuccessor(MachineBasicBlock *succ, uint32_t weight = 0); - - /// removeSuccessor - Remove successor from the successors list of this - /// MachineBasicBlock. The Predecessors list of succ is automatically updated. - /// - void removeSuccessor(MachineBasicBlock *succ); - - /// removeSuccessor - Remove specified successor from the successors list of - /// this MachineBasicBlock. The Predecessors list of succ is automatically - /// updated. Return the iterator to the element after the one removed. - /// - succ_iterator removeSuccessor(succ_iterator I); - - /// replaceSuccessor - Replace successor OLD with NEW and update weight info. + /// Add Succ as a successor of this MachineBasicBlock. The Predecessors list + /// of Succ is automatically updated. PROB parameter is stored in + /// Probabilities list. The default probability is set as unknown. Mixing + /// known and unknown probabilities in successor list is not allowed. When all + /// successors have unknown probabilities, 1 / N is returned as the + /// probability for each successor, where N is the number of successors. /// + /// Note that duplicate Machine CFG edges are not allowed. + void addSuccessor(MachineBasicBlock *Succ, + BranchProbability Prob = BranchProbability::getUnknown()); + + /// Add Succ as a successor of this MachineBasicBlock. The Predecessors list + /// of Succ is automatically updated. The probability is not provided because + /// BPI is not available (e.g. -O0 is used), in which case edge probabilities + /// won't be used. Using this interface can save some space. + void addSuccessorWithoutProb(MachineBasicBlock *Succ); + + /// Set successor probability of a given iterator. + void setSuccProbability(succ_iterator I, BranchProbability Prob); + + /// Normalize probabilities of all successors so that the sum of them becomes + /// one. This is usually done when the current update on this MBB is done, and + /// the sum of its successors' probabilities is not guaranteed to be one. The + /// user is responsible for the correct use of this function. + /// MBB::removeSuccessor() has an option to do this automatically. + void normalizeSuccProbs() { + BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end()); + } + + /// Validate successors' probabilities and check if the sum of them is + /// approximate one. This only works in DEBUG mode. + void validateSuccProbs() const; + + /// Remove successor from the successors list of this MachineBasicBlock. The + /// Predecessors list of Succ is automatically updated. + /// If NormalizeSuccProbs is true, then normalize successors' probabilities + /// after the successor is removed. + void removeSuccessor(MachineBasicBlock *Succ, + bool NormalizeSuccProbs = false); + + /// Remove specified successor from the successors list of this + /// MachineBasicBlock. The Predecessors list of Succ is automatically updated. + /// If NormalizeSuccProbs is true, then normalize successors' probabilities + /// after the successor is removed. + /// Return the iterator to the element after the one removed. + succ_iterator removeSuccessor(succ_iterator I, + bool NormalizeSuccProbs = false); + + /// Replace successor OLD with NEW and update probability info. void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New); + /// Transfers all the successors from MBB to this machine basic block (i.e., + /// copies all the successors FromMBB and remove all the successors from + /// FromMBB). + void transferSuccessors(MachineBasicBlock *FromMBB); - /// transferSuccessors - Transfers all the successors from MBB to this - /// machine basic block (i.e., copies all the successors fromMBB and - /// remove all the successors from fromMBB). - void transferSuccessors(MachineBasicBlock *fromMBB); + /// Transfers all the successors, as in transferSuccessors, and update PHI + /// operands in the successor blocks which refer to FromMBB to refer to this. + void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB); - /// transferSuccessorsAndUpdatePHIs - Transfers all the successors, as - /// in transferSuccessors, and update PHI operands in the successor blocks - /// which refer to fromMBB to refer to this. - void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB); + /// Return true if any of the successors have probabilities attached to them. + bool hasSuccessorProbabilities() const { return !Probs.empty(); } - /// isSuccessor - Return true if the specified MBB is a successor of this - /// block. + /// Return true if the specified MBB is a predecessor of this block. + bool isPredecessor(const MachineBasicBlock *MBB) const; + + /// Return true if the specified MBB is a successor of this block. bool isSuccessor(const MachineBasicBlock *MBB) const; - /// isLayoutSuccessor - Return true if the specified MBB will be emitted - /// immediately after this block, such that if this block exits by - /// falling through, control will transfer to the specified MBB. Note - /// that MBB need not be a successor at all, for example if this block - /// ends with an unconditional branch to some other block. + /// Return true if the specified MBB will be emitted immediately after this + /// block, such that if this block exits by falling through, control will + /// transfer to the specified MBB. Note that MBB need not be a successor at + /// all, for example if this block ends with an unconditional branch to some + /// other block. bool isLayoutSuccessor(const MachineBasicBlock *MBB) const; - /// canFallThrough - Return true if the block can implicitly transfer - /// control to the block after it by falling off the end of it. This should - /// return false if it can reach the block after it, but it uses an explicit - /// branch to do so (e.g., a table jump). True is a conservative answer. + /// Return true if the block can implicitly transfer control to the block + /// after it by falling off the end of it. This should return false if it can + /// reach the block after it, but it uses an explicit 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. iterator getFirstNonPHI(); - /// SkipPHIsAndLabels - Return the first instruction in MBB after I that is - /// not a PHI or a label. This is the correct point to insert copies at the - /// beginning of a basic block. + /// Return the first instruction in MBB after I that is not a PHI or a label. + /// This is the correct point to insert copies at the beginning of a basic + /// block. iterator SkipPHIsAndLabels(iterator I); - /// getFirstTerminator - returns an iterator to the first terminator - /// instruction of this basic block. If a terminator does not exist, - /// it returns end() + /// Returns an iterator to the first terminator 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(this)->getFirstTerminator(); + } - /// getFirstInstrTerminator - Same getFirstTerminator but it ignores bundles - /// and return an instr_iterator instead. + /// Same getFirstTerminator but it ignores bundles and return an + /// instr_iterator instead. instr_iterator getFirstInstrTerminator(); - /// getLastNonDebugInstr - returns an iterator to the last non-debug - /// instruction in the basic block, or end() + /// Returns an iterator to the first non-debug instruction in the basic block, + /// or end(). + iterator getFirstNonDebugInstr(); + const_iterator getFirstNonDebugInstr() const { + return const_cast(this)->getFirstNonDebugInstr(); + } + + /// 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(this)->getLastNonDebugInstr(); + } + + /// Convenience function that returns true if the block ends in a return + /// instruction. + bool isReturnBlock() const { + return !empty() && back().isReturn(); + } - /// SplitCriticalEdge - Split the critical edge from this block to the - /// given successor block, and return the newly created block, or null - /// if splitting is not possible. + /// Split the critical edge from this block to the given successor block, and + /// return the newly created block, or null if splitting is not possible. /// /// This function updates LiveVariables, MachineDominatorTree, and /// MachineLoopInfo, as applicable. @@ -464,165 +582,214 @@ public: void pop_back() { Insts.pop_back(); } void push_back(MachineInstr *MI) { Insts.push_back(MI); } - template - void insert(instr_iterator I, IT S, IT E) { - Insts.insert(I, S, E); - } - instr_iterator insert(instr_iterator I, MachineInstr *M) { - return Insts.insert(I, M); - } - instr_iterator insertAfter(instr_iterator I, MachineInstr *M) { - return Insts.insertAfter(I, M); - } + /// Insert MI into the instruction list before I, possibly inside a bundle. + /// + /// If the insertion point is inside a bundle, MI will be added to the bundle, + /// otherwise MI will not be added to any bundle. That means this function + /// alone can't be used to prepend or append instructions to bundles. See + /// MIBundleBuilder::insert() for a more reliable way of doing that. + instr_iterator insert(instr_iterator I, MachineInstr *M); + /// Insert a range of instructions into the instruction list before I. template 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); } - iterator insert(iterator I, MachineInstr *M) { - return Insts.insert(I.getInstrIterator(), M); + + /// 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); } - iterator insertAfter(iterator I, MachineInstr *M) { - return Insts.insertAfter(I.getInstrIterator(), M); + + /// 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); } - /// erase - Remove the specified element or range from the instruction list. - /// These functions delete any instructions removed. + /// Remove an instruction from the instruction list and delete it. /// - instr_iterator erase(instr_iterator I) { - return Insts.erase(I); - } - instr_iterator erase(instr_iterator I, instr_iterator E) { - return Insts.erase(I, E); - } + /// If the instruction is part of a bundle, the other instructions in the + /// bundle will still be bundled after removing the single instruction. + instr_iterator erase(instr_iterator I); + + /// Remove an instruction from the instruction list and delete it. + /// + /// If the instruction is part of a bundle, the other instructions in the + /// bundle will still be bundled after removing the single instruction. instr_iterator erase_instr(MachineInstr *I) { - instr_iterator MII(I); - return erase(MII); + return erase(instr_iterator(I)); } - iterator erase(iterator I); + /// Remove a range of instructions from the instruction list and delete them. iterator erase(iterator I, iterator E) { return Insts.erase(I.getInstrIterator(), E.getInstrIterator()); } + + /// Remove an instruction or bundle from the instruction list and delete it. + /// + /// If I points to a bundle of instructions, they are all erased. + iterator erase(iterator I) { + return erase(I, std::next(I)); + } + + /// Remove an instruction from the instruction list and delete it. + /// + /// If I is the head of a bundle of instructions, the whole bundle will be + /// erased. iterator erase(MachineInstr *I) { - iterator MII(I); - return erase(MII); - } - - /// remove - Remove the instruction from the instruction list. This function - /// does not delete the instruction. WARNING: Note, if the specified - /// instruction is a bundle this function will remove all the bundled - /// instructions as well. It is up to the caller to keep a list of the - /// bundled instructions and re-insert them if desired. This function is - /// *not recommended* for manipulating instructions with bundles. Use - /// splice instead. - MachineInstr *remove(MachineInstr *I); + return erase(iterator(I)); + } + + /// Remove the unbundled instruction from the instruction list without + /// deleting it. + /// + /// This function can not be used to remove bundled instructions, use + /// remove_instr to remove individual instructions from a bundle. + MachineInstr *remove(MachineInstr *I) { + assert(!I->isBundled() && "Cannot remove bundled instructions"); + return Insts.remove(instr_iterator(I)); + } + + /// Remove the possibly bundled instruction from the instruction list + /// without deleting it. + /// + /// If the instruction is part of a bundle, the other instructions in the + /// bundle will still be bundled after removing the single instruction. + MachineInstr *remove_instr(MachineInstr *I); + void clear() { Insts.clear(); } - /// splice - Take an instruction from MBB 'Other' at the position From, - /// and insert it into this MBB right before 'where'. - void splice(instr_iterator where, MachineBasicBlock *Other, - instr_iterator From) { - Insts.splice(where, Other->Insts, From); + /// Take an instruction from MBB 'Other' at the position From, and insert it + /// into this MBB right before 'Where'. + /// + /// If From points to a bundle of instructions, the whole bundle is moved. + 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, std::next(From)); } - void splice(iterator where, MachineBasicBlock *Other, iterator From); - /// splice - Take a block of instructions from MBB 'Other' in the range [From, - /// To), and insert them into this MBB right before 'where'. - void splice(instr_iterator where, MachineBasicBlock *Other, instr_iterator From, - instr_iterator To) { - Insts.splice(where, Other->Insts, From, To); - } - void splice(iterator where, MachineBasicBlock *Other, iterator From, - iterator To) { - Insts.splice(where.getInstrIterator(), Other->Insts, + /// Take a block of instructions from MBB 'Other' in the range [From, To), + /// and insert them into this MBB right before 'Where'. + /// + /// The instruction at 'Where' must not be included in the range of + /// instructions to move. + void splice(iterator Where, MachineBasicBlock *Other, + iterator From, iterator To) { + Insts.splice(Where.getInstrIterator(), Other->Insts, From.getInstrIterator(), To.getInstrIterator()); } - /// removeFromParent - This method unlinks 'this' from the containing - /// function, and returns it, but does not delete it. + /// This method unlinks 'this' from the containing function, and returns it, + /// but does not delete it. MachineBasicBlock *removeFromParent(); - /// eraseFromParent - This method unlinks 'this' from the containing - /// function and deletes it. + /// This method unlinks 'this' from the containing function and deletes it. void eraseFromParent(); - /// ReplaceUsesOfBlockWith - Given a machine basic block that branched to - /// 'Old', change the code and CFG so that it branches to 'New' instead. + /// Given a machine basic block that branched to 'Old', change the code and + /// CFG so that it branches to 'New' instead. void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); - /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in - /// the CFG to be inserted. If we have proven that MBB can only branch to - /// DestA and DestB, remove any other MBB successors from the CFG. DestA and - /// DestB can be null. Besides DestA and DestB, retain other edges leading - /// to LandingPads (currently there can be only one; we don't check or require - /// that here). Note it is possible that DestA and/or DestB are LandingPads. + /// Various pieces of code can cause excess edges in the CFG to be inserted. + /// If we have proven that MBB can only branch to DestA and DestB, remove any + /// other MBB successors from the CFG. DestA and DestB can be null. Besides + /// DestA and DestB, retain other edges leading to LandingPads (currently + /// there can be only one; we don't check or require that here). Note it is + /// possible that DestA and/or DestB are LandingPads. bool CorrectExtraCFGEdges(MachineBasicBlock *DestA, MachineBasicBlock *DestB, - bool isCond); + bool IsCond); - /// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping - /// any DBG_VALUE instructions. Return UnknownLoc if there is none. + /// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE + /// instructions. Return UnknownLoc if there is none. DebugLoc findDebugLoc(instr_iterator MBBI); DebugLoc findDebugLoc(iterator MBBI) { return findDebugLoc(MBBI.getInstrIterator()); } + /// Possible outcome of a register liveness query to computeRegisterLiveness() + enum LivenessQueryResult { + LQR_Live, ///< Register is known to be (at least partially) live. + LQR_Dead, ///< Register is known to be fully dead. + LQR_Unknown ///< Register liveness not decidable from local neighborhood. + }; + + /// Return whether (physical) register \p Reg has been ined and not + /// 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. + /// + /// \p Reg must be a physical register. + LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, + 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; + void print(raw_ostream &OS, ModuleSlotTracker &MST, + SlotIndexes * = nullptr) const; - /// getNumber - MachineBasicBlocks are uniquely numbered at the function - /// level, unless they're not in a MachineFunction yet, in which case this - /// will return -1. - /// + // Printing method used by LoopInfo. + void printAsOperand(raw_ostream &OS, bool PrintType = true) const; + + /// MachineBasicBlocks are uniquely numbered at the function level, unless + /// they're not in a MachineFunction yet, in which case this will return -1. int getNumber() const { return Number; } void setNumber(int N) { Number = N; } - /// getSymbol - Return the MCSymbol for this basic block. - /// + /// Return the MCSymbol for this basic block. MCSymbol *getSymbol() const; private: - /// getWeightIterator - Return weight iterator corresponding to the I - /// successor iterator. - weight_iterator getWeightIterator(succ_iterator I); - const_weight_iterator getWeightIterator(const_succ_iterator I) const; + /// Return probability iterator corresponding to the I successor iterator. + probability_iterator getProbabilityIterator(succ_iterator I); + const_probability_iterator + getProbabilityIterator(const_succ_iterator I) const; friend class MachineBranchProbabilityInfo; + friend class MIPrinter; - /// getSuccWeight - Return weight of the edge from this block to MBB. This - /// method should NOT be called directly, but by using getEdgeWeight method - /// from MachineBranchProbabilityInfo class. - uint32_t getSuccWeight(const MachineBasicBlock *succ) const; - + /// Return probability of the edge from this block to MBB. This method should + /// NOT be called directly, but by using getEdgeProbability method from + /// MachineBranchProbabilityInfo class. + BranchProbability getSuccProbability(const_succ_iterator Succ) const; // Methods used to maintain doubly linked list of blocks... friend struct ilist_traits; // Machine-CFG mutators - /// addPredecessor - Remove pred as a predecessor of this MachineBasicBlock. - /// Don't do this unless you know what you're doing, because it doesn't - /// update pred's successors list. Use pred->addSuccessor instead. - /// - void addPredecessor(MachineBasicBlock *pred); + /// Remove Pred as a predecessor of this MachineBasicBlock. Don't do this + /// unless you know what you're doing, because it doesn't update Pred's + /// successors list. Use Pred->addSuccessor instead. + void addPredecessor(MachineBasicBlock *Pred); - /// removePredecessor - Remove pred as a predecessor of this - /// MachineBasicBlock. Don't do this unless you know what you're - /// doing, because it doesn't update pred's successors list. Use - /// pred->removeSuccessor instead. - /// - void removePredecessor(MachineBasicBlock *pred); + /// Remove Pred as a predecessor of this MachineBasicBlock. Don't do this + /// unless you know what you're doing, because it doesn't update Pred's + /// successors list. Use Pred->removeSuccessor instead. + void removePredecessor(MachineBasicBlock *Pred); }; 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 { @@ -636,7 +803,7 @@ struct MBB2NumberFunctor : //===--------------------------------------------------------------------===// // Provide specializations of GraphTraits to be able to treat a -// MachineFunction as a graph of MachineBasicBlocks... +// MachineFunction as a graph of MachineBasicBlocks. // template <> struct GraphTraits { @@ -666,7 +833,7 @@ template <> struct GraphTraits { }; // Provide specializations of GraphTraits to be able to treat a -// MachineFunction as a graph of MachineBasicBlocks... and to walk it +// MachineFunction as a graph of MachineBasicBlocks and to walk it // in inverse order. Inverse order for a function is considered // to be when traversing the predecessor edges of a MBB // instead of the successor edges. @@ -699,71 +866,29 @@ template <> struct GraphTraits > { } }; -//===----------------------------------------------------------------------===// -// MachineOperand iterator -// -/// MachineOperands - Iterator that can visit all operands on a MachineInstr, -/// or all operands on a bundle of MachineInstrs. -/// -/// Intended use: -/// -/// for (MIOperands MIO(MI, true); MIO.isValid(); ++MIO) { -/// if (!MIO->isReg()) -/// continue; -/// ... -/// } -/// -class MIOperands { - MachineBasicBlock::instr_iterator InstrI, InstrE; - MachineInstr::mop_iterator OpI, OpE; - - // If the operands on InstrI are exhausted, advance InstrI to the next - // bundled instruction with operands. - void advance() { - while (OpI == OpE) { - // Don't advance off the basic block, or into a new bundle. - if (++InstrI == InstrE || !InstrI->isInsideBundle()) - break; - OpI = InstrI->operands_begin(); - OpE = InstrI->operands_end(); - } - } +/// 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: - /// MIOperands - Create an iterator that visits all operands on MI, or all - /// operands on every instruction in the bundle containing MI. - /// - /// @param MI The instruction to examine. - /// @param WholeBundle When true, visit all operands on the entire bundle. - /// - explicit MIOperands(MachineInstr *MI, bool WholeBundle = false) { - if (WholeBundle) { - InstrI = MI->getBundleStart(); - InstrE = MI->getParent()->instr_end(); - } else { - InstrI = InstrE = MI; - ++InstrE; - } - OpI = InstrI->operands_begin(); - OpE = InstrI->operands_end(); - if (WholeBundle) - advance(); - } - - /// isValid - Returns true until all the operands have been visited. - bool isValid() const { return OpI != OpE; } + MachineInstrSpan(MachineBasicBlock::iterator I) + : MBB(*I->getParent()), + I(I), + B(I == MBB.begin() ? MBB.end() : std::prev(I)), + E(std::next(I)) {} - /// Preincrement. Move to the next operand. - MIOperands &operator++() { - assert(isValid() && "Cannot advance MIOperands beyond the last operand"); - ++OpI; - advance(); - return *this; + MachineBasicBlock::iterator begin() { + return B == MBB.end() ? MBB.begin() : std::next(B); } + MachineBasicBlock::iterator end() { return E; } + bool empty() { return begin() == end(); } - MachineOperand &operator* () const { return *OpI; } - MachineOperand *operator->() const { return &*OpI; } + MachineBasicBlock::iterator getInitial() { return I; } }; } // End llvm namespace