|  | //===- HexagonBlockRanges.h -------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONBLOCKRANGES_H | 
|  | #define LLVM_LIB_TARGET_HEXAGON_HEXAGONBLOCKRANGES_H | 
|  |  | 
|  | #include "llvm/ADT/BitVector.h" | 
|  | #include <cassert> | 
|  | #include <map> | 
|  | #include <set> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class HexagonSubtarget; | 
|  | class MachineBasicBlock; | 
|  | class MachineFunction; | 
|  | class MachineInstr; | 
|  | class MachineRegisterInfo; | 
|  | class raw_ostream; | 
|  | class TargetInstrInfo; | 
|  | class TargetRegisterInfo; | 
|  |  | 
|  | struct HexagonBlockRanges { | 
|  | HexagonBlockRanges(MachineFunction &MF); | 
|  |  | 
|  | struct RegisterRef { | 
|  | unsigned Reg, Sub; | 
|  |  | 
|  | bool operator<(RegisterRef R) const { | 
|  | return Reg < R.Reg || (Reg == R.Reg && Sub < R.Sub); | 
|  | } | 
|  | }; | 
|  | using RegisterSet = std::set<RegisterRef>; | 
|  |  | 
|  | // This is to represent an "index", which is an abstraction of a position | 
|  | // of an instruction within a basic block. | 
|  | class IndexType { | 
|  | public: | 
|  | enum : unsigned { | 
|  | None  = 0, | 
|  | Entry = 1, | 
|  | Exit  = 2, | 
|  | First = 11  // 10th + 1st | 
|  | }; | 
|  |  | 
|  | IndexType() {} | 
|  | IndexType(unsigned Idx) : Index(Idx) {} | 
|  |  | 
|  | static bool isInstr(IndexType X) { return X.Index >= First; } | 
|  |  | 
|  | operator unsigned() const; | 
|  | bool operator== (unsigned x) const; | 
|  | bool operator== (IndexType Idx) const; | 
|  | bool operator!= (unsigned x) const; | 
|  | bool operator!= (IndexType Idx) const; | 
|  | IndexType operator++ (); | 
|  | bool operator< (unsigned Idx) const; | 
|  | bool operator< (IndexType Idx) const; | 
|  | bool operator<= (IndexType Idx) const; | 
|  |  | 
|  | private: | 
|  | bool operator>  (IndexType Idx) const; | 
|  | bool operator>= (IndexType Idx) const; | 
|  |  | 
|  | unsigned Index = None; | 
|  | }; | 
|  |  | 
|  | // A range of indices, essentially a representation of a live range. | 
|  | // This is also used to represent "dead ranges", i.e. ranges where a | 
|  | // register is dead. | 
|  | class IndexRange : public std::pair<IndexType,IndexType> { | 
|  | public: | 
|  | IndexRange() = default; | 
|  | IndexRange(IndexType Start, IndexType End, bool F = false, bool T = false) | 
|  | : std::pair<IndexType,IndexType>(Start, End), Fixed(F), TiedEnd(T) {} | 
|  |  | 
|  | IndexType start() const { return first; } | 
|  | IndexType end() const   { return second; } | 
|  |  | 
|  | bool operator< (const IndexRange &A) const { | 
|  | return start() < A.start(); | 
|  | } | 
|  |  | 
|  | bool overlaps(const IndexRange &A) const; | 
|  | bool contains(const IndexRange &A) const; | 
|  | void merge(const IndexRange &A); | 
|  |  | 
|  | bool Fixed = false;   // Can be renamed?  "Fixed" means "no". | 
|  | bool TiedEnd = false; // The end is not a use, but a dead def tied to a use. | 
|  |  | 
|  | private: | 
|  | void setStart(const IndexType &S) { first = S; } | 
|  | void setEnd(const IndexType &E)   { second = E; } | 
|  | }; | 
|  |  | 
|  | // A list of index ranges. This represents liveness of a register | 
|  | // in a basic block. | 
|  | class RangeList : public std::vector<IndexRange> { | 
|  | public: | 
|  | void add(IndexType Start, IndexType End, bool Fixed, bool TiedEnd) { | 
|  | push_back(IndexRange(Start, End, Fixed, TiedEnd)); | 
|  | } | 
|  | void add(const IndexRange &Range) { | 
|  | push_back(Range); | 
|  | } | 
|  |  | 
|  | void include(const RangeList &RL); | 
|  | void unionize(bool MergeAdjacent = false); | 
|  | void subtract(const IndexRange &Range); | 
|  |  | 
|  | private: | 
|  | void addsub(const IndexRange &A, const IndexRange &B); | 
|  | }; | 
|  |  | 
|  | class InstrIndexMap { | 
|  | public: | 
|  | InstrIndexMap(MachineBasicBlock &B); | 
|  |  | 
|  | MachineInstr *getInstr(IndexType Idx) const; | 
|  | IndexType getIndex(MachineInstr *MI) const; | 
|  | MachineBasicBlock &getBlock() const { return Block; } | 
|  | IndexType getPrevIndex(IndexType Idx) const; | 
|  | IndexType getNextIndex(IndexType Idx) const; | 
|  | void replaceInstr(MachineInstr *OldMI, MachineInstr *NewMI); | 
|  |  | 
|  | friend raw_ostream &operator<< (raw_ostream &OS, const InstrIndexMap &Map); | 
|  |  | 
|  | IndexType First, Last; | 
|  |  | 
|  | private: | 
|  | MachineBasicBlock &Block; | 
|  | std::map<IndexType,MachineInstr*> Map; | 
|  | }; | 
|  |  | 
|  | using RegToRangeMap = std::map<RegisterRef, RangeList>; | 
|  |  | 
|  | RegToRangeMap computeLiveMap(InstrIndexMap &IndexMap); | 
|  | RegToRangeMap computeDeadMap(InstrIndexMap &IndexMap, RegToRangeMap &LiveMap); | 
|  | static RegisterSet expandToSubRegs(RegisterRef R, | 
|  | const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI); | 
|  |  | 
|  | struct PrintRangeMap { | 
|  | PrintRangeMap(const RegToRangeMap &M, const TargetRegisterInfo &I) | 
|  | : Map(M), TRI(I) {} | 
|  |  | 
|  | friend raw_ostream &operator<< (raw_ostream &OS, const PrintRangeMap &P); | 
|  |  | 
|  | private: | 
|  | const RegToRangeMap ⤅ | 
|  | const TargetRegisterInfo &TRI; | 
|  | }; | 
|  |  | 
|  | private: | 
|  | RegisterSet getLiveIns(const MachineBasicBlock &B, | 
|  | const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI); | 
|  |  | 
|  | void computeInitialLiveRanges(InstrIndexMap &IndexMap, | 
|  | RegToRangeMap &LiveMap); | 
|  |  | 
|  | MachineFunction &MF; | 
|  | const HexagonSubtarget &HST; | 
|  | const TargetInstrInfo &TII; | 
|  | const TargetRegisterInfo &TRI; | 
|  | BitVector Reserved; | 
|  | }; | 
|  |  | 
|  | inline HexagonBlockRanges::IndexType::operator unsigned() const { | 
|  | assert(Index >= First); | 
|  | return Index; | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator== (unsigned x) const { | 
|  | return Index == x; | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator== (IndexType Idx) const { | 
|  | return Index == Idx.Index; | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator!= (unsigned x) const { | 
|  | return Index != x; | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator!= (IndexType Idx) const { | 
|  | return Index != Idx.Index; | 
|  | } | 
|  |  | 
|  | inline | 
|  | HexagonBlockRanges::IndexType HexagonBlockRanges::IndexType::operator++ () { | 
|  | assert(Index != None); | 
|  | assert(Index != Exit); | 
|  | if (Index == Entry) | 
|  | Index = First; | 
|  | else | 
|  | ++Index; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator< (unsigned Idx) const { | 
|  | return operator< (IndexType(Idx)); | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator< (IndexType Idx) const { | 
|  | // !(x < x). | 
|  | if (Index == Idx.Index) | 
|  | return false; | 
|  | // !(None < x) for all x. | 
|  | // !(x < None) for all x. | 
|  | if (Index == None || Idx.Index == None) | 
|  | return false; | 
|  | // !(Exit < x) for all x. | 
|  | // !(x < Entry) for all x. | 
|  | if (Index == Exit || Idx.Index == Entry) | 
|  | return false; | 
|  | // Entry < x for all x != Entry. | 
|  | // x < Exit for all x != Exit. | 
|  | if (Index == Entry || Idx.Index == Exit) | 
|  | return true; | 
|  |  | 
|  | return Index < Idx.Index; | 
|  | } | 
|  |  | 
|  | inline bool HexagonBlockRanges::IndexType::operator<= (IndexType Idx) const { | 
|  | return operator==(Idx) || operator<(Idx); | 
|  | } | 
|  |  | 
|  | raw_ostream &operator<< (raw_ostream &OS, HexagonBlockRanges::IndexType Idx); | 
|  | raw_ostream &operator<< (raw_ostream &OS, | 
|  | const HexagonBlockRanges::IndexRange &IR); | 
|  | raw_ostream &operator<< (raw_ostream &OS, | 
|  | const HexagonBlockRanges::RangeList &RL); | 
|  | raw_ostream &operator<< (raw_ostream &OS, | 
|  | const HexagonBlockRanges::InstrIndexMap &M); | 
|  | raw_ostream &operator<< (raw_ostream &OS, | 
|  | const HexagonBlockRanges::PrintRangeMap &P); | 
|  |  | 
|  | } // end namespace llvm | 
|  |  | 
|  | #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONBLOCKRANGES_H |