X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FCodeGen%2FMachineBasicBlock.h;h=1440b967aea2167be67c4e064f07396d8dde0d5a;hb=0bea7854271564707d59a10339e9f302155d0b73;hp=3cfc47ac4d8464d08470dd88d7529ddfa324e39d;hpb=d463a7446402f0771465fe66fe0a7d9f72534902;p=oota-llvm.git diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 3cfc47ac4d8..1440b967aea 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/DataTypes.h" +#include namespace llvm { @@ -23,8 +25,10 @@ class Pass; class BasicBlock; class MachineFunction; class MCSymbol; +class SlotIndexes; class StringRef; class raw_ostream; +class MachineBranchProbabilityInfo; template <> struct ilist_traits : public ilist_default_traits { @@ -61,20 +65,28 @@ class MachineBasicBlock : public ilist_node { const BasicBlock *BB; int Number; MachineFunction *xParent; - + /// Predecessors/Successors - Keep track of the predecessor / successor /// basicblocks. std::vector Predecessors; std::vector 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). + std::vector Weights; + typedef std::vector::iterator weight_iterator; + typedef std::vector::const_iterator const_weight_iterator; + /// LiveIns - Keep track of the physical registers that are livein of /// the basicblock. std::vector LiveIns; /// 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; - + /// IsLandingPad - Indicate that this basic block is entered via an /// exception handler. bool IsLandingPad; @@ -83,6 +95,10 @@ class MachineBasicBlock : public ilist_node { /// 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() {} @@ -104,6 +120,10 @@ public: /// "(null)". StringRef getName() const; + /// getFullName - Return a formatted string to identify this block and its + /// parent function. + std::string getFullName() const; + /// hasAddressTaken - Test whether this block is potentially the target /// of an indirect branch. bool hasAddressTaken() const { return AddressTaken; } @@ -117,27 +137,122 @@ public: const MachineFunction *getParent() const { return xParent; } MachineFunction *getParent() { return xParent; } - typedef Instructions::iterator iterator; - typedef Instructions::const_iterator const_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; + + /// bundle_iterator - 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) {} + + 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()) && + "It's not legal to initialize bundle_iterator with a bundled MI"); + } + // 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; } + + bool operator==(const bundle_iterator &x) const { + return MII == x.MII; + } + bool operator!=(const bundle_iterator &x) const { + return !operator==(x); + } + + // Increment and decrement operators... + bundle_iterator &operator--() { // predecrement - Back up + do --MII; + while (MII->isBundledWithPred()); + return *this; + } + bundle_iterator &operator++() { // preincrement - Advance + while (MII->isBundledWithSucc()) + ++MII; + ++MII; + return *this; + } + bundle_iterator operator--(int) { // postdecrement operators... + bundle_iterator tmp = *this; + --*this; + return tmp; + } + bundle_iterator operator++(int) { // postincrement operators... + bundle_iterator tmp = *this; + ++*this; + return tmp; + } + + IterTy getInstrIterator() const { + return MII; + } + }; + + typedef Instructions::iterator instr_iterator; + typedef Instructions::const_iterator const_instr_iterator; + typedef std::reverse_iterator reverse_instr_iterator; + typedef + std::reverse_iterator const_reverse_instr_iterator; + + typedef + bundle_iterator iterator; + typedef + bundle_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + 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(); } - - iterator begin() { return Insts.begin(); } - const_iterator begin() const { return Insts.begin(); } - iterator end() { return Insts.end(); } - const_iterator end() const { return Insts.end(); } - reverse_iterator rbegin() { return Insts.rbegin(); } - const_reverse_iterator rbegin() const { return Insts.rbegin(); } - reverse_iterator rend () { return Insts.rend(); } - const_reverse_iterator rend () const { return Insts.rend(); } + 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(); } + instr_iterator instr_end() { return Insts.end(); } + const_instr_iterator instr_end() const { return Insts.end(); } + reverse_instr_iterator instr_rbegin() { return Insts.rbegin(); } + const_reverse_instr_iterator instr_rbegin() const { return Insts.rbegin(); } + reverse_instr_iterator instr_rend () { return Insts.rend(); } + const_reverse_instr_iterator instr_rend () const { return Insts.rend(); } + + 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(); } + + inline iterator_range terminators() { + return iterator_range(getFirstTerminator(), end()); + } + inline iterator_range terminators() const { + return iterator_range(getFirstTerminator(), end()); + } // Machine-CFG iterators typedef std::vector::iterator pred_iterator; @@ -152,7 +267,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(); } @@ -186,12 +300,30 @@ public: } bool succ_empty() const { return Successors.empty(); } + inline iterator_range predecessors() { + return iterator_range(pred_begin(), pred_end()); + } + inline iterator_range predecessors() const { + return iterator_range(pred_begin(), pred_end()); + } + inline iterator_range successors() { + return iterator_range(succ_begin(), succ_end()); + } + inline iterator_range successors() const { + return iterator_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); } + /// 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 removeLiveIn(unsigned Reg); @@ -208,10 +340,12 @@ public: bool livein_empty() const { return LiveIns.empty(); } /// getAlignment - 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). /// void setAlignment(unsigned Align) { Alignment = Align; } @@ -221,10 +355,14 @@ public: /// setIsLandingPad - Indicates the block is a landing pad. That is /// this basic block is entered via an exception handler. - void setIsLandingPad() { IsLandingPad = true; } + void setIsLandingPad(bool V = true) { IsLandingPad = V; } + + /// getLandingPadSuccessor - If this block has a successor that is a landing + /// pad, return it. Otherwise return NULL. + const MachineBasicBlock *getLandingPadSuccessor() const; // 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. @@ -238,11 +376,18 @@ public: void updateTerminator(); // Machine-CFG mutators - + /// addSuccessor - Add succ as a successor of this MachineBasicBlock. - /// The Predecessors list of succ is automatically updated. + /// 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); + /// Note that duplicate Machine CFG edges are not allowed. + /// + 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. @@ -254,7 +399,12 @@ public: /// 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. + /// + void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New); + + /// 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). @@ -264,7 +414,11 @@ public: /// in transferSuccessors, and update PHI operands in the successor blocks /// which refer to fromMBB to refer to this. void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB); - + + /// isPredecessor - Return true if the specified MBB is a predecessor of this + /// block. + bool isPredecessor(const MachineBasicBlock *MBB) const; + /// isSuccessor - Return true if the specified MBB is a successor of this /// block. bool isSuccessor(const MachineBasicBlock *MBB) const; @@ -282,17 +436,32 @@ public: /// 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. + 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() iterator getFirstTerminator(); + const_iterator getFirstTerminator() const; + + /// getFirstInstrTerminator - 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() + iterator getLastNonDebugInstr(); + const_iterator getLastNonDebugInstr() const; /// SplitCriticalEdge - Split the critical edge from this block to the /// given successor block, and return the newly created block, or null @@ -305,35 +474,121 @@ public: void pop_front() { Insts.pop_front(); } void pop_back() { Insts.pop_back(); } void push_back(MachineInstr *MI) { Insts.push_back(MI); } + + /// 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) { Insts.insert(I, S, E); } - iterator insert(iterator I, MachineInstr *M) { return Insts.insert(I, M); } + 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); + } - // erase - Remove the specified element or range from the instruction list. - // These functions delete any instructions removed. - // - iterator erase(iterator I) { return Insts.erase(I); } - iterator erase(iterator I, iterator E) { return Insts.erase(I, E); } - MachineInstr *remove(MachineInstr *I) { return Insts.remove(I); } - void clear() { Insts.clear(); } + /// 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); + } - /// splice - Take an instruction from MBB 'Other' at the position From, - /// and insert it into this MBB right before 'where'. - void splice(iterator where, MachineBasicBlock *Other, iterator From) { - Insts.splice(where, Other->Insts, From); + /// 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); } - /// 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(iterator where, MachineBasicBlock *Other, iterator From, - iterator To) { - Insts.splice(where, Other->Insts, From, To); + /// 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_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) { + return erase(instr_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) { + 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(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(); + } + + /// 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)); + } + + /// 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. MachineBasicBlock *removeFromParent(); - + /// eraseFromParent - This method unlinks 'this' from the containing /// function and deletes it. void eraseFromParent(); @@ -354,11 +609,39 @@ public: /// findDebugLoc - find the next valid DebugLoc starting at MBBI, skipping /// any DBG_VALUE instructions. Return UnknownLoc if there is none. - DebugLoc findDebugLoc(MachineBasicBlock::iterator &MBBI); + 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 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. + }; + + /// computeRegisterLiveness - Return whether (physical) register \c Reg + /// has been ined and not 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. + /// + /// \c Reg must be a physical register. + LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, + unsigned Reg, MachineInstr *MI, + unsigned Neighborhood=10); // Debugging methods. void dump() const; - void print(raw_ostream &OS) 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 @@ -370,8 +653,23 @@ public: /// getSymbol - Return the MCSymbol for this basic block. /// MCSymbol *getSymbol() const; - -private: // Methods used to maintain doubly linked list of blocks... + + +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; + + friend class MachineBranchProbabilityInfo; + + /// 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_succ_iterator Succ) const; + + + // Methods used to maintain doubly linked list of blocks... friend struct ilist_traits; // Machine-CFG mutators @@ -392,7 +690,13 @@ private: // Methods used to maintain doubly linked list of blocks... 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 { + unsigned operator()(const MachineBasicBlock *MBB) const { + return MBB->getNumber(); + } +}; //===--------------------------------------------------------------------===// // GraphTraits specializations for machine basic block graphs (machine-CFGs) @@ -462,6 +766,31 @@ template <> struct GraphTraits > { } }; + + +/// 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