xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonBlockRanges.h (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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 &Map;
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