16 #ifndef LLVM_CODEGEN_REGALLOCPBQP_H 17 #define LLVM_CODEGEN_REGALLOCPBQP_H 39 class MachineBlockFrequencyInfo;
40 class MachineFunction;
55 : UnsafeRows(new
bool[M.getRows() - 1]()),
56 UnsafeCols(new
bool[M.getCols() - 1]()) {
57 unsigned* ColCounts =
new unsigned[M.
getCols() - 1]();
59 for (
unsigned i = 1; i < M.
getRows(); ++i) {
60 unsigned RowCount = 0;
61 for (
unsigned j = 1; j < M.
getCols(); ++j) {
62 if (M[i][j] == std::numeric_limits<PBQPNum>::infinity()) {
65 UnsafeRows[i - 1] =
true;
66 UnsafeCols[j - 1] =
true;
69 WorstRow =
std::max(WorstRow, RowCount);
71 unsigned WorstColCountForCurRow =
72 *std::max_element(ColCounts, ColCounts + M.
getCols() - 1);
73 WorstCol =
std::max(WorstCol, WorstColCountForCurRow);
86 unsigned WorstRow = 0;
87 unsigned WorstCol = 0;
88 std::unique_ptr<bool[]> UnsafeRows;
89 std::unique_ptr<bool[]> UnsafeCols;
102 std::copy(OptVec.begin(), OptVec.end(), Opts.get());
105 unsigned size()
const {
return NumOpts; }
109 if (NumOpts != Other.NumOpts)
111 return std::equal(Opts.get(), Opts.get() + NumOpts, Other.Opts.get());
115 return !(*
this == Other);
119 unsigned NumOpts = 0;
120 std::unique_ptr<unsigned[]> Opts;
124 unsigned *OStart = OptRegs.Opts.get();
125 unsigned *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts;
141 : MF(MF), LIS(LIS), MBFI(MBFI) {}
148 VRegToNodeId[VReg] = NId;
152 auto VRegItr = VRegToNodeId.find(VReg);
153 if (VRegItr == VRegToNodeId.end())
155 return VRegItr->second;
159 return AllowedRegVecs.getValue(std::move(Allowed));
177 NotProvablyAllocatable,
178 ConservativelyAllocatable,
185 : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts),
186 OptUnsafeEdges(new
unsigned[NumOpts]), VReg(Other.VReg),
187 AllowedRegs(Other.AllowedRegs)
189 , everConservativelyAllocatable(Other.everConservativelyAllocatable)
193 std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts],
201 void setVReg(
unsigned VReg) { this->VReg = VReg; }
205 this->AllowedRegs = std::move(AllowedRegs);
211 OptUnsafeEdges = std::unique_ptr<unsigned[]>(
new unsigned[NumOpts]());
216 assert(RS >= this->RS &&
"A node's reduction state can not be downgraded");
222 if (RS == ConservativelyAllocatable)
223 everConservativelyAllocatable =
true;
229 const bool* UnsafeOpts =
231 for (
unsigned i = 0; i < NumOpts; ++i)
232 OptUnsafeEdges[i] += UnsafeOpts[i];
237 const bool* UnsafeOpts =
239 for (
unsigned i = 0; i < NumOpts; ++i)
240 OptUnsafeEdges[i] -= UnsafeOpts[i];
244 return (DeniedOpts < NumOpts) ||
245 (
std::find(&OptUnsafeEdges[0], &OptUnsafeEdges[NumOpts], 0) !=
246 &OptUnsafeEdges[NumOpts]);
251 return everConservativelyAllocatable;
257 unsigned NumOpts = 0;
258 unsigned DeniedOpts = 0;
259 std::unique_ptr<unsigned[]> OptUnsafeEdges;
264 bool everConservativelyAllocatable =
false;
300 assert(
G.getNodeCosts(NId).getLength() > 1 &&
301 "PBQP Graph should not contain single or zero-option nodes");
302 G.getNodeMetadata(NId).setup(
G.getNodeCosts(NId));
309 handleReconnectEdge(EId,
G.getEdgeNode1Id(EId));
310 handleReconnectEdge(EId,
G.getEdgeNode2Id(EId));
327 NodeId N1Id =
G.getEdgeNode1Id(EId);
328 NodeId N2Id =
G.getEdgeNode2Id(EId);
331 bool Transpose = N1Id !=
G.getEdgeNode1Id(EId);
352 if (
G.getNodeDegree(NId) == 3) {
354 moveToOptimallyReducibleNodes(NId);
356 NodeMetadata::NotProvablyAllocatable &&
359 moveToConservativelyAllocatableNodes(NId);
363 void removeFromCurrentSet(
NodeId NId) {
364 switch (
G.getNodeMetadata(NId).getReductionState()) {
365 case NodeMetadata::Unprocessed:
break;
366 case NodeMetadata::OptimallyReducible:
367 assert(OptimallyReducibleNodes.find(NId) !=
368 OptimallyReducibleNodes.end() &&
369 "Node not in optimally reducible set.");
370 OptimallyReducibleNodes.erase(NId);
372 case NodeMetadata::ConservativelyAllocatable:
373 assert(ConservativelyAllocatableNodes.find(NId) !=
374 ConservativelyAllocatableNodes.end() &&
375 "Node not in conservatively allocatable set.");
376 ConservativelyAllocatableNodes.erase(NId);
378 case NodeMetadata::NotProvablyAllocatable:
379 assert(NotProvablyAllocatableNodes.find(NId) !=
380 NotProvablyAllocatableNodes.end() &&
381 "Node not in not-provably-allocatable set.");
382 NotProvablyAllocatableNodes.erase(NId);
387 void moveToOptimallyReducibleNodes(
NodeId NId) {
388 removeFromCurrentSet(NId);
389 OptimallyReducibleNodes.insert(NId);
390 G.getNodeMetadata(NId).setReductionState(
391 NodeMetadata::OptimallyReducible);
394 void moveToConservativelyAllocatableNodes(
NodeId NId) {
395 removeFromCurrentSet(NId);
396 ConservativelyAllocatableNodes.insert(NId);
397 G.getNodeMetadata(NId).setReductionState(
398 NodeMetadata::ConservativelyAllocatable);
401 void moveToNotProvablyAllocatableNodes(
NodeId NId) {
402 removeFromCurrentSet(NId);
403 NotProvablyAllocatableNodes.insert(NId);
404 G.getNodeMetadata(NId).setReductionState(
405 NodeMetadata::NotProvablyAllocatable);
410 for (
auto NId :
G.nodeIds()) {
411 if (
G.getNodeDegree(NId) < 3)
412 moveToOptimallyReducibleNodes(NId);
413 else if (
G.getNodeMetadata(NId).isConservativelyAllocatable())
414 moveToConservativelyAllocatableNodes(NId);
416 moveToNotProvablyAllocatableNodes(NId);
426 std::vector<GraphBase::NodeId>
reduce() {
427 assert(!
G.empty() &&
"Cannot reduce empty graph.");
430 std::vector<NodeId> NodeStack;
434 if (!OptimallyReducibleNodes.empty()) {
437 OptimallyReducibleNodes.erase(NItr);
438 NodeStack.push_back(NId);
439 switch (
G.getNodeDegree(NId)) {
450 }
else if (!ConservativelyAllocatableNodes.empty()) {
459 ConservativelyAllocatableNodes.erase(NItr);
460 NodeStack.push_back(NId);
461 G.disconnectAllNeighborsFromNode(NId);
462 }
else if (!NotProvablyAllocatableNodes.empty()) {
464 std::min_element(NotProvablyAllocatableNodes.begin(),
465 NotProvablyAllocatableNodes.end(),
466 SpillCostComparator(
G));
468 NotProvablyAllocatableNodes.erase(NItr);
469 NodeStack.push_back(NId);
470 G.disconnectAllNeighborsFromNode(NId);
478 class SpillCostComparator {
480 SpillCostComparator(
const Graph&
G) :
G(G) {}
495 using NodeSet = std::set<NodeId>;
496 NodeSet OptimallyReducibleNodes;
497 NodeSet ConservativelyAllocatableNodes;
498 NodeSet NotProvablyAllocatableNodes;
524 return RegAllocSolver.
solve();
536 #endif // LLVM_CODEGEN_REGALLOCPBQP_H Represents a solution to a PBQP problem.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
Holds a vector of the allowed physical regs for a vreg.
bool empty() const
Returns true if the graph is empty.
void handleSetNodeCosts(NodeId NId, const Vector &newCosts)
unsigned getLength() const
Return the length of the vector.
static NodeId invalidNodeId()
Returns a value representing an invalid (non-existent) node.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
RegAllocSolverImpl(Graph &G)
FunctionPass * createPBQPRegisterAllocator(char *customPassID=nullptr)
Create a PBQP register allocator instance.
typename RegAllocSolverImpl ::GraphMetadata GraphMetadata
unsigned getRows() const
Return the number of rows in this matrix.
void applyR1(GraphT &G, typename GraphT::NodeId NId)
Reduce a node of degree one.
void handleDisconnectEdge(EdgeId EId, NodeId NId)
unsigned getCols() const
Return the number of cols in this matrix.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
const Vector & getNodeCosts(NodeId NId) const
Get a node's cost vector.
PBQPRAGraph(GraphMetadata Metadata)
AllowedRegVector(const std::vector< unsigned > &OptVec)
bool operator==(const AllowedRegVector &Other) const
FunctionPass class - This class is used to implement most global optimizations.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SetVector< SUnit * >::const_iterator iterator
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
static cl::opt< RegisterRegAlloc::FunctionPassCtor, false, RegisterPassParser< RegisterRegAlloc > > RegAlloc("regalloc", cl::Hidden, cl::init(&useDefaultRegisterAllocator), cl::desc("Register allocator to use"))
Solution backpropagate(GraphT &G, StackT stack)
NodeEntry::AdjEdgeList::size_type getNodeDegree(NodeId NId) const
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.
unsigned operator[](size_t I) const
bool operator!=(const AllowedRegVector &Other) const
const Metadata & getMetadata() const
std::shared_ptr< const AllowedRegVector > PoolRef
void handleReconnectEdge(EdgeId EId, NodeId NId)
hash_code hash_value(const AllowedRegVector &OptRegs)
Solution solve(PBQPRAGraph &G)
unsigned getSpillOptionIdx()
Spill option index.
void handleAddEdge(EdgeId EId)
void applyR2(GraphT &G, typename GraphT::NodeId NId)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
void handleAddNode(NodeId NId)
OutputIt copy(R &&Range, OutputIt Out)
void handleRemoveNode(NodeId NId)