10b57cec5SDimitry Andric //===- HexagonBlockRanges.h -------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONBLOCKRANGES_H 100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_HEXAGON_HEXAGONBLOCKRANGES_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h" 13*e8d8bef9SDimitry Andric #include "llvm/CodeGen/Register.h" 140b57cec5SDimitry Andric #include <cassert> 150b57cec5SDimitry Andric #include <map> 160b57cec5SDimitry Andric #include <set> 170b57cec5SDimitry Andric #include <utility> 180b57cec5SDimitry Andric #include <vector> 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace llvm { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric class HexagonSubtarget; 230b57cec5SDimitry Andric class MachineBasicBlock; 240b57cec5SDimitry Andric class MachineFunction; 250b57cec5SDimitry Andric class MachineInstr; 260b57cec5SDimitry Andric class MachineRegisterInfo; 270b57cec5SDimitry Andric class raw_ostream; 280b57cec5SDimitry Andric class TargetInstrInfo; 290b57cec5SDimitry Andric class TargetRegisterInfo; 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric struct HexagonBlockRanges { 320b57cec5SDimitry Andric HexagonBlockRanges(MachineFunction &MF); 330b57cec5SDimitry Andric 34*e8d8bef9SDimitry Andric // FIXME: Consolidate duplicate definitions of RegisterRef 350b57cec5SDimitry Andric struct RegisterRef { 36*e8d8bef9SDimitry Andric llvm::Register Reg; 37*e8d8bef9SDimitry Andric unsigned Sub; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric bool operator<(RegisterRef R) const { 400b57cec5SDimitry Andric return Reg < R.Reg || (Reg == R.Reg && Sub < R.Sub); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric }; 430b57cec5SDimitry Andric using RegisterSet = std::set<RegisterRef>; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // This is to represent an "index", which is an abstraction of a position 460b57cec5SDimitry Andric // of an instruction within a basic block. 470b57cec5SDimitry Andric class IndexType { 480b57cec5SDimitry Andric public: 490b57cec5SDimitry Andric enum : unsigned { 500b57cec5SDimitry Andric None = 0, 510b57cec5SDimitry Andric Entry = 1, 520b57cec5SDimitry Andric Exit = 2, 530b57cec5SDimitry Andric First = 11 // 10th + 1st 540b57cec5SDimitry Andric }; 550b57cec5SDimitry Andric IndexTypeHexagonBlockRanges560b57cec5SDimitry Andric IndexType() {} IndexTypeHexagonBlockRanges570b57cec5SDimitry Andric IndexType(unsigned Idx) : Index(Idx) {} 580b57cec5SDimitry Andric isInstrHexagonBlockRanges590b57cec5SDimitry Andric static bool isInstr(IndexType X) { return X.Index >= First; } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric operator unsigned() const; 620b57cec5SDimitry Andric bool operator== (unsigned x) const; 630b57cec5SDimitry Andric bool operator== (IndexType Idx) const; 640b57cec5SDimitry Andric bool operator!= (unsigned x) const; 650b57cec5SDimitry Andric bool operator!= (IndexType Idx) const; 660b57cec5SDimitry Andric IndexType operator++ (); 670b57cec5SDimitry Andric bool operator< (unsigned Idx) const; 680b57cec5SDimitry Andric bool operator< (IndexType Idx) const; 690b57cec5SDimitry Andric bool operator<= (IndexType Idx) const; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric private: 720b57cec5SDimitry Andric bool operator> (IndexType Idx) const; 730b57cec5SDimitry Andric bool operator>= (IndexType Idx) const; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric unsigned Index = None; 760b57cec5SDimitry Andric }; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // A range of indices, essentially a representation of a live range. 790b57cec5SDimitry Andric // This is also used to represent "dead ranges", i.e. ranges where a 800b57cec5SDimitry Andric // register is dead. 810b57cec5SDimitry Andric class IndexRange : public std::pair<IndexType,IndexType> { 820b57cec5SDimitry Andric public: 830b57cec5SDimitry Andric IndexRange() = default; 840b57cec5SDimitry Andric IndexRange(IndexType Start, IndexType End, bool F = false, bool T = false) 850b57cec5SDimitry Andric : std::pair<IndexType,IndexType>(Start, End), Fixed(F), TiedEnd(T) {} 860b57cec5SDimitry Andric startHexagonBlockRanges870b57cec5SDimitry Andric IndexType start() const { return first; } endHexagonBlockRanges880b57cec5SDimitry Andric IndexType end() const { return second; } 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric bool operator< (const IndexRange &A) const { 910b57cec5SDimitry Andric return start() < A.start(); 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric bool overlaps(const IndexRange &A) const; 950b57cec5SDimitry Andric bool contains(const IndexRange &A) const; 960b57cec5SDimitry Andric void merge(const IndexRange &A); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric bool Fixed = false; // Can be renamed? "Fixed" means "no". 990b57cec5SDimitry Andric bool TiedEnd = false; // The end is not a use, but a dead def tied to a use. 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric private: setStartHexagonBlockRanges1020b57cec5SDimitry Andric void setStart(const IndexType &S) { first = S; } setEndHexagonBlockRanges1030b57cec5SDimitry Andric void setEnd(const IndexType &E) { second = E; } 1040b57cec5SDimitry Andric }; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // A list of index ranges. This represents liveness of a register 1070b57cec5SDimitry Andric // in a basic block. 1080b57cec5SDimitry Andric class RangeList : public std::vector<IndexRange> { 1090b57cec5SDimitry Andric public: addHexagonBlockRanges1100b57cec5SDimitry Andric void add(IndexType Start, IndexType End, bool Fixed, bool TiedEnd) { 1110b57cec5SDimitry Andric push_back(IndexRange(Start, End, Fixed, TiedEnd)); 1120b57cec5SDimitry Andric } addHexagonBlockRanges1130b57cec5SDimitry Andric void add(const IndexRange &Range) { 1140b57cec5SDimitry Andric push_back(Range); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void include(const RangeList &RL); 1180b57cec5SDimitry Andric void unionize(bool MergeAdjacent = false); 1190b57cec5SDimitry Andric void subtract(const IndexRange &Range); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric private: 1220b57cec5SDimitry Andric void addsub(const IndexRange &A, const IndexRange &B); 1230b57cec5SDimitry Andric }; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric class InstrIndexMap { 1260b57cec5SDimitry Andric public: 1270b57cec5SDimitry Andric InstrIndexMap(MachineBasicBlock &B); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric MachineInstr *getInstr(IndexType Idx) const; 1300b57cec5SDimitry Andric IndexType getIndex(MachineInstr *MI) const; getBlockHexagonBlockRanges1310b57cec5SDimitry Andric MachineBasicBlock &getBlock() const { return Block; } 1320b57cec5SDimitry Andric IndexType getPrevIndex(IndexType Idx) const; 1330b57cec5SDimitry Andric IndexType getNextIndex(IndexType Idx) const; 1340b57cec5SDimitry Andric void replaceInstr(MachineInstr *OldMI, MachineInstr *NewMI); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric friend raw_ostream &operator<< (raw_ostream &OS, const InstrIndexMap &Map); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric IndexType First, Last; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric private: 1410b57cec5SDimitry Andric MachineBasicBlock &Block; 1420b57cec5SDimitry Andric std::map<IndexType,MachineInstr*> Map; 1430b57cec5SDimitry Andric }; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric using RegToRangeMap = std::map<RegisterRef, RangeList>; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric RegToRangeMap computeLiveMap(InstrIndexMap &IndexMap); 1480b57cec5SDimitry Andric RegToRangeMap computeDeadMap(InstrIndexMap &IndexMap, RegToRangeMap &LiveMap); 1490b57cec5SDimitry Andric static RegisterSet expandToSubRegs(RegisterRef R, 1500b57cec5SDimitry Andric const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric struct PrintRangeMap { PrintRangeMapHexagonBlockRanges::PrintRangeMap1530b57cec5SDimitry Andric PrintRangeMap(const RegToRangeMap &M, const TargetRegisterInfo &I) 1540b57cec5SDimitry Andric : Map(M), TRI(I) {} 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric friend raw_ostream &operator<< (raw_ostream &OS, const PrintRangeMap &P); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric private: 1590b57cec5SDimitry Andric const RegToRangeMap ⤅ 1600b57cec5SDimitry Andric const TargetRegisterInfo &TRI; 1610b57cec5SDimitry Andric }; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric private: 1640b57cec5SDimitry Andric RegisterSet getLiveIns(const MachineBasicBlock &B, 1650b57cec5SDimitry Andric const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric void computeInitialLiveRanges(InstrIndexMap &IndexMap, 1680b57cec5SDimitry Andric RegToRangeMap &LiveMap); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric MachineFunction &MF; 1710b57cec5SDimitry Andric const HexagonSubtarget &HST; 1720b57cec5SDimitry Andric const TargetInstrInfo &TII; 1730b57cec5SDimitry Andric const TargetRegisterInfo &TRI; 1740b57cec5SDimitry Andric BitVector Reserved; 1750b57cec5SDimitry Andric }; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric inline HexagonBlockRanges::IndexType::operator unsigned() const { 1780b57cec5SDimitry Andric assert(Index >= First); 1790b57cec5SDimitry Andric return Index; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator== (unsigned x) const { 1830b57cec5SDimitry Andric return Index == x; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator== (IndexType Idx) const { 1870b57cec5SDimitry Andric return Index == Idx.Index; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator!= (unsigned x) const { 1910b57cec5SDimitry Andric return Index != x; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator!= (IndexType Idx) const { 1950b57cec5SDimitry Andric return Index != Idx.Index; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric inline 1990b57cec5SDimitry Andric HexagonBlockRanges::IndexType HexagonBlockRanges::IndexType::operator++ () { 2000b57cec5SDimitry Andric assert(Index != None); 2010b57cec5SDimitry Andric assert(Index != Exit); 2020b57cec5SDimitry Andric if (Index == Entry) 2030b57cec5SDimitry Andric Index = First; 2040b57cec5SDimitry Andric else 2050b57cec5SDimitry Andric ++Index; 2060b57cec5SDimitry Andric return *this; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator< (unsigned Idx) const { 2100b57cec5SDimitry Andric return operator< (IndexType(Idx)); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator< (IndexType Idx) const { 2140b57cec5SDimitry Andric // !(x < x). 2150b57cec5SDimitry Andric if (Index == Idx.Index) 2160b57cec5SDimitry Andric return false; 2170b57cec5SDimitry Andric // !(None < x) for all x. 2180b57cec5SDimitry Andric // !(x < None) for all x. 2190b57cec5SDimitry Andric if (Index == None || Idx.Index == None) 2200b57cec5SDimitry Andric return false; 2210b57cec5SDimitry Andric // !(Exit < x) for all x. 2220b57cec5SDimitry Andric // !(x < Entry) for all x. 2230b57cec5SDimitry Andric if (Index == Exit || Idx.Index == Entry) 2240b57cec5SDimitry Andric return false; 2250b57cec5SDimitry Andric // Entry < x for all x != Entry. 2260b57cec5SDimitry Andric // x < Exit for all x != Exit. 2270b57cec5SDimitry Andric if (Index == Entry || Idx.Index == Exit) 2280b57cec5SDimitry Andric return true; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric return Index < Idx.Index; 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric inline bool HexagonBlockRanges::IndexType::operator<= (IndexType Idx) const { 2340b57cec5SDimitry Andric return operator==(Idx) || operator<(Idx); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, HexagonBlockRanges::IndexType Idx); 2380b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, 2390b57cec5SDimitry Andric const HexagonBlockRanges::IndexRange &IR); 2400b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, 2410b57cec5SDimitry Andric const HexagonBlockRanges::RangeList &RL); 2420b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, 2430b57cec5SDimitry Andric const HexagonBlockRanges::InstrIndexMap &M); 2440b57cec5SDimitry Andric raw_ostream &operator<< (raw_ostream &OS, 2450b57cec5SDimitry Andric const HexagonBlockRanges::PrintRangeMap &P); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric } // end namespace llvm 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONBLOCKRANGES_H 250