| //===- 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 <cassert> | |
| #include <cstdint> | |
| #include <set> | |
| #include <utility> | |
| 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<MCRegUnit, LaneBitmask> 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<unsigned>(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<RegisterId> PhysicalRegisterInfo::getAliasSet(RegisterRef RR) const { | |
| // Do not include Reg in the alias set. | |
| std::set<RegisterId> 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<RegisterId> PhysicalRegisterInfo::getUnits(RegisterRef RR) const { | |
| std::set<RegisterId> 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<unsigned>(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<unsigned>(31); | |
| if (I + 1 == E && NumRegs % 32 != 0) // Last word may be partial | |
| C &= maskTrailingOnes<unsigned>(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<unsigned>(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<int>(AI.isValid()) == static_cast<int>(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<int>(AI.isValid()) < static_cast<int>(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<MCRegUnit>(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<unsigned>(Unit))) | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool RegisterAggr::hasCoverOf(RegisterRef RR) const { | |
| if (RR.isMask()) | |
| return PRI.getMaskUnits(RR).subsetOf(Units); | |
| for (MCRegUnitMaskIterator U(RR.asMCReg(), &PRI.getTRI()); U.isValid(); ++U) { | |
| auto [Unit, LaneMask] = *U; | |
| if ((LaneMask & RR.Mask).any()) | |
| if (!Units.test(static_cast<unsigned>(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<unsigned>(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<MCRegUnit>(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<MCRegUnit>(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<unsigned>(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<MCRegUnit>(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 |