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)
146 using RegSet = std::set<Register>;
150 RegSet VRegsToAlloc, EmptyIntervalVRegs;
184char RegAllocPBQP::ID = 0;
196 for (
auto NId :
G.nodeIds()) {
199 if (SpillCost == 0.0)
200 SpillCost = std::numeric_limits<PBQP::PBQPNum>::min();
202 SpillCost += MinSpillCost;
205 G.setNodeCosts(NId, std::move(NodeCosts));
214 using IKey = std::pair<AllowedRegVecPtr, AllowedRegVecPtr>;
217 using IEdgeKey = std::pair<PBQP::GraphBase::NodeId, PBQP::GraphBase::NodeId>;
222 const DisjointAllowedRegsCache &
D)
const {
223 const auto *NRegs = &
G.getNodeMetadata(NId).getAllowedRegs();
224 const auto *MRegs = &
G.getNodeMetadata(MId).getAllowedRegs();
230 return D.contains(IKey(NRegs, MRegs));
232 return D.contains(IKey(MRegs, NRegs));
237 DisjointAllowedRegsCache &
D) {
238 const auto *NRegs = &
G.getNodeMetadata(NId).getAllowedRegs();
239 const auto *MRegs = &
G.getNodeMetadata(MId).getAllowedRegs();
241 assert(NRegs != MRegs &&
"AllowedRegs can not be disjoint with itself");
244 D.insert(IKey(NRegs, MRegs));
246 D.insert(IKey(MRegs, NRegs));
254 std::tuple<LiveInterval*, size_t, PBQP::GraphBase::NodeId>;
256 static SlotIndex getStartPoint(
const IntervalInfo &
I) {
257 return std::get<0>(
I)->segments[std::get<1>(
I)].start;
260 static SlotIndex getEndPoint(
const IntervalInfo &
I) {
261 return std::get<0>(
I)->segments[std::get<1>(
I)].end;
265 return std::get<2>(
I);
268 static bool lowestStartPoint(
const IntervalInfo &I1,
269 const IntervalInfo &I2) {
272 return getStartPoint(I1) > getStartPoint(I2);
275 static bool lowestEndPoint(
const IntervalInfo &I1,
276 const IntervalInfo &I2) {
289 return std::get<0>(I1)->reg() < std::get<0>(I2)->reg();
292 static bool isAtLastSegment(
const IntervalInfo &
I) {
293 return std::get<1>(
I) == std::get<0>(
I)->size() - 1;
296 static IntervalInfo nextSegment(
const IntervalInfo &
I) {
297 return std::make_tuple(std::get<0>(
I), std::get<1>(
I) + 1, std::get<2>(
I));
319 DisjointAllowedRegsCache
D;
321 using IntervalSet = std::set<IntervalInfo,
decltype(&lowestEndPoint)>;
322 using IntervalQueue =
323 std::priority_queue<IntervalInfo, std::vector<IntervalInfo>,
324 decltype(&lowestStartPoint)>;
325 IntervalSet
Active(lowestEndPoint);
326 IntervalQueue Inactive(lowestStartPoint);
329 for (
auto NId :
G.nodeIds()) {
330 Register VReg =
G.getNodeMetadata(NId).getVReg();
332 assert(!LI.
empty() &&
"PBQP graph contains node for empty interval");
333 Inactive.push(std::make_tuple(&LI, 0, NId));
336 while (!Inactive.empty()) {
339 IntervalInfo Cur = Inactive.top();
342 IntervalSet::iterator RetireItr =
Active.begin();
343 while (RetireItr !=
Active.end() &&
344 (getEndPoint(*RetireItr) <= getStartPoint(Cur))) {
347 if (!isAtLastSegment(*RetireItr))
348 Inactive.push(nextSegment(*RetireItr));
356 Cur = Inactive.top();
362 for (
const auto &
A : Active) {
367 if (haveDisjointAllowedRegs(
G, NId, MId,
D))
371 IEdgeKey EK(std::min(NId, MId), std::max(NId, MId));
376 if (!createInterferenceEdge(
G, NId, MId,
C))
377 setDisjointAllowedRegs(
G, NId, MId,
D);
397 *
G.getMetadata().MF.getSubtarget().getRegisterInfo();
398 const auto &NRegs =
G.getNodeMetadata(NId).getAllowedRegs();
399 const auto &MRegs =
G.getNodeMetadata(MId).getAllowedRegs();
402 IKey
K(&NRegs, &MRegs);
405 G.addEdgeBypassingCostAllocator(NId, MId,
I->second);
410 bool NodesInterfere =
false;
411 for (
unsigned I = 0;
I != NRegs.size(); ++
I) {
413 for (
unsigned J = 0; J != MRegs.size(); ++J) {
415 if (
TRI.regsOverlap(PRegN, PRegM)) {
416 M[
I + 1][J + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
417 NodesInterfere =
true;
426 C[
K] =
G.getEdgeCostsPtr(EId);
441 for (
const auto &
MBB : MF) {
442 for (
const auto &
MI :
MBB) {
444 if (!
CP.setRegisters(&
MI) ||
CP.getSrcReg() ==
CP.getDstReg())
453 if (!MF.getRegInfo().isAllocatable(DstReg))
458 const PBQPRAGraph::NodeMetadata::AllowedRegVector &
Allowed =
459 G.getNodeMetadata(NId).getAllowedRegs();
461 unsigned PRegOpt = 0;
462 while (PRegOpt <
Allowed.size() && Allowed[PRegOpt].id() != DstReg)
465 if (PRegOpt <
Allowed.size()) {
467 NewCosts[PRegOpt + 1] -= CBenefit;
468 G.setNodeCosts(NId, std::move(NewCosts));
473 const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed1 =
474 &
G.getNodeMetadata(N1Id).getAllowedRegs();
475 const PBQPRAGraph::NodeMetadata::AllowedRegVector *Allowed2 =
476 &
G.getNodeMetadata(N2Id).getAllowedRegs();
479 if (EId ==
G.invalidEdgeId()) {
481 Allowed2->size() + 1, 0);
482 addVirtRegCoalesce(Costs, *Allowed1, *Allowed2, CBenefit);
483 G.addEdge(N1Id, N2Id, std::move(Costs));
485 if (
G.getEdgeNode1Id(EId) == N2Id) {
490 addVirtRegCoalesce(Costs, *Allowed1, *Allowed2, CBenefit);
491 G.updateEdgeCosts(EId, std::move(Costs));
499 void addVirtRegCoalesce(
501 const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed1,
502 const PBQPRAGraph::NodeMetadata::AllowedRegVector &Allowed2,
504 assert(CostMat.getRows() == Allowed1.size() + 1 &&
"Size mismatch.");
505 assert(CostMat.getCols() == Allowed2.size() + 1 &&
"Size mismatch.");
506 for (
unsigned I = 0;
I != Allowed1.size(); ++
I) {
508 for (
unsigned J = 0; J != Allowed2.size(); ++J) {
511 CostMat[
I + 1][J + 1] -= Benefit;
519 float normalize(
float UseDefFreq,
unsigned Size,
unsigned NumInstr)
override {
536void PBQPRAConstraint::anchor() {}
538void PBQPRAConstraintList::anchor() {}
540void RegAllocPBQP::getAnalysisUsage(
AnalysisUsage &au)
const {
569 for (
unsigned I = 0, E =
MRI.getNumVirtRegs();
I != E; ++
I) {
571 if (
MRI.reg_nodbg_empty(Reg))
573 VRegsToAlloc.insert(Reg);
581 for (
unsigned i = 0; CSR[i] != 0; ++i)
582 if (
TRI.regsOverlap(Reg, CSR[i]))
594 *
G.getMetadata().MF.getSubtarget().getRegisterInfo();
596 std::vector<Register> Worklist(VRegsToAlloc.begin(), VRegsToAlloc.end());
598 std::map<Register, std::vector<MCRegister>> VRegAllowedMap;
600 while (!Worklist.empty()) {
608 if (VRegLI.
empty()) {
609 EmptyIntervalVRegs.insert(VRegLI.
reg());
610 VRegsToAlloc.erase(VRegLI.
reg());
621 std::vector<MCRegister> VRegAllowed;
625 if (
MRI.isReserved(PReg))
629 if (!RegMaskOverlaps.
empty() && !RegMaskOverlaps.
test(PReg))
633 bool Interference =
false;
644 VRegAllowed.push_back(PReg);
649 if (VRegAllowed.empty()) {
651 spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
656 VRegAllowedMap[VReg.
id()] = std::move(VRegAllowed);
659 for (
auto &KV : VRegAllowedMap) {
660 auto VReg = KV.first;
664 EmptyIntervalVRegs.insert(VReg);
665 VRegsToAlloc.erase(VReg);
669 auto &VRegAllowed = KV.second;
675 for (
unsigned i = 0; i != VRegAllowed.size(); ++i)
677 NodeCosts[1 + i] += 1.0;
680 G.getNodeMetadata(NId).setVReg(VReg);
681 G.getNodeMetadata(NId).setAllowedRegs(
682 G.getMetadata().getAllowedRegs(std::move(VRegAllowed)));
683 G.getMetadata().setNodeIdForVReg(VReg, NId);
687void RegAllocPBQP::spillVReg(
Register VReg,
691 VRegsToAlloc.erase(VReg);
693 nullptr, &DeadRemats);
694 VRegSpiller.
spill(LRE);
699 << LRE.getParent().weight() <<
", New vregs: ");
707 VRegsToAlloc.insert(LI.
reg());
713bool RegAllocPBQP::mapPBQPToRegAlloc(
const PBQPRAGraph &
G,
723 bool AnotherRoundNeeded =
false;
730 for (
auto NId :
G.nodeIds()) {
731 Register VReg =
G.getNodeMetadata(NId).getVReg();
735 MCRegister PReg =
G.getNodeMetadata(NId).getAllowedRegs()[AllocOpt - 1];
737 <<
TRI.getName(PReg) <<
"\n");
738 assert(PReg != 0 &&
"Invalid preg selected.");
744 spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller);
745 AnotherRoundNeeded |= !NewVRegs.
empty();
749 return !AnotherRoundNeeded;
758 for (
const Register &R : EmptyIntervalVRegs) {
766 for (
MCRegister CandidateReg : RawPRegOrder) {
773 "No un-reserved physical registers in this register class");
783 for (
auto *DeadInst : DeadRemats) {
785 DeadInst->eraseFromParent();
791 LiveIntervals &LIS = getAnalysis<LiveIntervalsWrapperPass>().getLIS();
793 getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI();
795 auto &LiveStks = getAnalysis<LiveStacksWrapperLegacy>().getLS();
796 auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
798 VirtRegMap &VRM = getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
800 PBQPVirtRegAuxInfo VRAI(
801 MF, LIS, VRM, getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI);
802 VRAI.calculateSpillWeightsAndHints();
809 MF, LIS, VRM, getAnalysis<MachineLoopInfoWrapperPass>().getLI(), MBFI);
810 std::unique_ptr<Spiller> VRegSpiller(
827 findVRegIntervalsToAlloc(MF, LIS);
831 std::string FullyQualifiedName =
832 F.getParent()->getModuleIdentifier() +
"." +
F.getName().str();
836 if (!VRegsToAlloc.empty()) {
838 std::unique_ptr<PBQPRAConstraintList> ConstraintsRoot =
839 std::make_unique<PBQPRAConstraintList>();
840 ConstraintsRoot->addConstraint(std::make_unique<SpillCosts>());
841 ConstraintsRoot->addConstraint(std::make_unique<Interference>());
843 ConstraintsRoot->addConstraint(std::make_unique<Coalescing>());
846 bool PBQPAllocComplete =
false;
849 while (!PBQPAllocComplete) {
854 initializeGraph(
G, VRM, *VRegSpiller);
855 ConstraintsRoot->apply(
G);
859 std::ostringstream RS;
861 std::string GraphFileName = FullyQualifiedName +
"." + RS.str() +
865 LLVM_DEBUG(
dbgs() <<
"Dumping graph for round " << Round <<
" to \""
866 << GraphFileName <<
"\"\n");
872 PBQPAllocComplete = mapPBQPToRegAlloc(
G, Solution, VRM, *VRegSpiller);
878 finalizeAlloc(MF, LIS, VRM);
879 postOptimization(*VRegSpiller, LIS);
880 VRegsToAlloc.clear();
881 EmptyIntervalVRegs.clear();
894 Register VReg =
G.getNodeMetadata(NId).getVReg();
895 const char *RegClassName =
TRI->getRegClassName(
MRI.getRegClass(VReg));
896 OS << NId <<
" (" << RegClassName <<
':' <<
printReg(VReg,
TRI) <<
')';
900#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
904 assert(Costs.getLength() != 0 &&
"Empty vector in graph.");
912 assert(N1Id != N2Id &&
"PBQP graphs should not have self-edges.");
914 assert(M.getRows() != 0 &&
"No rows in matrix.");
915 assert(M.getCols() != 0 &&
"No cols in matrix.");
929 for (
auto NId : nodeIds()) {
930 OS <<
" node" << NId <<
" [ label=\""
932 << getNodeCosts(NId) <<
"\" ]\n";
935 OS <<
" edge [ len=" << nodeIds().size() <<
" ]\n";
936 for (
auto EId : edgeIds()) {
937 OS <<
" node" << getEdgeNode1Id(EId)
938 <<
" -- node" << getEdgeNode2Id(EId)
940 const Matrix &EdgeCosts = getEdgeCosts(EId);
941 for (
unsigned i = 0; i < EdgeCosts.getRows(); ++i) {
942 OS << EdgeCosts.getRowAsVector(i) <<
"\\n";
950 return new RegAllocPBQP(customPassID);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
Register 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)
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.
LLVM_ABI AnalysisUsage & addRequiredID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI 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.
LLVM_ABI 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.
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,...
LLVM_ABI 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.
LLVM_ABI 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 LLVM_ABI 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 postOptimization()
virtual void spill(LiveRangeEdit &LRE, AllocationOrder *Order=nullptr)=0
spill - Spill the LRE.getParent() live interval.
StringRef - Represent a constant reference to a string, i.e.
ArrayRef< MCPhysReg > getRawAllocationOrder(const MachineFunction &MF, bool Rev=false) 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 std::unique_ptr< PBQPRAConstraint > getCustomPBQPConstraints() const
Return PBQPConstraint(s) for the target.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
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
LLVM_ABI void assignVirt2Phys(Register virtReg, MCRegister 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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 append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI void initializeLiveIntervalsWrapperPassPass(PassRegistry &)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI FunctionPass * createDefaultPBQPRegisterAllocator()
PBQPRegisterAllocation Pass - This pass implements the Partitioned Boolean Quadratic Prograaming (PBQ...
FunctionPass * createPBQPRegisterAllocator(char *customPassID=nullptr)
Create a PBQP register allocator instance.
LLVM_ABI void initializeSlotIndexesWrapperPassPass(PassRegistry &)
Spiller * createInlineSpiller(const Spiller::RequiredAnalyses &Analyses, MachineFunction &MF, VirtRegMap &VRM, VirtRegAuxInfo &VRAI, LiveRegMatrix *Matrix=nullptr)
Create and return a spiller that will insert spill code directly instead of deferring though VirtRegM...
LLVM_ABI void initializeLiveStacksWrapperLegacyPass(PassRegistry &)
LLVM_ABI void initializeVirtRegMapWrapperLegacyPass(PassRegistry &)
LLVM_ABI 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.