//===- RDFRegisters.h -------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_RDFREGISTERS_H #define LLVM_CODEGEN_RDFREGISTERS_H #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCRegister.h" #include #include #include #include #include namespace llvm { class MachineFunction; class raw_ostream; namespace rdf { struct RegisterAggr; using RegisterId = uint32_t; template bool disjoint(const std::set &A, const std::set &B) { auto ItA = A.begin(), EndA = A.end(); auto ItB = B.begin(), EndB = B.end(); while (ItA != EndA && ItB != EndB) { if (*ItA < *ItB) ++ItA; else if (*ItB < *ItA) ++ItB; else return false; } return true; } // Template class for a map translating uint32_t into arbitrary types. // The map will act like an indexed set: upon insertion of a new object, // it will automatically assign a new index to it. Index of 0 is treated // as invalid and is never allocated. template struct IndexedSet { IndexedSet() { Map.reserve(N); } T get(uint32_t Idx) const { // Index Idx corresponds to Map[Idx-1]. assert(Idx != 0 && !Map.empty() && Idx - 1 < Map.size()); return Map[Idx - 1]; } uint32_t insert(T Val) { // Linear search. auto F = llvm::find(Map, Val); if (F != Map.end()) return F - Map.begin() + 1; Map.push_back(Val); return Map.size(); // Return actual_index + 1. } uint32_t find(T Val) const { auto F = llvm::find(Map, Val); assert(F != Map.end()); return F - Map.begin() + 1; } uint32_t size() const { return Map.size(); } using const_iterator = typename std::vector::const_iterator; const_iterator begin() const { return Map.begin(); } const_iterator end() const { return Map.end(); } private: std::vector Map; }; struct RegisterRef { private: static constexpr RegisterId MaskFlag = 1u << 30; static constexpr RegisterId UnitFlag = 1u << 31; public: RegisterId Id = 0; LaneBitmask Mask = LaneBitmask::getNone(); // Only for registers. constexpr RegisterRef() = default; constexpr explicit RegisterRef(RegisterId R, LaneBitmask M = LaneBitmask::getAll()) : Id(R), Mask(isRegId(R) && R != 0 ? M : LaneBitmask::getNone()) {} // Classify null register as a "register". constexpr bool isReg() const { return Id == 0 || isRegId(Id); } constexpr bool isUnit() const { return isUnitId(Id); } constexpr bool isMask() const { return isMaskId(Id); } constexpr MCRegister asMCReg() const { assert(isReg()); return Id; } constexpr MCRegUnit asMCRegUnit() const { assert(isUnit()); return static_cast(Id & ~UnitFlag); } constexpr unsigned asMaskIdx() const { assert(isMask()); return Id & ~MaskFlag; } explicit constexpr operator bool() const { return !isReg() || (Id != 0 && Mask.any()); } size_t hash() const { return std::hash{}(Id) ^ std::hash{}(Mask.getAsInteger()); } static constexpr bool isRegId(RegisterId Id) { return Id != 0 && !(Id & UnitFlag) && !(Id & MaskFlag); } static constexpr bool isUnitId(RegisterId Id) { return Id & UnitFlag; } static constexpr bool isMaskId(RegisterId Id) { return Id & MaskFlag; } static constexpr RegisterId toUnitId(unsigned Idx) { return Idx | UnitFlag; } static constexpr RegisterId toMaskId(unsigned Idx) { return Idx | MaskFlag; } bool operator<(RegisterRef) const = delete; bool operator==(RegisterRef) const = delete; bool operator!=(RegisterRef) const = delete; }; struct PhysicalRegisterInfo { PhysicalRegisterInfo(const TargetRegisterInfo &tri, const MachineFunction &mf); RegisterId getRegMaskId(const uint32_t *RM) const { return RegisterRef::toMaskId(RegMasks.find(RM)); } const uint32_t *getRegMaskBits(RegisterRef RR) const { return RegMasks.get(RR.asMaskIdx()); } bool alias(RegisterRef RA, RegisterRef RB) const; // Returns the set of aliased physical registers. std::set getAliasSet(RegisterRef RR) const; RegisterRef getRefForUnit(MCRegUnit U) const { return RegisterRef(UnitInfos[U].Reg, UnitInfos[U].Mask); } const BitVector &getMaskUnits(RegisterRef RR) const { return MaskInfos[RR.asMaskIdx()].Units; } std::set getUnits(RegisterRef RR) const; const BitVector &getUnitAliases(MCRegUnit U) const { return AliasInfos[U].Regs; } RegisterRef mapTo(RegisterRef RR, RegisterId R) const; const TargetRegisterInfo &getTRI() const { return TRI; } bool equal_to(RegisterRef A, RegisterRef B) const; bool less(RegisterRef A, RegisterRef B) const; void print(raw_ostream &OS, RegisterRef A) const; void print(raw_ostream &OS, const RegisterAggr &A) const; private: struct RegInfo { const TargetRegisterClass *RegClass = nullptr; }; struct UnitInfo { RegisterId Reg = 0; LaneBitmask Mask; }; struct MaskInfo { BitVector Units; }; struct AliasInfo { BitVector Regs; }; const TargetRegisterInfo &TRI; IndexedSet RegMasks; std::vector RegInfos; IndexedMap UnitInfos; std::vector MaskInfos; IndexedMap AliasInfos; }; struct RegisterRefEqualTo { constexpr RegisterRefEqualTo(const llvm::rdf::PhysicalRegisterInfo &pri) : PRI(&pri) {} bool operator()(llvm::rdf::RegisterRef A, llvm::rdf::RegisterRef B) const { return PRI->equal_to(A, B); } private: // Make it a pointer just in case. See comment in `RegisterRefLess` below. const llvm::rdf::PhysicalRegisterInfo *PRI; }; struct RegisterRefLess { constexpr RegisterRefLess(const llvm::rdf::PhysicalRegisterInfo &pri) : PRI(&pri) {} bool operator()(llvm::rdf::RegisterRef A, llvm::rdf::RegisterRef B) const { return PRI->less(A, B); } private: // Make it a pointer because apparently some versions of MSVC use std::swap // on the comparator object. const llvm::rdf::PhysicalRegisterInfo *PRI; }; struct RegisterAggr { RegisterAggr(const PhysicalRegisterInfo &pri) : Units(pri.getTRI().getNumRegUnits()), PRI(pri) {} RegisterAggr(const RegisterAggr &RG) = default; unsigned size() const { return Units.count(); } bool empty() const { return Units.none(); } bool hasAliasOf(RegisterRef RR) const; bool hasCoverOf(RegisterRef RR) const; const PhysicalRegisterInfo &getPRI() const { return PRI; } bool operator==(const RegisterAggr &A) const { return DenseMapInfo::isEqual(Units, A.Units); } static bool isCoverOf(RegisterRef RA, RegisterRef RB, const PhysicalRegisterInfo &PRI) { return RegisterAggr(PRI).insert(RA).hasCoverOf(RB); } RegisterAggr &insert(RegisterRef RR); RegisterAggr &insert(const RegisterAggr &RG); RegisterAggr &intersect(RegisterRef RR); RegisterAggr &intersect(const RegisterAggr &RG); RegisterAggr &clear(RegisterRef RR); RegisterAggr &clear(const RegisterAggr &RG); RegisterRef intersectWith(RegisterRef RR) const; RegisterRef clearIn(RegisterRef RR) const; RegisterRef makeRegRef() const; size_t hash() const { return DenseMapInfo::getHashValue(Units); } struct ref_iterator { using MapType = std::map; private: MapType Masks; MapType::iterator Pos; unsigned Index; const RegisterAggr *Owner; public: ref_iterator(const RegisterAggr &RG, bool End); RegisterRef operator*() const { return RegisterRef(Pos->first, Pos->second); } ref_iterator &operator++() { ++Pos; ++Index; return *this; } bool operator==(const ref_iterator &I) const { assert(Owner == I.Owner); (void)Owner; return Index == I.Index; } bool operator!=(const ref_iterator &I) const { return !(*this == I); } }; ref_iterator ref_begin() const { return ref_iterator(*this, false); } ref_iterator ref_end() const { return ref_iterator(*this, true); } using unit_iterator = BitVector::const_set_bits_iterator; unit_iterator unit_begin() const { return Units.set_bits_begin(); } unit_iterator unit_end() const { return Units.set_bits_end(); } iterator_range refs() const { return make_range(ref_begin(), ref_end()); } iterator_range units() const { return make_range(unit_begin(), unit_end()); } private: BitVector Units; const PhysicalRegisterInfo &PRI; }; // This is really a std::map, except that it provides a non-trivial // default constructor to the element accessed via []. template struct RegisterAggrMap { RegisterAggrMap(const PhysicalRegisterInfo &pri) : Empty(pri) {} RegisterAggr &operator[](KeyType Key) { return Map.emplace(Key, Empty).first->second; } auto begin() { return Map.begin(); } auto end() { return Map.end(); } auto begin() const { return Map.begin(); } auto end() const { return Map.end(); } auto find(const KeyType &Key) const { return Map.find(Key); } private: RegisterAggr Empty; std::map Map; public: using key_type = typename decltype(Map)::key_type; using mapped_type = typename decltype(Map)::mapped_type; using value_type = typename decltype(Map)::value_type; }; raw_ostream &operator<<(raw_ostream &OS, const RegisterAggr &A); // Print the lane mask in a short form (or not at all if all bits are set). struct PrintLaneMaskShort { PrintLaneMaskShort(LaneBitmask M) : Mask(M) {} LaneBitmask Mask; }; raw_ostream &operator<<(raw_ostream &OS, const PrintLaneMaskShort &P); } // end namespace rdf } // end namespace llvm namespace std { template <> struct hash { size_t operator()(llvm::rdf::RegisterRef A) const { // return A.hash(); } }; template <> struct hash { size_t operator()(const llvm::rdf::RegisterAggr &A) const { // return A.hash(); } }; } // namespace std namespace llvm::rdf { using RegisterSet = std::set; } // namespace llvm::rdf #endif // LLVM_CODEGEN_RDFREGISTERS_H