65 #include "llvm/Config/llvm-config.h" 86 #include <system_error> 93 #define DEBUG_TYPE "regalloc" 101 cl::desc(
"Attempt coalescing during PBQP register allocation."),
107 cl::desc(
"Dump graphs for each function/round in the compilation unit."),
122 RegAllocPBQP(
char *cPassID =
nullptr)
131 StringRef getPassName()
const override {
return "PBQP Register Allocator"; }
145 using LI2NodeMap = std::map<const LiveInterval *, unsigned>;
146 using Node2LIMap = std::vector<const LiveInterval *>;
147 using AllowedSet = std::vector<unsigned>;
148 using AllowedSetMap = std::vector<AllowedSet>;
149 using RegPair = std::pair<unsigned, unsigned>;
150 using CoalesceMap = std::map<RegPair, PBQP::PBQPNum>;
151 using RegSet = std::set<unsigned>;
155 RegSet VRegsToAlloc, EmptyIntervalVRegs;
204 if (SpillCost == 0.0)
205 SpillCost = std::numeric_limits<PBQP::PBQPNum>::min();
207 SpillCost += MinSpillCost;
219 using IKey = std::pair<AllowedRegVecPtr, AllowedRegVecPtr>;
222 using IEdgeKey = std::pair<PBQP::GraphBase::NodeId, PBQP::GraphBase::NodeId>;
227 const DisjointAllowedRegsCache &
D)
const {
235 return D.count(IKey(NRegs, MRegs)) > 0;
237 return D.count(IKey(MRegs, NRegs)) > 0;
242 DisjointAllowedRegsCache &D) {
246 assert(NRegs != MRegs &&
"AllowedRegs can not be disjoint with itself");
249 D.insert(IKey(NRegs, MRegs));
251 D.insert(IKey(MRegs, NRegs));
259 std::tuple<LiveInterval*, size_t, PBQP::GraphBase::NodeId>;
261 static SlotIndex getStartPoint(
const IntervalInfo &
I) {
262 return std::get<0>(
I)->segments[std::get<1>(I)].start;
265 static SlotIndex getEndPoint(
const IntervalInfo &
I) {
266 return std::get<0>(
I)->segments[std::get<1>(I)].end;
270 return std::get<2>(
I);
273 static bool lowestStartPoint(
const IntervalInfo &I1,
274 const IntervalInfo &I2) {
277 return getStartPoint(I1) > getStartPoint(I2);
280 static bool lowestEndPoint(
const IntervalInfo &I1,
281 const IntervalInfo &I2) {
294 return std::get<0>(I1)->reg < std::get<0>(I2)->reg;
297 static bool isAtLastSegment(
const IntervalInfo &
I) {
298 return std::get<1>(
I) == std::get<0>(I)->size() - 1;
301 static IntervalInfo nextSegment(
const IntervalInfo &I) {
302 return std::make_tuple(std::get<0>(I), std::get<1>(I) + 1, std::get<2>(I));
324 DisjointAllowedRegsCache
D;
326 using IntervalSet = std::set<IntervalInfo, decltype(&lowestEndPoint)>;
327 using IntervalQueue =
328 std::priority_queue<IntervalInfo, std::vector<IntervalInfo>,
329 decltype(&lowestStartPoint)>;
330 IntervalSet Active(lowestEndPoint);
331 IntervalQueue Inactive(lowestStartPoint);
337 assert(!LI.
empty() &&
"PBQP graph contains node for empty interval");
338 Inactive.push(std::make_tuple(&LI, 0, NId));
341 while (!Inactive.empty()) {
344 IntervalInfo Cur = Inactive.top();
347 IntervalSet::iterator RetireItr = Active.begin();
348 while (RetireItr != Active.end() &&
349 (getEndPoint(*RetireItr) <= getStartPoint(Cur))) {
352 if (!isAtLastSegment(*RetireItr))
353 Inactive.push(nextSegment(*RetireItr));
357 Active.erase(Active.begin(), RetireItr);
361 Cur = Inactive.top();
367 for (
const auto &A : Active) {
372 if (haveDisjointAllowedRegs(G, NId, MId, D))
376 IEdgeKey EK(std::min(NId, MId),
std::max(NId, MId));
381 if (!createInterferenceEdge(G, NId, MId, C))
382 setDisjointAllowedRegs(G, NId, MId, D);
402 *G.
getMetadata().MF.getSubtarget().getRegisterInfo();
407 IKey K(&NRegs, &MRegs);
408 IMatrixCache::iterator I = C.find(K);
415 bool NodesInterfere =
false;
416 for (
unsigned I = 0; I != NRegs.size(); ++
I) {
417 unsigned PRegN = NRegs[
I];
418 for (
unsigned J = 0; J != MRegs.size(); ++J) {
419 unsigned PRegM = MRegs[J];
421 M[I + 1][J + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
422 NodesInterfere =
true;
446 for (
const auto &MBB : MF) {
447 for (
const auto &
MI : MBB) {
449 if (!
CP.setRegisters(&
MI) ||
CP.getSrcReg() ==
CP.getDstReg())
452 unsigned DstReg =
CP.getDstReg();
453 unsigned SrcReg =
CP.getSrcReg();
459 if (!MF.getRegInfo().isAllocatable(DstReg))
464 const PBQPRAGraph::NodeMetadata::AllowedRegVector &
Allowed =
467 unsigned PRegOpt = 0;
468 while (PRegOpt < Allowed.size() && Allowed[PRegOpt] != DstReg)
471 if (PRegOpt < Allowed.size()) {
473 NewCosts[PRegOpt + 1] -= CBenefit;
479 const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed1 =
481 const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed2 =
487 Allowed2->size() + 1, 0);
488 addVirtRegCoalesce(Costs, *Allowed1, *Allowed2, CBenefit);
489 G.
addEdge(N1Id, N2Id, std::move(Costs));
496 addVirtRegCoalesce(Costs, *Allowed1, *Allowed2, CBenefit);
505 void addVirtRegCoalesce(
507 const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed1,
508 const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed2,
510 assert(CostMat.getRows() == Allowed1.size() + 1 &&
"Size mismatch.");
511 assert(CostMat.getCols() == Allowed2.size() + 1 &&
"Size mismatch.");
512 for (
unsigned I = 0; I != Allowed1.size(); ++
I) {
513 unsigned PReg1 = Allowed1[
I];
514 for (
unsigned J = 0; J != Allowed2.size(); ++J) {
515 unsigned PReg2 = Allowed2[J];
517 CostMat[I + 1][J + 1] -= Benefit;
528 void PBQPRAConstraint::anchor() {}
530 void PBQPRAConstraintList::anchor() {}
532 void RegAllocPBQP::getAnalysisUsage(
AnalysisUsage &au)
const {
565 VRegsToAlloc.insert(Reg);
572 for (
unsigned i = 0; CSR[i] != 0; ++i)
585 *G.
getMetadata().MF.getSubtarget().getRegisterInfo();
587 std::vector<unsigned> Worklist(VRegsToAlloc.begin(), VRegsToAlloc.end());
589 std::map<unsigned, std::vector<unsigned>> VRegAllowedMap;
591 while (!Worklist.empty()) {
592 unsigned VReg = Worklist.back();
599 if (VRegLI.
empty()) {
600 EmptyIntervalVRegs.insert(VRegLI.
reg);
601 VRegsToAlloc.erase(VRegLI.
reg);
612 std::vector<unsigned> VRegAllowed;
614 for (
unsigned I = 0; I != RawPRegOrder.
size(); ++
I) {
615 unsigned PReg = RawPRegOrder[
I];
620 if (!RegMaskOverlaps.
empty() && !RegMaskOverlaps.
test(PReg))
624 bool Interference =
false;
635 VRegAllowed.push_back(PReg);
640 if (VRegAllowed.empty()) {
642 spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
643 Worklist.insert(Worklist.end(), NewVRegs.
begin(), NewVRegs.
end());
646 VRegAllowedMap[VReg] = std::move(VRegAllowed);
649 for (
auto &KV : VRegAllowedMap) {
650 auto VReg = KV.first;
654 EmptyIntervalVRegs.insert(VReg);
655 VRegsToAlloc.erase(VReg);
659 auto &VRegAllowed = KV.second;
665 for (
unsigned i = 0; i != VRegAllowed.size(); ++i)
667 NodeCosts[1 + i] += 1.0;
672 G.
getMetadata().getAllowedRegs(std::move(VRegAllowed)));
677 void RegAllocPBQP::spillVReg(
unsigned VReg,
681 VRegsToAlloc.erase(VReg);
683 nullptr, &DeadRemats);
684 VRegSpiller.
spill(LRE);
689 << LRE.getParent().weight <<
", New vregs: ");
698 VRegsToAlloc.insert(LI.
reg);
704 bool RegAllocPBQP::mapPBQPToRegAlloc(
const PBQPRAGraph &G,
714 bool AnotherRoundNeeded =
false;
726 unsigned PReg = G.
getNodeMetadata(NId).getAllowedRegs()[AllocOption - 1];
729 assert(PReg != 0 &&
"Invalid preg selected.");
735 spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
736 AnotherRoundNeeded |= !NewVRegs.
empty();
740 return !AnotherRoundNeeded;
749 for (RegSet::const_iterator
750 I = EmptyIntervalVRegs.begin(),
E = EmptyIntervalVRegs.end();
759 for (
unsigned CandidateReg : RawPRegOrder) {
766 "No un-reserved physical registers in this register class");
776 for (
auto DeadInst : DeadRemats) {
778 DeadInst->eraseFromParent();
793 getAnalysis<MachineBlockFrequencyInfo>();
816 findVRegIntervalsToAlloc(MF, LIS);
820 std::string FullyQualifiedName =
825 if (!VRegsToAlloc.empty()) {
827 std::unique_ptr<PBQPRAConstraintList> ConstraintsRoot =
828 llvm::make_unique<PBQPRAConstraintList>();
829 ConstraintsRoot->addConstraint(llvm::make_unique<SpillCosts>());
830 ConstraintsRoot->addConstraint(llvm::make_unique<Interference>());
832 ConstraintsRoot->addConstraint(llvm::make_unique<Coalescing>());
835 bool PBQPAllocComplete =
false;
838 while (!PBQPAllocComplete) {
842 initializeGraph(G, VRM, *VRegSpiller);
843 ConstraintsRoot->apply(G);
847 std::ostringstream RS;
849 std::string GraphFileName = FullyQualifiedName +
"." + RS.str() +
853 LLVM_DEBUG(
dbgs() <<
"Dumping graph for round " << Round <<
" to \"" 854 << GraphFileName <<
"\"\n");
860 PBQPAllocComplete = mapPBQPToRegAlloc(G, Solution, VRM, *VRegSpiller);
866 finalizeAlloc(MF, LIS, VRM);
867 postOptimization(*VRegSpiller, LIS);
868 VRegsToAlloc.clear();
869 EmptyIntervalVRegs.clear();
884 OS << NId <<
" (" << RegClassName <<
':' <<
printReg(VReg, TRI) <<
')';
888 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 890 for (
auto NId : nodeIds()) {
891 const Vector &Costs = getNodeCosts(NId);
892 assert(Costs.getLength() != 0 &&
"Empty vector in graph.");
897 for (
auto EId : edgeIds()) {
898 NodeId N1Id = getEdgeNode1Id(EId);
899 NodeId N2Id = getEdgeNode2Id(EId);
900 assert(N1Id != N2Id &&
"PBQP graphs should not have self-edges.");
901 const Matrix &M = getEdgeCosts(EId);
902 assert(M.getRows() != 0 &&
"No rows in matrix.");
903 assert(M.getCols() != 0 &&
"No cols in matrix.");
904 OS <<
PrintNodeInfo(N1Id, *
this) <<
' ' << M.getRows() <<
" rows / ";
905 OS <<
PrintNodeInfo(N2Id, *
this) <<
' ' << M.getCols() <<
" cols:\n";
917 for (
auto NId : nodeIds()) {
918 OS <<
" node" << NId <<
" [ label=\"" 920 << getNodeCosts(NId) <<
"\" ]\n";
923 OS <<
" edge [ len=" << nodeIds().size() <<
" ]\n";
924 for (
auto EId : edgeIds()) {
925 OS <<
" node" << getEdgeNode1Id(EId)
926 <<
" -- node" << getEdgeNode2Id(EId)
928 const Matrix &EdgeCosts = getEdgeCosts(EId);
929 for (
unsigned i = 0; i < EdgeCosts.getRows(); ++i) {
930 OS << EdgeCosts.getRowAsVector(i) <<
"\\n";
938 return new RegAllocPBQP(customPassID);
bool reg_nodbg_empty(unsigned RegNo) const
reg_nodbg_empty - Return true if the only instructions using or defining Reg are Debug instructions...
Represents a solution to a PBQP problem.
static Printable PrintNodeInfo(PBQP::RegAlloc::PBQPRAGraph::NodeId NId, const PBQP::RegAlloc::PBQPRAGraph &G)
Create Printable object for node and register info.
Abstract base for classes implementing PBQP register allocation constraints (e.g. ...
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
void RemoveMachineInstrFromMaps(MachineInstr &MI)
This class represents lattice values for constants.
bool empty() const
empty - Tests whether there are no bits in this bitvector.
static unsigned index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs)
Add an edge between the given nodes with the given costs.
Holds a vector of the allowed physical regs for a vreg.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
ArrayRef< MCPhysReg > getRawAllocationOrder(const MachineFunction &MF) const
Returns the preferred order for allocating registers from this register class in MF.
Implements a dense probed hash-table based set.
EdgeId findEdge(NodeId N1Id, NodeId N2Id)
Get the edge connecting two nodes.
LiveInterval - This class represents the liveness of a register, or stack slot.
virtual ~PBQPRAConstraint()=0
bool test(unsigned Idx) const
uint64_t getFrequency() const
Returns the frequency as a fixpoint number scaled by the entry frequency.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
void updateEdgeCosts(EdgeId EId, OtherMatrixT Costs)
Update an edge's cost matrix.
unsigned const TargetRegisterInfo * TRI
NodeId addEdgeBypassingCostAllocator(NodeId N1Id, NodeId N2Id, OtherMatrixPtrT Costs)
Add an edge bypassing the cost allocator.
NodeId getEdgeNode1Id(EdgeId EId) const
Get the first node connected to this edge.
bool checkRegMaskInterference(LiveInterval &LI, BitVector &UsableRegs)
Test if LI is live across any register mask instructions, and compute a bit mask of physical register...
virtual void spill(LiveRangeEdit &LRE)=0
spill - Spill the LRE.getParent() live interval.
FunctionPass * createPBQPRegisterAllocator(char *customPassID=nullptr)
Create a PBQP register allocator instance.
virtual std::unique_ptr< PBQPRAConstraint > getCustomPBQPConstraints() const
Return PBQPConstraint(s) for the target.
const char * getRegClassName(const TargetRegisterClass *Class) const
Returns the name of the register class.
NodeMetadata & getNodeMetadata(NodeId NId)
AnalysisUsage & addRequired()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
typename RegAllocSolverImpl ::GraphMetadata GraphMetadata
A helper class for register coalescers.
void apply(Opt *O, const Mod &M, const Mods &... Ms)
void freezeReservedRegs(const MachineFunction &)
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
static cl::opt< bool > PBQPCoalescing("pbqp-coalescing", cl::desc("Attempt coalescing during PBQP register allocation."), cl::init(false), cl::Hidden)
NodeIdSet nodeIds() const
RegisterRegAlloc class - Track the registration of register allocators.
typename RegAllocSolverImpl ::Matrix Matrix
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
const Matrix & getEdgeCosts(EdgeId EId) const
Get an edge's cost matrix.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
const char * getName(unsigned RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register...
const MatrixPtr & getEdgeCostsPtr(EdgeId EId) const
Get a MatrixPtr to a node's cost matrix.
initializer< Ty > init(const Ty &Val)
void initializeSlotIndexesPass(PassRegistry &)
const TargetRegisterInfo * getTargetRegisterInfo() const
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
unsigned const MachineRegisterInfo * MRI
const Vector & getNodeCosts(NodeId NId) const
Get a node's cost vector.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
void initializeLiveStacksPass(PassRegistry &)
size_t size() const
size - Get the array size.
MachineRegisterInfo & getRegInfo() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const
getblockFreq - Return block frequency.
Represent the analysis usage information of a pass.
void initializeLiveIntervalsPass(PassRegistry &)
FunctionPass * createDefaultPBQPRegisterAllocator()
PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean Quadratic Prograaming (PBQ...
FunctionPass class - This class is used to implement most global optimizations.
static bool isACalleeSavedRegister(unsigned reg, const TargetRegisterInfo &TRI, const MachineFunction &MF)
static RegisterRegAlloc RegisterPBQPRepAlloc("pbqp", "PBQP register allocator", createDefaultPBQPRegisterAllocator)
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
GraphMetadata & getMetadata()
Get a reference to the graph metadata.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
void assignVirt2Phys(unsigned virtReg, MCPhysReg physReg)
creates a mapping for the specified virtual register to the specified physical register ...
void calculateSpillWeightsAndHints(LiveIntervals &LIS, MachineFunction &MF, VirtRegMap *VRM, const MachineLoopInfo &MLI, const MachineBlockFrequencyInfo &MBFI, VirtRegAuxInfo::NormalizingFn norm=normalizeSpillWeight)
Compute spill weights and allocation hints for all virtual register live intervals.
bool regsOverlap(unsigned regA, unsigned regB) const
Returns true if the two registers are equal or alias each other.
AnalysisUsage & addRequiredID(const void *ID)
Module.h This file contains the declarations for the Module class.
void printDot(raw_ostream &OS) const
Print a representation of this graph in DOT format.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
void setPreservesCFG()
This function should be called by the pass, iff they do not:
LiveInterval & getInterval(unsigned Reg)
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
void dump() const
Dump this graph to dbgs().
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
MachineFunctionProperties & set(Property P)
typename RegAllocSolverImpl ::RawVector RawVector
TargetSubtargetInfo - Generic base class for all target subtargets.
void initializeVirtRegMapPass(PassRegistry &)
Spiller * createInlineSpiller(MachineFunctionPass &pass, MachineFunction &mf, VirtRegMap &vrm)
Create and return a spiller that will insert spill code directly instead of deferring though VirtRegM...
static EdgeId invalidEdgeId()
Returns a value representing an invalid (non-existent) edge.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
A raw_ostream that writes to a file descriptor.
bool overlaps(const LiveRange &other) const
overlaps - Return true if the intersection of the two live ranges is not empty.
SmallVectorImpl< unsigned >::const_iterator iterator
Iterator for accessing the new registers added by this edit.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_NODISCARD bool empty() const
StringRef getName() const
Return a constant reference to the value's name.
unsigned getSelection(GraphBase::NodeId nodeId) const
Get a node's selection.
uint64_t getEntryFreq() const
Solution solve(PBQPRAGraph &G)
virtual void postOptimization()
unsigned getSpillOptionIdx()
Spill option index.
typename RegAllocSolverImpl ::Vector Vector
static cl::opt< bool > PBQPDumpGraphs("pbqp-dump-graphs", cl::desc("Dump graphs for each function/round in the compilation unit."), cl::init(false), cl::Hidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static float normalizeSpillWeight(float UseDefFreq, unsigned Size, unsigned NumInstr)
Normalize the spill weight of a live interval.
void clearAllVirt()
clears all virtual to physical register mappings
Module * getParent()
Get the module that this global value is contained inside of...
typename RegAllocSolverImpl ::RawMatrix RawMatrix
simple register Simple Register Coalescing
const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
NodeId addNode(OtherVectorT Costs)
Add a node with the given costs.
Simple wrapper around std::function<void(raw_ostream&)>.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
unsigned getSimpleHint(unsigned VReg) const
getSimpleHint - same as getRegAllocationHint except it will only return a target independent hint...
SlotIndex - An opaque wrapper around machine indexes.
void setNodeCosts(NodeId NId, OtherVectorT Costs)
Set a node's cost vector.
static float normalizePBQPSpillWeight(float UseDefFreq, unsigned Size, unsigned NumInstr)
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
LiveRange & getRegUnit(unsigned Unit)
Return the live range for register unit Unit.
Properties which a MachineFunction may have at a given point in time.
bool isReserved(unsigned PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.