64#include "llvm/Config/llvm-config.h"
84#include <system_error>
91#define DEBUG_TYPE "regalloc"
99 cl::desc(
"Attempt coalescing during PBQP register allocation."),
105 cl::desc(
"Dump graphs for each function/round in the compilation unit."),
120 RegAllocPBQP(
char *cPassID =
nullptr)
139 MachineFunctionProperties::Property::NoPHIs);
144 MachineFunctionProperties::Property::IsSSA);
148 using RegSet = std::set<Register>;
152 RegSet VRegsToAlloc, EmptyIntervalVRegs;
186char RegAllocPBQP::ID = 0;
198 for (
auto NId :
G.nodeIds()) {
201 if (SpillCost == 0.0)
202 SpillCost = std::numeric_limits<PBQP::PBQPNum>::min();
204 SpillCost += MinSpillCost;
207 G.setNodeCosts(NId, std::move(NodeCosts));
216 using IKey = std::pair<AllowedRegVecPtr, AllowedRegVecPtr>;
219 using IEdgeKey = std::pair<PBQP::GraphBase::NodeId, PBQP::GraphBase::NodeId>;
224 const DisjointAllowedRegsCache &
D)
const {
225 const auto *NRegs = &
G.getNodeMetadata(NId).getAllowedRegs();
226 const auto *MRegs = &
G.getNodeMetadata(MId).getAllowedRegs();
232 return D.contains(IKey(NRegs, MRegs));
234 return D.contains(IKey(MRegs, NRegs));
239 DisjointAllowedRegsCache &
D) {
240 const auto *NRegs = &
G.getNodeMetadata(NId).getAllowedRegs();
241 const auto *MRegs = &
G.getNodeMetadata(MId).getAllowedRegs();
243 assert(NRegs != MRegs &&
"AllowedRegs can not be disjoint with itself");
246 D.insert(IKey(NRegs, MRegs));
248 D.insert(IKey(MRegs, NRegs));
256 std::tuple<LiveInterval*, size_t, PBQP::GraphBase::NodeId>;
258 static SlotIndex getStartPoint(
const IntervalInfo &
I) {
259 return std::get<0>(
I)->segments[std::get<1>(
I)].start;
262 static SlotIndex getEndPoint(
const IntervalInfo &
I) {
263 return std::get<0>(
I)->segments[std::get<1>(
I)].end;
267 return std::get<2>(
I);
270 static bool lowestStartPoint(
const IntervalInfo &I1,
271 const IntervalInfo &I2) {
274 return getStartPoint(I1) > getStartPoint(I2);
277 static bool lowestEndPoint(
const IntervalInfo &I1,
278 const IntervalInfo &I2) {
291 return std::get<0>(I1)->reg() < std::get<0>(I2)->reg();
294 static bool isAtLastSegment(
const IntervalInfo &
I) {
295 return std::get<1>(
I) == std::get<0>(
I)->size() - 1;
298 static IntervalInfo nextSegment(
const IntervalInfo &
I) {
299 return std::make_tuple(std::get<0>(
I), std::get<1>(
I) + 1, std::get<2>(
I));
321 DisjointAllowedRegsCache
D;
323 using IntervalSet = std::set<IntervalInfo,
decltype(&lowestEndPoint)>;
324 using IntervalQueue =
325 std::priority_queue<IntervalInfo, std::vector<IntervalInfo>,
326 decltype(&lowestStartPoint)>;
327 IntervalSet Active(lowestEndPoint);
328 IntervalQueue Inactive(lowestStartPoint);
331 for (
auto NId :
G.nodeIds()) {
332 Register VReg =
G.getNodeMetadata(NId).getVReg();
334 assert(!LI.
empty() &&
"PBQP graph contains node for empty interval");
335 Inactive.push(std::make_tuple(&LI, 0, NId));
338 while (!Inactive.empty()) {
341 IntervalInfo Cur = Inactive.top();
344 IntervalSet::iterator RetireItr = Active.begin();
345 while (RetireItr != Active.end() &&
346 (getEndPoint(*RetireItr) <= getStartPoint(Cur))) {
349 if (!isAtLastSegment(*RetireItr))
350 Inactive.push(nextSegment(*RetireItr));
354 Active.erase(Active.begin(), RetireItr);
358 Cur = Inactive.top();
364 for (
const auto &
A : Active) {
369 if (haveDisjointAllowedRegs(
G, NId, MId,
D))
373 IEdgeKey EK(std::min(NId, MId), std::max(NId, MId));
378 if (!createInterferenceEdge(
G, NId, MId,
C))
379 setDisjointAllowedRegs(
G, NId, MId,
D);
399 *
G.getMetadata().MF.getSubtarget().getRegisterInfo();
400 const auto &NRegs =
G.getNodeMetadata(NId).getAllowedRegs();
401 const auto &MRegs =
G.getNodeMetadata(MId).getAllowedRegs();
404 IKey
K(&NRegs, &MRegs);
407 G.addEdgeBypassingCostAllocator(NId, MId,
I->second);
412 bool NodesInterfere =
false;
413 for (
unsigned I = 0;
I != NRegs.size(); ++
I) {
415 for (
unsigned J = 0; J != MRegs.size(); ++J) {
417 if (
TRI.regsOverlap(PRegN, PRegM)) {
418 M[
I + 1][J + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
419 NodesInterfere =
true;
428 C[
K] =
G.getEdgeCostsPtr(EId);
443 for (
const auto &
MBB : MF) {
444 for (
const auto &
MI :
MBB) {
446 if (!
CP.setRegisters(&
MI) ||
CP.getSrcReg() ==
CP.getDstReg())
455 if (!MF.getRegInfo().isAllocatable(DstReg))
460 const PBQPRAGraph::NodeMetadata::AllowedRegVector &
Allowed =
461 G.getNodeMetadata(NId).getAllowedRegs();
463 unsigned PRegOpt = 0;
464 while (PRegOpt <
Allowed.size() && Allowed[PRegOpt].id() != DstReg)
467 if (PRegOpt <
Allowed.size()) {
469 NewCosts[PRegOpt + 1] -= CBenefit;
470 G.setNodeCosts(NId, std::move(NewCosts));
475 const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed1 =
476 &
G.getNodeMetadata(N1Id).getAllowedRegs();
477 const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed2 =
478 &
G.getNodeMetadata(N2Id).getAllowedRegs();
481 if (EId ==
G.invalidEdgeId()) {
483 Allowed2->size() + 1, 0);
484 addVirtRegCoalesce(Costs, *Allowed1, *Allowed2, CBenefit);
485 G.addEdge(N1Id, N2Id, std::move(Costs));
487 if (
G.getEdgeNode1Id(EId) == N2Id) {
492 addVirtRegCoalesce(Costs, *Allowed1, *Allowed2, CBenefit);
493 G.updateEdgeCosts(EId, std::move(Costs));
501 void addVirtRegCoalesce(
503 const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed1,
504 const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed2,
506 assert(CostMat.getRows() == Allowed1.size() + 1 &&
"Size mismatch.");
507 assert(CostMat.getCols() == Allowed2.size() + 1 &&
"Size mismatch.");
508 for (
unsigned I = 0;
I != Allowed1.size(); ++
I) {
510 for (
unsigned J = 0; J != Allowed2.size(); ++J) {
513 CostMat[
I + 1][J + 1] -= Benefit;
521 float normalize(
float UseDefFreq,
unsigned Size,
unsigned NumInstr)
override {
538void PBQPRAConstraint::anchor() {}
540void PBQPRAConstraintList::anchor() {}
542void RegAllocPBQP::getAnalysisUsage(
AnalysisUsage &au)
const {
571 for (
unsigned I = 0, E =
MRI.getNumVirtRegs();
I != E; ++
I) {
573 if (
MRI.reg_nodbg_empty(Reg))
575 VRegsToAlloc.insert(Reg);
583 for (
unsigned i = 0; CSR[i] != 0; ++i)
584 if (
TRI.regsOverlap(Reg, CSR[i]))
596 *
G.getMetadata().MF.getSubtarget().getRegisterInfo();
598 std::vector<Register> Worklist(VRegsToAlloc.begin(), VRegsToAlloc.end());
600 std::map<Register, std::vector<MCRegister>> VRegAllowedMap;
602 while (!Worklist.empty()) {
610 if (VRegLI.
empty()) {
611 EmptyIntervalVRegs.insert(VRegLI.
reg());
612 VRegsToAlloc.erase(VRegLI.
reg());
623 std::vector<MCRegister> VRegAllowed;
627 if (
MRI.isReserved(PReg))
631 if (!RegMaskOverlaps.
empty() && !RegMaskOverlaps.
test(PReg))
635 bool Interference =
false;
646 VRegAllowed.push_back(PReg);
651 if (VRegAllowed.empty()) {
653 spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
658 VRegAllowedMap[VReg.
id()] = std::move(VRegAllowed);
661 for (
auto &KV : VRegAllowedMap) {
662 auto VReg = KV.first;
666 EmptyIntervalVRegs.insert(VReg);
667 VRegsToAlloc.erase(VReg);
671 auto &VRegAllowed = KV.second;
677 for (
unsigned i = 0; i != VRegAllowed.size(); ++i)
679 NodeCosts[1 + i] += 1.0;
682 G.getNodeMetadata(NId).setVReg(VReg);
683 G.getNodeMetadata(NId).setAllowedRegs(
684 G.getMetadata().getAllowedRegs(std::move(VRegAllowed)));
685 G.getMetadata().setNodeIdForVReg(VReg, NId);
689void RegAllocPBQP::spillVReg(
Register VReg,
693 VRegsToAlloc.erase(VReg);
695 nullptr, &DeadRemats);
696 VRegSpiller.
spill(LRE);
701 << LRE.getParent().weight() <<
", New vregs: ");
709 VRegsToAlloc.insert(LI.
reg());
715bool RegAllocPBQP::mapPBQPToRegAlloc(
const PBQPRAGraph &
G,
725 bool AnotherRoundNeeded =
false;
732 for (
auto NId :
G.nodeIds()) {
733 Register VReg =
G.getNodeMetadata(NId).getVReg();
737 MCRegister PReg =
G.getNodeMetadata(NId).getAllowedRegs()[AllocOpt - 1];
739 <<
TRI.getName(PReg) <<
"\n");
740 assert(PReg != 0 &&
"Invalid preg selected.");
746 spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
747 AnotherRoundNeeded |= !NewVRegs.
empty();
751 return !AnotherRoundNeeded;
760 for (
const Register &R : EmptyIntervalVRegs) {
768 for (
MCRegister CandidateReg : RawPRegOrder) {
775 "No un-reserved physical registers in this register class");
785 for (
auto *DeadInst : DeadRemats) {
787 DeadInst->eraseFromParent();
793 LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
795 getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
797 VirtRegMap &VRM = getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
799 PBQPVirtRegAuxInfo VRAI(
800 MF, LIS, VRM, getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI);
801 VRAI.calculateSpillWeightsAndHints();
808 MF, LIS, VRM, getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI);
809 std::unique_ptr<Spiller> VRegSpiller(
826 findVRegIntervalsToAlloc(MF, LIS);
830 std::string FullyQualifiedName =
831 F.getParent()->getModuleIdentifier() +
"." +
F.getName().str();
835 if (!VRegsToAlloc.empty()) {
837 std::unique_ptr<PBQPRAConstraintList> ConstraintsRoot =
838 std::make_unique<PBQPRAConstraintList>();
839 ConstraintsRoot->addConstraint(std::make_unique<SpillCosts>());
840 ConstraintsRoot->addConstraint(std::make_unique<Interference>());
842 ConstraintsRoot->addConstraint(std::make_unique<Coalescing>());
845 bool PBQPAllocComplete =
false;
848 while (!PBQPAllocComplete) {
853 initializeGraph(
G, VRM, *VRegSpiller);
854 ConstraintsRoot->apply(
G);
858 std::ostringstream RS;
860 std::string GraphFileName = FullyQualifiedName +
"." + RS.str() +
864 LLVM_DEBUG(
dbgs() <<
"Dumping graph for round " << Round <<
" to \""
865 << GraphFileName <<
"\"\n");
871 PBQPAllocComplete = mapPBQPToRegAlloc(
G, Solution, VRM, *VRegSpiller);
877 finalizeAlloc(MF, LIS, VRM);
878 postOptimization(*VRegSpiller, LIS);
879 VRegsToAlloc.clear();
880 EmptyIntervalVRegs.clear();
893 Register VReg =
G.getNodeMetadata(NId).getVReg();
894 const char *RegClassName =
TRI->getRegClassName(
MRI.getRegClass(VReg));
895 OS << NId <<
" (" << RegClassName <<
':' <<
printReg(VReg,
TRI) <<
')';
899#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
903 assert(Costs.getLength() != 0 &&
"Empty vector in graph.");
911 assert(N1Id != N2Id &&
"PBQP graphs should not have self-edges.");
913 assert(M.getRows() != 0 &&
"No rows in matrix.");
914 assert(M.getCols() != 0 &&
"No cols in matrix.");
928 for (
auto NId : nodeIds()) {
929 OS <<
" node" << NId <<
" [ label=\""
931 << getNodeCosts(NId) <<
"\" ]\n";
934 OS <<
" edge [ len=" << nodeIds().size() <<
" ]\n";
935 for (
auto EId : edgeIds()) {
936 OS <<
" node" << getEdgeNode1Id(EId)
937 <<
" -- node" << getEdgeNode2Id(EId)
939 const Matrix &EdgeCosts = getEdgeCosts(EId);
940 for (
unsigned i = 0; i < EdgeCosts.getRows(); ++i) {
941 OS << EdgeCosts.getRowAsVector(i) <<
"\\n";
949 return new RegAllocPBQP(customPassID);
unsigned const MachineRegisterInfo * MRI
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
Module.h This file contains the declarations for the Module class.
unsigned const TargetRegisterInfo * TRI
static Printable PrintNodeInfo(PBQP::RegAlloc::PBQPRAGraph::NodeId NId, const PBQP::RegAlloc::PBQPRAGraph &G)
Create Printable object for node and register info.
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)
static cl::opt< bool > PBQPCoalescing("pbqp-coalescing", cl::desc("Attempt coalescing during PBQP register allocation."), cl::init(false), cl::Hidden)
static bool isACalleeSavedRegister(MCRegister Reg, const TargetRegisterInfo &TRI, const MachineFunction &MF)
static RegisterRegAlloc RegisterPBQPRepAlloc("pbqp", "PBQP register allocator", createDefaultPBQPRegisterAllocator)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequiredID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool test(unsigned Idx) const
bool empty() const
empty - Tests whether there are no bits in this bitvector.
A helper class for register coalescers.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Implements a dense probed hash-table based set.
FunctionPass class - This class is used to implement most global optimizations.
LiveInterval - This class represents the liveness of a register, or stack slot.
bool checkRegMaskInterference(const LiveInterval &LI, BitVector &UsableRegs)
Test if LI is live across any register mask instructions, and compute a bit mask of physical register...
void RemoveMachineInstrFromMaps(MachineInstr &MI)
LiveRange & getRegUnit(unsigned Unit)
Return the live range for register unit Unit.
LiveInterval & getInterval(Register Reg)
bool overlaps(const LiveRange &other) const
overlaps - Return true if the intersection of the two live ranges is not empty.
Wrapper class representing physical registers. Should be passed by value.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
double getBlockFreqRelativeToEntryBlock(const MachineBasicBlock *MBB) const
Compute the frequency of the block, relative to the entry block.
Analysis pass which computes a MachineDominatorTree.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual MachineFunctionProperties getClearedProperties() const
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
void freezeReservedRegs()
freezeReservedRegs - Called by the register allocator to freeze the set of reserved registers before ...
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
Abstract base for classes implementing PBQP register allocation constraints (e.g.
virtual ~PBQPRAConstraint()=0
virtual void apply(PBQPRAGraph &G)=0
typename SolverT::GraphMetadata GraphMetadata
typename SolverT::Matrix Matrix
NodeId getEdgeNode2Id(EdgeId EId) const
Get the second node connected to this edge.
NodeId getEdgeNode1Id(EdgeId EId) const
Get the first node connected to this edge.
const Matrix & getEdgeCosts(EdgeId EId) const
Get an edge's cost matrix.
typename SolverT::Vector Vector
NodeIdSet nodeIds() const
typename SolverT::RawMatrix RawMatrix
typename SolverT::RawVector RawVector
const Vector & getNodeCosts(NodeId NId) const
Get a node's cost vector.
EdgeIdSet edgeIds() const
Holds a vector of the allowed physical regs for a vreg.
void printDot(raw_ostream &OS) const
Print a representation of this graph in DOT format.
void dump() const
Dump this graph to dbgs().
Represents a solution to a PBQP problem.
unsigned getSelection(GraphBase::NodeId nodeId) const
Get a node's selection.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Simple wrapper around std::function<void(raw_ostream&)>.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr unsigned id() const
SlotIndex - An opaque wrapper around machine indexes.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
virtual void spill(LiveRangeEdit &LRE)=0
spill - Spill the LRE.getParent() live interval.
virtual void postOptimization()
StringRef - Represent a constant reference to a string, i.e.
ArrayRef< MCPhysReg > getRawAllocationOrder(const MachineFunction &MF) const
Returns the preferred order for allocating registers from this register class in MF.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual std::unique_ptr< PBQPRAConstraint > getCustomPBQPConstraints() const
Return PBQPConstraint(s) for the target.
Calculate auxiliary information for a virtual register such as its spill weight and allocation hint.
virtual float normalize(float UseDefFreq, unsigned Size, unsigned NumInstr)
Weight normalization function.
void clearAllVirt()
clears all virtual to physical register mappings
MachineRegisterInfo & getRegInfo() const
void assignVirt2Phys(Register virtReg, MCPhysReg physReg)
creates a mapping for the specified virtual register to the specified physical register
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Solution solve(PBQPRAGraph &G)
unsigned getSpillOptionIdx()
Spill option index.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void initializeVirtRegMapWrapperLegacyPass(PassRegistry &)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Spiller * createInlineSpiller(MachineFunctionPass &Pass, MachineFunction &MF, VirtRegMap &VRM, VirtRegAuxInfo &VRAI)
Create and return a spiller that will insert spill code directly instead of deferring though VirtRegM...
void initializeLiveStacksWrapperLegacyPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createDefaultPBQPRegisterAllocator()
PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean Quadratic Prograaming (PBQ...
void initializeLiveIntervalsWrapperPassPass(PassRegistry &)
FunctionPass * createPBQPRegisterAllocator(char *customPassID=nullptr)
Create a PBQP register allocator instance.
void initializeSlotIndexesWrapperPassPass(PassRegistry &)
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.