| //===- 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_LIB_TARGET_HEXAGON_RDFREGISTERS_H |
| #define LLVM_LIB_TARGET_HEXAGON_RDFREGISTERS_H |
| |
| #include "llvm/ADT/BitVector.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/CodeGen/TargetRegisterInfo.h" |
| #include "llvm/MC/LaneBitmask.h" |
| #include <cassert> |
| #include <cstdint> |
| #include <map> |
| #include <set> |
| #include <vector> |
| |
| namespace llvm { |
| |
| class MachineFunction; |
| class raw_ostream; |
| |
| namespace rdf { |
| |
| using RegisterId = uint32_t; |
| |
| // 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 <typename T, unsigned N = 32> |
| 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<T>::const_iterator; |
| |
| const_iterator begin() const { return Map.begin(); } |
| const_iterator end() const { return Map.end(); } |
| |
| private: |
| std::vector<T> Map; |
| }; |
| |
| struct RegisterRef { |
| RegisterId Reg = 0; |
| LaneBitmask Mask = LaneBitmask::getNone(); |
| |
| RegisterRef() = default; |
| explicit RegisterRef(RegisterId R, LaneBitmask M = LaneBitmask::getAll()) |
| : Reg(R), Mask(R != 0 ? M : LaneBitmask::getNone()) {} |
| |
| operator bool() const { |
| return Reg != 0 && Mask.any(); |
| } |
| |
| bool operator== (const RegisterRef &RR) const { |
| return Reg == RR.Reg && Mask == RR.Mask; |
| } |
| |
| bool operator!= (const RegisterRef &RR) const { |
| return !operator==(RR); |
| } |
| |
| bool operator< (const RegisterRef &RR) const { |
| return Reg < RR.Reg || (Reg == RR.Reg && Mask < RR.Mask); |
| } |
| }; |
| |
| |
| struct PhysicalRegisterInfo { |
| PhysicalRegisterInfo(const TargetRegisterInfo &tri, |
| const MachineFunction &mf); |
| |
| static bool isRegMaskId(RegisterId R) { |
| return Register::isStackSlot(R); |
| } |
| |
| RegisterId getRegMaskId(const uint32_t *RM) const { |
| return Register::index2StackSlot(RegMasks.find(RM)); |
| } |
| |
| const uint32_t *getRegMaskBits(RegisterId R) const { |
| return RegMasks.get(Register::stackSlot2Index(R)); |
| } |
| |
| RegisterRef normalize(RegisterRef RR) const; |
| |
| bool alias(RegisterRef RA, RegisterRef RB) const { |
| if (!isRegMaskId(RA.Reg)) |
| return !isRegMaskId(RB.Reg) ? aliasRR(RA, RB) : aliasRM(RA, RB); |
| return !isRegMaskId(RB.Reg) ? aliasRM(RB, RA) : aliasMM(RA, RB); |
| } |
| |
| std::set<RegisterId> getAliasSet(RegisterId Reg) const; |
| |
| RegisterRef getRefForUnit(uint32_t U) const { |
| return RegisterRef(UnitInfos[U].Reg, UnitInfos[U].Mask); |
| } |
| |
| const BitVector &getMaskUnits(RegisterId MaskId) const { |
| return MaskInfos[Register::stackSlot2Index(MaskId)].Units; |
| } |
| |
| RegisterRef mapTo(RegisterRef RR, unsigned R) const; |
| const TargetRegisterInfo &getTRI() const { return TRI; } |
| |
| private: |
| struct RegInfo { |
| const TargetRegisterClass *RegClass = nullptr; |
| }; |
| struct UnitInfo { |
| RegisterId Reg = 0; |
| LaneBitmask Mask; |
| }; |
| struct MaskInfo { |
| BitVector Units; |
| }; |
| |
| const TargetRegisterInfo &TRI; |
| IndexedSet<const uint32_t*> RegMasks; |
| std::vector<RegInfo> RegInfos; |
| std::vector<UnitInfo> UnitInfos; |
| std::vector<MaskInfo> MaskInfos; |
| |
| bool aliasRR(RegisterRef RA, RegisterRef RB) const; |
| bool aliasRM(RegisterRef RR, RegisterRef RM) const; |
| bool aliasMM(RegisterRef RM, RegisterRef RN) const; |
| }; |
| |
| struct RegisterAggr { |
| RegisterAggr(const PhysicalRegisterInfo &pri) |
| : Units(pri.getTRI().getNumRegUnits()), PRI(pri) {} |
| RegisterAggr(const RegisterAggr &RG) = default; |
| |
| bool empty() const { return Units.none(); } |
| bool hasAliasOf(RegisterRef RR) const; |
| bool hasCoverOf(RegisterRef RR) const; |
| |
| 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; |
| |
| void print(raw_ostream &OS) const; |
| |
| struct rr_iterator { |
| using MapType = std::map<RegisterId, LaneBitmask>; |
| |
| private: |
| MapType Masks; |
| MapType::iterator Pos; |
| unsigned Index; |
| const RegisterAggr *Owner; |
| |
| public: |
| rr_iterator(const RegisterAggr &RG, bool End); |
| |
| RegisterRef operator*() const { |
| return RegisterRef(Pos->first, Pos->second); |
| } |
| |
| rr_iterator &operator++() { |
| ++Pos; |
| ++Index; |
| return *this; |
| } |
| |
| bool operator==(const rr_iterator &I) const { |
| assert(Owner == I.Owner); |
| (void)Owner; |
| return Index == I.Index; |
| } |
| |
| bool operator!=(const rr_iterator &I) const { |
| return !(*this == I); |
| } |
| }; |
| |
| rr_iterator rr_begin() const { |
| return rr_iterator(*this, false); |
| } |
| rr_iterator rr_end() const { |
| return rr_iterator(*this, true); |
| } |
| |
| private: |
| BitVector Units; |
| const PhysicalRegisterInfo &PRI; |
| }; |
| |
| // Optionally print the lane mask, if it is not ~0. |
| struct PrintLaneMaskOpt { |
| PrintLaneMaskOpt(LaneBitmask M) : Mask(M) {} |
| LaneBitmask Mask; |
| }; |
| raw_ostream &operator<< (raw_ostream &OS, const PrintLaneMaskOpt &P); |
| |
| } // end namespace rdf |
| |
| } // end namespace llvm |
| |
| #endif // LLVM_LIB_TARGET_HEXAGON_RDFREGISTERS_H |