//===- RDFRegisters.cpp ---------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #include "llvm/ADT/BitVector.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/RDFRegisters.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/MC/LaneBitmask.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include #include #include #include namespace llvm::rdf { PhysicalRegisterInfo::PhysicalRegisterInfo(const TargetRegisterInfo &tri, const MachineFunction &mf) : TRI(tri) { RegInfos.resize(TRI.getNumRegs()); BitVector BadRC(TRI.getNumRegs()); for (const TargetRegisterClass *RC : TRI.regclasses()) { for (MCPhysReg R : *RC) { RegInfo &RI = RegInfos[R]; if (RI.RegClass != nullptr && !BadRC[R]) { if (RC->LaneMask != RI.RegClass->LaneMask) { BadRC.set(R); RI.RegClass = nullptr; } } else RI.RegClass = RC; } } UnitInfos.resize(TRI.getNumRegUnits()); for (MCRegUnit U : TRI.regunits()) { if (UnitInfos[U].Reg != 0) continue; MCRegUnitRootIterator R(U, &TRI); assert(R.isValid()); RegisterId F = *R; ++R; if (R.isValid()) { UnitInfos[U].Mask = LaneBitmask::getAll(); UnitInfos[U].Reg = F; } else { for (MCRegUnitMaskIterator I(F, &TRI); I.isValid(); ++I) { std::pair P = *I; UnitInfo &UI = UnitInfos[P.first]; UI.Reg = F; UI.Mask = P.second; } } } for (const uint32_t *RM : TRI.getRegMasks()) RegMasks.insert(RM); for (const MachineBasicBlock &B : mf) for (const MachineInstr &In : B) for (const MachineOperand &Op : In.operands()) if (Op.isRegMask()) RegMasks.insert(Op.getRegMask()); MaskInfos.resize(RegMasks.size() + 1); for (uint32_t M = 1, NM = RegMasks.size(); M <= NM; ++M) { BitVector PU(TRI.getNumRegUnits()); const uint32_t *MB = RegMasks.get(M); for (unsigned I = 1, E = TRI.getNumRegs(); I != E; ++I) { if (!(MB[I / 32] & (1u << (I % 32)))) continue; for (MCRegUnit Unit : TRI.regunits(MCRegister::from(I))) PU.set(static_cast(Unit)); } MaskInfos[M].Units = PU.flip(); } AliasInfos.resize(TRI.getNumRegUnits()); for (MCRegUnit U : TRI.regunits()) { BitVector AS(TRI.getNumRegs()); for (MCRegUnitRootIterator R(U, &TRI); R.isValid(); ++R) for (MCPhysReg S : TRI.superregs_inclusive(*R)) AS.set(S); AliasInfos[U].Regs = AS; } } bool PhysicalRegisterInfo::alias(RegisterRef RA, RegisterRef RB) const { return !disjoint(getUnits(RA), getUnits(RB)); } std::set PhysicalRegisterInfo::getAliasSet(RegisterRef RR) const { // Do not include Reg in the alias set. std::set AS; assert(!RR.isUnit() && "No units allowed"); if (RR.isMask()) { // XXX SLOW const uint32_t *MB = getRegMaskBits(RR); for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) { if (MB[i / 32] & (1u << (i % 32))) continue; AS.insert(i); } return AS; } assert(RR.isReg()); for (MCRegAliasIterator AI(RR.asMCReg(), &TRI, false); AI.isValid(); ++AI) AS.insert(*AI); return AS; } std::set PhysicalRegisterInfo::getUnits(RegisterRef RR) const { std::set Units; if (RR.isReg()) { if (RR.Mask.none()) return Units; // Empty for (MCRegUnitMaskIterator UM(RR.asMCReg(), &TRI); UM.isValid(); ++UM) { auto [U, M] = *UM; if ((M & RR.Mask).any()) Units.insert(static_cast(U)); } return Units; } assert(RR.isMask()); unsigned NumRegs = TRI.getNumRegs(); const uint32_t *MB = getRegMaskBits(RR); for (unsigned I = 0, E = (NumRegs + 31) / 32; I != E; ++I) { uint32_t C = ~MB[I]; // Clobbered regs if (I == 0) // Reg 0 should be ignored C &= maskLeadingOnes(31); if (I + 1 == E && NumRegs % 32 != 0) // Last word may be partial C &= maskTrailingOnes(NumRegs % 32); if (C == 0) continue; while (C != 0) { unsigned T = llvm::countr_zero(C); unsigned CR = 32 * I + T; // Clobbered reg for (MCRegUnit U : TRI.regunits(CR)) Units.insert(static_cast(U)); C &= ~(1u << T); } } return Units; } RegisterRef PhysicalRegisterInfo::mapTo(RegisterRef RR, RegisterId R) const { if (RR.Id == R) return RR; if (unsigned Idx = TRI.getSubRegIndex(RegisterRef(R).asMCReg(), RR.asMCReg())) return RegisterRef(R, TRI.composeSubRegIndexLaneMask(Idx, RR.Mask)); if (unsigned Idx = TRI.getSubRegIndex(RR.asMCReg(), RegisterRef(R).asMCReg())) { const RegInfo &RI = RegInfos[R]; LaneBitmask RCM = RI.RegClass ? RI.RegClass->LaneMask : LaneBitmask::getAll(); LaneBitmask M = TRI.reverseComposeSubRegIndexLaneMask(Idx, RR.Mask); return RegisterRef(R, M & RCM); } llvm_unreachable("Invalid arguments: unrelated registers?"); } bool PhysicalRegisterInfo::equal_to(RegisterRef A, RegisterRef B) const { if (!A.isReg() || !B.isReg()) { // For non-regs, or comparing reg and non-reg, use only the Id member. return A.Id == B.Id; } if (A.Id == B.Id) return A.Mask == B.Mask; // Compare reg units lexicographically. MCRegUnitMaskIterator AI(A.asMCReg(), &getTRI()); MCRegUnitMaskIterator BI(B.asMCReg(), &getTRI()); while (AI.isValid() && BI.isValid()) { auto [AReg, AMask] = *AI; auto [BReg, BMask] = *BI; // If both iterators point to a unit contained in both A and B, then // compare the units. if ((AMask & A.Mask).any() && (BMask & B.Mask).any()) { if (AReg != BReg) return false; // Units are equal, move on to the next ones. ++AI; ++BI; continue; } if ((AMask & A.Mask).none()) ++AI; if ((BMask & B.Mask).none()) ++BI; } // One or both have reached the end. return static_cast(AI.isValid()) == static_cast(BI.isValid()); } bool PhysicalRegisterInfo::less(RegisterRef A, RegisterRef B) const { if (!A.isReg() || !B.isReg()) { // For non-regs, or comparing reg and non-reg, use only the Id member. return A.Id < B.Id; } if (A.Id == B.Id) return A.Mask < B.Mask; if (A.Mask == B.Mask) return A.Id < B.Id; // Compare reg units lexicographically. llvm::MCRegUnitMaskIterator AI(A.asMCReg(), &getTRI()); llvm::MCRegUnitMaskIterator BI(B.asMCReg(), &getTRI()); while (AI.isValid() && BI.isValid()) { auto [AReg, AMask] = *AI; auto [BReg, BMask] = *BI; // If both iterators point to a unit contained in both A and B, then // compare the units. if ((AMask & A.Mask).any() && (BMask & B.Mask).any()) { if (AReg != BReg) return AReg < BReg; // Units are equal, move on to the next ones. ++AI; ++BI; continue; } if ((AMask & A.Mask).none()) ++AI; if ((BMask & B.Mask).none()) ++BI; } // One or both have reached the end: assume invalid < valid. return static_cast(AI.isValid()) < static_cast(BI.isValid()); } void PhysicalRegisterInfo::print(raw_ostream &OS, RegisterRef A) const { if (A.isReg()) { MCRegister Reg = A.asMCReg(); if (Reg && Reg.id() < TRI.getNumRegs()) OS << TRI.getName(Reg); else OS << printReg(Reg, &TRI); OS << PrintLaneMaskShort(A.Mask); } else if (A.isUnit()) { OS << printRegUnit(A.asMCRegUnit(), &TRI); } else { unsigned Idx = A.asMaskIdx(); const char *Fmt = Idx < 0x10000 ? "%04x" : "%08x"; OS << "M#" << format(Fmt, Idx); } } void PhysicalRegisterInfo::print(raw_ostream &OS, const RegisterAggr &A) const { OS << '{'; for (unsigned U : A.units()) OS << ' ' << printRegUnit(static_cast(U), &TRI); OS << " }"; } bool RegisterAggr::hasAliasOf(RegisterRef RR) const { if (RR.isMask()) return Units.anyCommon(PRI.getMaskUnits(RR)); for (MCRegUnitMaskIterator U(RR.asMCReg(), &PRI.getTRI()); U.isValid(); ++U) { auto [Unit, LaneMask] = *U; if ((LaneMask & RR.Mask).any()) if (Units.test(static_cast(Unit))) return true; } return false; } bool RegisterAggr::hasCoverOf(RegisterRef RR) const { if (RR.isMask()) { BitVector T(PRI.getMaskUnits(RR)); return T.reset(Units).none(); } for (MCRegUnitMaskIterator U(RR.asMCReg(), &PRI.getTRI()); U.isValid(); ++U) { auto [Unit, LaneMask] = *U; if ((LaneMask & RR.Mask).any()) if (!Units.test(static_cast(Unit))) return false; } return true; } RegisterAggr &RegisterAggr::insert(RegisterRef RR) { if (RR.isMask()) { Units |= PRI.getMaskUnits(RR); return *this; } for (MCRegUnitMaskIterator U(RR.asMCReg(), &PRI.getTRI()); U.isValid(); ++U) { auto [Unit, LaneMask] = *U; if ((LaneMask & RR.Mask).any()) Units.set(static_cast(Unit)); } return *this; } RegisterAggr &RegisterAggr::insert(const RegisterAggr &RG) { Units |= RG.Units; return *this; } RegisterAggr &RegisterAggr::intersect(RegisterRef RR) { return intersect(RegisterAggr(PRI).insert(RR)); } RegisterAggr &RegisterAggr::intersect(const RegisterAggr &RG) { Units &= RG.Units; return *this; } RegisterAggr &RegisterAggr::clear(RegisterRef RR) { return clear(RegisterAggr(PRI).insert(RR)); } RegisterAggr &RegisterAggr::clear(const RegisterAggr &RG) { Units.reset(RG.Units); return *this; } RegisterRef RegisterAggr::intersectWith(RegisterRef RR) const { RegisterAggr T(PRI); T.insert(RR).intersect(*this); if (T.empty()) return RegisterRef(); RegisterRef NR = T.makeRegRef(); assert(NR); return NR; } RegisterRef RegisterAggr::clearIn(RegisterRef RR) const { return RegisterAggr(PRI).insert(RR).clear(*this).makeRegRef(); } RegisterRef RegisterAggr::makeRegRef() const { int U = Units.find_first(); if (U < 0) return RegisterRef(); // Find the set of all registers that are aliased to all the units // in this aggregate. // Get all the registers aliased to the first unit in the bit vector. BitVector Regs = PRI.getUnitAliases(static_cast(U)); U = Units.find_next(U); // For each other unit, intersect it with the set of all registers // aliased that unit. while (U >= 0) { Regs &= PRI.getUnitAliases(static_cast(U)); U = Units.find_next(U); } // If there is at least one register remaining, pick the first one, // and consolidate the masks of all of its units contained in this // aggregate. int F = Regs.find_first(); if (F <= 0) return RegisterRef(); LaneBitmask M; for (MCRegUnitMaskIterator I(F, &PRI.getTRI()); I.isValid(); ++I) { auto [Unit, LaneMask] = *I; if (Units.test(static_cast(Unit))) M |= LaneMask; } return RegisterRef(F, M); } RegisterAggr::ref_iterator::ref_iterator(const RegisterAggr &RG, bool End) : Owner(&RG) { for (int U = RG.Units.find_first(); U >= 0; U = RG.Units.find_next(U)) { RegisterRef R = RG.PRI.getRefForUnit(static_cast(U)); Masks[R.Id] |= R.Mask; } Pos = End ? Masks.end() : Masks.begin(); Index = End ? Masks.size() : 0; } raw_ostream &operator<<(raw_ostream &OS, const RegisterAggr &A) { A.getPRI().print(OS, A); return OS; } raw_ostream &operator<<(raw_ostream &OS, const PrintLaneMaskShort &P) { if (P.Mask.all()) return OS; if (P.Mask.none()) return OS << ":*none*"; LaneBitmask::Type Val = P.Mask.getAsInteger(); if ((Val & 0xffff) == Val) return OS << ':' << format("%04llX", Val); if ((Val & 0xffffffff) == Val) return OS << ':' << format("%08llX", Val); return OS << ':' << PrintLaneMask(P.Mask); } } // namespace llvm::rdf