16 #ifndef LLVM_CODEGEN_REGALLOCPBQP_H
17 #define LLVM_CODEGEN_REGALLOCPBQP_H
44 : WorstRow(0), WorstCol(0),
45 UnsafeRows(new
bool[M.getRows() - 1]()),
46 UnsafeCols(new
bool[M.getCols() - 1]()) {
48 unsigned* ColCounts =
new unsigned[M.
getCols() - 1]();
50 for (
unsigned i = 1; i < M.
getRows(); ++i) {
51 unsigned RowCount = 0;
52 for (
unsigned j = 1; j < M.
getCols(); ++j) {
53 if (M[i][j] == std::numeric_limits<PBQPNum>::infinity()) {
56 UnsafeRows[i - 1] =
true;
57 UnsafeCols[j - 1] =
true;
60 WorstRow = std::max(WorstRow, RowCount);
62 unsigned WorstColCountForCurRow =
63 *std::max_element(ColCounts, ColCounts + M.
getCols() - 1);
64 WorstCol = std::max(WorstCol, WorstColCountForCurRow);
74 unsigned WorstRow, WorstCol;
75 std::unique_ptr<bool[]> UnsafeRows;
76 std::unique_ptr<bool[]> UnsafeCols;
88 std::copy(OptVec.begin(), OptVec.end(), Opts.get());
92 : NumOpts(Other.NumOpts), Opts(new
unsigned[NumOpts]) {
93 std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get());
97 : NumOpts(std::move(
Other.NumOpts)), Opts(std::move(
Other.Opts)) {}
100 NumOpts = Other.NumOpts;
101 Opts.reset(
new unsigned[NumOpts]);
102 std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get());
107 NumOpts = std::move(
Other.NumOpts);
108 Opts = std::move(
Other.Opts);
112 unsigned size()
const {
return NumOpts; }
116 if (NumOpts != Other.NumOpts)
118 return std::equal(Opts.get(), Opts.get() + NumOpts, Other.Opts.get());
122 return !(*
this ==
Other);
127 std::unique_ptr<unsigned[]> Opts;
131 unsigned *OStart = OptRegs.Opts.get();
132 unsigned *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts;
148 : MF(MF), LIS(LIS), MBFI(MBFI) {}
155 VRegToNodeId[VReg] = NId;
159 auto VRegItr = VRegToNodeId.find(VReg);
160 if (VRegItr == VRegToNodeId.end())
162 return VRegItr->second;
166 VRegToNodeId.erase(VReg);
170 return AllowedRegVecs.
getValue(std::move(Allowed));
175 AllowedRegVecPool AllowedRegVecs;
194 : RS(
Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr),
197 , everConservativelyAllocatable(
false)
204 : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
205 OptUnsafeEdges(new
unsigned[NumOpts]), VReg(Other.VReg),
206 AllowedRegs(Other.AllowedRegs)
208 , everConservativelyAllocatable(Other.everConservativelyAllocatable)
212 std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts],
221 OptUnsafeEdges(std::move(
Other.OptUnsafeEdges)), VReg(
Other.VReg),
222 AllowedRegs(std::move(
Other.AllowedRegs))
224 , everConservativelyAllocatable(
Other.everConservativelyAllocatable)
232 NumOpts = Other.NumOpts;
233 DeniedOpts = Other.DeniedOpts;
234 OptUnsafeEdges.reset(
new unsigned[NumOpts]);
235 std::copy(Other.OptUnsafeEdges.get(), Other.OptUnsafeEdges.get() + NumOpts,
236 OptUnsafeEdges.get());
238 AllowedRegs = Other.AllowedRegs;
240 everConservativelyAllocatable = Other.everConservativelyAllocatable;
249 NumOpts =
Other.NumOpts;
250 DeniedOpts =
Other.DeniedOpts;
251 OptUnsafeEdges = std::move(
Other.OptUnsafeEdges);
253 AllowedRegs = std::move(
Other.AllowedRegs);
255 everConservativelyAllocatable =
Other.everConservativelyAllocatable;
260 void setVReg(
unsigned VReg) { this->VReg = VReg; }
264 this->AllowedRegs = std::move(AllowedRegs);
270 OptUnsafeEdges = std::unique_ptr<unsigned[]>(
new unsigned[NumOpts]());
275 assert(RS >= this->RS &&
"A node's reduction state can not be downgraded");
282 everConservativelyAllocatable =
true;
289 const bool* UnsafeOpts =
291 for (
unsigned i = 0; i < NumOpts; ++i)
292 OptUnsafeEdges[i] += UnsafeOpts[i];
297 const bool* UnsafeOpts =
299 for (
unsigned i = 0; i < NumOpts; ++i)
300 OptUnsafeEdges[i] -= UnsafeOpts[i];
304 return (DeniedOpts < NumOpts) ||
305 (std::find(&OptUnsafeEdges[0], &OptUnsafeEdges[NumOpts], 0) !=
306 &OptUnsafeEdges[NumOpts]);
311 return everConservativelyAllocatable;
319 std::unique_ptr<unsigned[]> OptUnsafeEdges;
324 bool everConservativelyAllocatable;
360 "PBQP Graph should not contain single or zero-option nodes");
418 moveToOptimallyReducibleNodes(NId);
423 moveToConservativelyAllocatableNodes(NId);
427 void removeFromCurrentSet(
NodeId NId) {
431 assert(OptimallyReducibleNodes.find(NId) !=
432 OptimallyReducibleNodes.end() &&
433 "Node not in optimally reducible set.");
434 OptimallyReducibleNodes.erase(NId);
437 assert(ConservativelyAllocatableNodes.find(NId) !=
438 ConservativelyAllocatableNodes.end() &&
439 "Node not in conservatively allocatable set.");
440 ConservativelyAllocatableNodes.erase(NId);
443 assert(NotProvablyAllocatableNodes.find(NId) !=
444 NotProvablyAllocatableNodes.end() &&
445 "Node not in not-provably-allocatable set.");
446 NotProvablyAllocatableNodes.erase(NId);
451 void moveToOptimallyReducibleNodes(
NodeId NId) {
452 removeFromCurrentSet(NId);
453 OptimallyReducibleNodes.insert(NId);
458 void moveToConservativelyAllocatableNodes(
NodeId NId) {
459 removeFromCurrentSet(NId);
460 ConservativelyAllocatableNodes.insert(NId);
465 void moveToNotProvablyAllocatableNodes(
NodeId NId) {
466 removeFromCurrentSet(NId);
467 NotProvablyAllocatableNodes.insert(NId);
476 moveToOptimallyReducibleNodes(NId);
478 moveToConservativelyAllocatableNodes(NId);
480 moveToNotProvablyAllocatableNodes(NId);
490 std::vector<GraphBase::NodeId> reduce() {
491 assert(!G.
empty() &&
"Cannot reduce empty graph.");
494 std::vector<NodeId> NodeStack;
498 if (!OptimallyReducibleNodes.empty()) {
499 NodeSet::iterator NItr = OptimallyReducibleNodes.begin();
501 OptimallyReducibleNodes.erase(NItr);
502 NodeStack.push_back(NId);
514 }
else if (!ConservativelyAllocatableNodes.empty()) {
521 NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin();
523 ConservativelyAllocatableNodes.erase(NItr);
524 NodeStack.push_back(NId);
527 }
else if (!NotProvablyAllocatableNodes.empty()) {
528 NodeSet::iterator NItr =
529 std::min_element(NotProvablyAllocatableNodes.begin(),
530 NotProvablyAllocatableNodes.end(),
531 SpillCostComparator(G));
533 NotProvablyAllocatableNodes.erase(NItr);
534 NodeStack.push_back(NId);
543 class SpillCostComparator {
545 SpillCostComparator(
const Graph& G) : G(G) {}
546 bool operator()(NodeId N1Id, NodeId N2Id) {
547 PBQPNum N1SC =
G.getNodeCosts(N1Id)[0];
548 PBQPNum N2SC =
G.getNodeCosts(N2Id)[0];
550 return G.getNodeDegree(N1Id) <
G.getNodeDegree(N2Id);
558 typedef std::set<NodeId> NodeSet;
559 NodeSet OptimallyReducibleNodes;
560 NodeSet ConservativelyAllocatableNodes;
561 NodeSet NotProvablyAllocatableNodes;
586 return RegAllocSolver.
solve();
PBQP::Graph< RegAllocSolverImpl > Graph
unsigned getCols() const
Return the number of cols in this matrix.
Represents a solution to a PBQP problem.
NodeId getEdgeNode1Id(EdgeId EId) const
Get the first node connected to this edge.
Holds a vector of the allowed physical regs for a vreg.
void handleSetNodeCosts(NodeId NId, const Vector &newCosts)
bool operator!=(const AllowedRegVector &Other) const
static NodeId invalidNodeId()
Returns a value representing an invalid (non-existent) node.
NodeId getEdgeNode2Id(EdgeId EId) const
Get the second node connected to this edge.
PoolRef getValue(ValueKeyT ValueKey)
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
RegAllocSolverImpl::GraphMetadata GraphMetadata
const Vector & getNodeCosts(NodeId NId) const
Get a node's cost vector.
RegAllocSolverImpl(Graph &G)
FunctionPass * createPBQPRegisterAllocator(char *customPassID=nullptr)
Create a PBQP register allocator instance.
NodeMetadata & getNodeMetadata(NodeId NId)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
AllowedRegVector(const AllowedRegVector &Other)
friend hash_code hash_value(const AllowedRegVector &)
bool operator==(const AllowedRegVector &Other) const
void printDot(raw_ostream &OS) const
Print a representation of this graph in DOT format.
void applyR1(GraphT &G, typename GraphT::NodeId NId)
Reduce a node of degree one.
void handleDisconnectEdge(EdgeId EId, NodeId NId)
NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const
NodeIdSet nodeIds() const
PBQPRAGraph(GraphMetadata Metadata)
AllowedRegVector(const std::vector< unsigned > &OptVec)
void setSolver(SolverT &S)
Lock this graph to the given solver instance in preparation for running the solver.
unsigned getLength() const
Return the length of the vector.
static cl::opt< RegisterRegAlloc::FunctionPassCtor, false, RegisterPassParser< RegisterRegAlloc > > RegAlloc("regalloc", cl::init(&useDefaultRegisterAllocator), cl::desc("Register allocator to use"))
-regalloc=... command line option.
const Metadata & getMetadata() const
AllowedRegVector(AllowedRegVector &&Other)
void unsetSolver()
Release from solver instance.
unsigned operator[](size_t I) const
Solution backpropagate(GraphT &G, StackT stack)
const Matrix & getEdgeCosts(EdgeId EId) const
Get an edge's cost matrix.
std::shared_ptr< const AllowedRegVector > PoolRef
AllowedRegVector & operator=(const AllowedRegVector &Other)
bool empty() const
Returns true if the graph is empty.
RegAlloc::NodeMetadata NodeMetadata
RegAlloc::GraphMetadata GraphMetadata
void handleUpdateCosts(EdgeId EId, const Matrix &NewCosts)
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
An opaque object representing a hash code.
void disconnectAllNeighborsFromNode(NodeId NId)
Convenience method to disconnect all neighbours from the given node.
unsigned getRows() const
Return the number of rows in this matrix.
void handleRemoveEdge(EdgeId EId)
void handleReconnectEdge(EdgeId EId, NodeId NId)
hash_code hash_value(const AllowedRegVector &OptRegs)
AllowedRegVector & operator=(AllowedRegVector &&Other)
Solution solve(PBQPRAGraph &G)
unsigned getSpillOptionIdx()
Spill option index.
void handleAddEdge(EdgeId EId)
void applyR2(GraphT &G, typename GraphT::NodeId NId)
This class implements an extremely fast bulk output stream that can only output to a stream...
void dump() const
Dump this graph to dbgs().
PBQP::PoolCostAllocator< Vector, Matrix > CostAllocator
void handleAddNode(NodeId NId)
void handleRemoveNode(NodeId NId)