X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FMachineBasicBlock.h;h=9585b29a5dc30ce145b6bc63c45019a145471e30;hp=87e27361f2e558ae09eefd75e1f50ecbbc69bca9;hb=5666fc71f0e2ed2c0400d8bca079a1dd3f33fe53;hpb=dbc2c060f2325bae26cd7bb4a27d4a8d1e8c8e93 diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 87e27361f2e..9585b29a5dc 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -16,6 +16,8 @@ #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,12 +27,15 @@ class Pass; class BasicBlock; class MachineFunction; class MCSymbol; -class MIRPrinter; +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: @@ -53,14 +58,33 @@ 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: + // XXX-update: A flag that checks whether we can eliminate this machine basic + // block. + bool canEliminateMachineBB; + typedef ilist Instructions; Instructions Insts; const BasicBlock *BB; @@ -71,35 +95,43 @@ class MachineBasicBlock : public ilist_node { std::vector Predecessors; std::vector Successors; - /// 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 + /// 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 Weights; - typedef std::vector::iterator weight_iterator; - typedef std::vector::const_iterator const_weight_iterator; + 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. - std::vector LiveIns; + 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; + unsigned Alignment = 0; /// Indicate that this basic block is entered via an exception handler. - bool IsLandingPad; + bool IsEHPad = false; /// Indicate that this basic block is potentially the target of an indirect /// branch. - bool AddressTaken; + bool AddressTaken = false; + + /// Indicate that this basic block is the entry block of an EH funclet. + bool IsEHFuncletEntry = false; + + /// Indicate that this basic block is the entry block of a cleanup funclet. + bool IsCleanupFuncletEntry = false; /// \brief since getSymbol is a relatively heavy-weight operation, the symbol /// is only computed once and is cached. - mutable MCSymbol *CachedMCSymbol; + mutable MCSymbol *CachedMCSymbol = nullptr; // Intrusive list support MachineBasicBlock() {} - explicit MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb); + explicit MachineBasicBlock(MachineFunction &MF, const BasicBlock *BB); ~MachineBasicBlock(); @@ -107,6 +139,15 @@ class MachineBasicBlock : public ilist_node { friend class MachineFunction; public: + // 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. @@ -137,14 +178,14 @@ public: IterTy MII; public: - bundle_iterator(IterTy mii) : MII(mii) {} + bundle_iterator(IterTy MI) : MII(MI) {} - bundle_iterator(Ty &mi) : MII(mi) { - assert(!mi.isBundledWithPred() && + 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->isBundledWithPred()) && + bundle_iterator(Ty *MI) : MII(MI) { + assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize bundle_iterator with a bundled MI"); } // Template allows conversion from const to nonconst. @@ -156,13 +197,13 @@ public: 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... @@ -238,11 +279,16 @@ public: 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; + } + inline iterator_range terminators() { - return iterator_range(getFirstTerminator(), end()); + return make_range(getFirstTerminator(), end()); } inline iterator_range terminators() const { - return iterator_range(getFirstTerminator(), end()); + return make_range(getFirstTerminator(), end()); } // Machine-CFG iterators @@ -292,16 +338,16 @@ public: bool succ_empty() const { return Successors.empty(); } inline iterator_range predecessors() { - return iterator_range(pred_begin(), pred_end()); + return make_range(pred_begin(), pred_end()); } inline iterator_range predecessors() const { - return iterator_range(pred_begin(), pred_end()); + return make_range(pred_begin(), pred_end()); } inline iterator_range successors() { - return iterator_range(succ_begin(), succ_end()); + return make_range(succ_begin(), succ_end()); } inline iterator_range successors() const { - return iterator_range(succ_begin(), succ_end()); + return make_range(succ_begin(), succ_end()); } // LiveIn management methods. @@ -309,33 +355,46 @@ public: /// 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); } + void addLiveIn(MCPhysReg PhysReg, LaneBitmask LaneMask = ~0u) { + LiveIns.push_back(RegisterMaskPair(PhysReg, LaneMask)); + } + void addLiveIn(const RegisterMaskPair &RegMaskPair) { + LiveIns.push_back(RegMaskPair); + } /// 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()); - } + void sortUniqueLiveIns(); /// 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); + unsigned addLiveIn(MCPhysReg PhysReg, const TargetRegisterClass *RC); /// Remove the specified register from the live in set. - void removeLiveIn(unsigned Reg); + void removeLiveIn(MCPhysReg Reg, LaneBitmask LaneMask = ~0u); /// Return true if the specified register is in the live in set. - bool isLiveIn(unsigned Reg) const; + 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()); + } + + /// 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). @@ -347,16 +406,30 @@ public: /// 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; } + bool isEHPad() const { return IsEHPad; } /// 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; } + void setIsEHPad(bool V = true) { IsEHPad = V; } /// 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. /// Move 'this' block before or after the specified block. This only moves @@ -373,40 +446,68 @@ public: // Machine-CFG mutators - /// 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. + /// 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, uint32_t weight = 0); + 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()); + } - /// Set successor weight of a given iterator. - void setSuccWeight(succ_iterator I, uint32_t weight); + /// 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. - void removeSuccessor(MachineBasicBlock *succ); + /// 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. + /// 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); + succ_iterator removeSuccessor(succ_iterator I, + bool NormalizeSuccProbs = false); - /// Replace successor OLD with NEW and update weight info. + /// 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); + /// 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); + /// 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 weights attached to them. - bool hasSuccessorWeights() const { return !Weights.empty(); } + /// Return true if any of the successors have probabilities attached to them. + bool hasSuccessorProbabilities() const { return !Probs.empty(); } /// Return true if the specified MBB is a predecessor of this block. bool isPredecessor(const MachineBasicBlock *MBB) const; @@ -464,6 +565,12 @@ public: 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(); + } + /// 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. /// @@ -550,7 +657,7 @@ public: /// remove_instr to remove individual instructions from a bundle. MachineInstr *remove(MachineInstr *I) { assert(!I->isBundled() && "Cannot remove bundled instructions"); - return Insts.remove(I); + return Insts.remove(instr_iterator(I)); } /// Remove the possibly bundled instruction from the instruction list @@ -604,7 +711,7 @@ public: /// possible that DestA and/or DestB are LandingPads. bool CorrectExtraCFGEdges(MachineBasicBlock *DestA, MachineBasicBlock *DestB, - bool isCond); + bool IsCond); /// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE /// instructions. Return UnknownLoc if there is none. @@ -615,12 +722,9 @@ public: /// Possible outcome of a register liveness query to computeRegisterLiveness() enum LivenessQueryResult { - LQR_Live, ///< Register is known to be live. - LQR_OverlappingLive, ///< Register itself is not live, but some overlapping - ///< register is. - LQR_Dead, ///< Register is known to be dead. - LQR_Unknown ///< Register liveness not decidable from local - ///< neighborhood. + 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 @@ -655,33 +759,33 @@ public: private: - /// 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 MIRPrinter; + friend class MIPrinter; - /// Return weight of the edge from this block to MBB. This method should NOT - /// be called directly, but by using getEdgeWeight method from + /// 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. - uint32_t getSuccWeight(const_succ_iterator Succ) const; - + BranchProbability getSuccProbability(const_succ_iterator Succ) const; // Methods used to maintain doubly linked list of blocks... friend struct ilist_traits; // Machine-CFG mutators - /// 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); - /// 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);