bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G, const PBQP::Solution &Solution, VirtRegMap &VRM, Spiller &VRegSpiller) { MachineFunction &MF = G.getMetadata().MF; LiveIntervals &LIS = G.getMetadata().LIS; const TargetRegisterInfo &TRI = *MF.getTarget().getSubtargetImpl()->getRegisterInfo(); (void)TRI; // Set to true if we have any spills bool AnotherRoundNeeded = false; // Clear the existing allocation. VRM.clearAllVirt(); // Iterate over the nodes mapping the PBQP solution to a register // assignment. for (auto NId : G.nodeIds()) { unsigned VReg = G.getNodeMetadata(NId).getVReg(); unsigned AllocOption = Solution.getSelection(NId); if (AllocOption != PBQP::RegAlloc::getSpillOptionIdx()) { unsigned PReg = G.getNodeMetadata(NId).getOptionRegs()[AllocOption - 1]; DEBUG(dbgs() << "VREG " << PrintReg(VReg, &TRI) << " -> " << TRI.getName(PReg) << "\n"); assert(PReg != 0 && "Invalid preg selected."); VRM.assignVirt2Phys(VReg, PReg); } else { VRegsToAlloc.erase(VReg); SmallVector<unsigned, 8> NewSpills; LiveRangeEdit LRE(&LIS.getInterval(VReg), NewSpills, MF, LIS, &VRM); VRegSpiller.spill(LRE); DEBUG(dbgs() << "VREG " << PrintReg(VReg, &TRI) << " -> SPILLED (Cost: " << LRE.getParent().weight << ", New vregs: "); // Copy any newly inserted live intervals into the list of regs to // allocate. for (LiveRangeEdit::iterator I = LRE.begin(), E = LRE.end(); I != E; ++I) { LiveInterval &LI = LIS.getInterval(*I); assert(!LI.empty() && "Empty spill range."); DEBUG(dbgs() << PrintReg(LI.reg, &TRI) << " "); VRegsToAlloc.insert(LI.reg); } DEBUG(dbgs() << ")\n"); // We need another round if spill intervals were added. AnotherRoundNeeded |= !LRE.empty(); } } return !AnotherRoundNeeded; }
void RegAllocPBQP::initializeGraph(PBQPRAGraph &G) { MachineFunction &MF = G.getMetadata().MF; LiveIntervals &LIS = G.getMetadata().LIS; const MachineRegisterInfo &MRI = G.getMetadata().MF.getRegInfo(); const TargetRegisterInfo &TRI = *G.getMetadata().MF.getTarget().getSubtargetImpl()->getRegisterInfo(); for (auto VReg : VRegsToAlloc) { const TargetRegisterClass *TRC = MRI.getRegClass(VReg); LiveInterval &VRegLI = LIS.getInterval(VReg); // Record any overlaps with regmask operands. BitVector RegMaskOverlaps; LIS.checkRegMaskInterference(VRegLI, RegMaskOverlaps); // Compute an initial allowed set for the current vreg. std::vector<unsigned> VRegAllowed; ArrayRef<MCPhysReg> RawPRegOrder = TRC->getRawAllocationOrder(MF); for (unsigned I = 0; I != RawPRegOrder.size(); ++I) { unsigned PReg = RawPRegOrder[I]; if (MRI.isReserved(PReg)) continue; // vregLI crosses a regmask operand that clobbers preg. if (!RegMaskOverlaps.empty() && !RegMaskOverlaps.test(PReg)) continue; // vregLI overlaps fixed regunit interference. bool Interference = false; for (MCRegUnitIterator Units(PReg, &TRI); Units.isValid(); ++Units) { if (VRegLI.overlaps(LIS.getRegUnit(*Units))) { Interference = true; break; } } if (Interference) continue; // preg is usable for this virtual register. VRegAllowed.push_back(PReg); } PBQPRAGraph::RawVector NodeCosts(VRegAllowed.size() + 1, 0); PBQPRAGraph::NodeId NId = G.addNode(std::move(NodeCosts)); G.getNodeMetadata(NId).setVReg(VReg); G.getNodeMetadata(NId).setOptionRegs(std::move(VRegAllowed)); G.getMetadata().setNodeIdForVReg(VReg, NId); } }
void A57ChainingConstraint::addInterChainConstraint(PBQPRAGraph &G, unsigned Rd, unsigned Ra) { LiveIntervals &LIs = G.getMetadata().LIS; // Do some Chain management if (Chains.count(Ra)) { if (Rd != Ra) { DEBUG(dbgs() << "Moving acc chain from " << PrintReg(Ra, TRI) << " to " << PrintReg(Rd, TRI) << '\n';); Chains.remove(Ra); Chains.insert(Rd); }
bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAGraph &G, const PBQP::Solution &Solution, VirtRegMap &VRM, Spiller &VRegSpiller) { MachineFunction &MF = G.getMetadata().MF; LiveIntervals &LIS = G.getMetadata().LIS; const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); (void)TRI; // Set to true if we have any spills bool AnotherRoundNeeded = false; // Clear the existing allocation. VRM.clearAllVirt(); // Iterate over the nodes mapping the PBQP solution to a register // assignment. for (auto NId : G.nodeIds()) { unsigned VReg = G.getNodeMetadata(NId).getVReg(); unsigned AllocOption = Solution.getSelection(NId); if (AllocOption != PBQP::RegAlloc::getSpillOptionIdx()) { unsigned PReg = G.getNodeMetadata(NId).getAllowedRegs()[AllocOption - 1]; DEBUG(dbgs() << "VREG " << PrintReg(VReg, &TRI) << " -> " << TRI.getName(PReg) << "\n"); assert(PReg != 0 && "Invalid preg selected."); VRM.assignVirt2Phys(VReg, PReg); } else { // Spill VReg. If this introduces new intervals we'll need another round // of allocation. SmallVector<unsigned, 8> NewVRegs; spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller); AnotherRoundNeeded |= !NewVRegs.empty(); } } return !AnotherRoundNeeded; }
bool A57ChainingConstraint::addIntraChainConstraint(PBQPRAGraph &G, unsigned Rd, unsigned Ra) { if (Rd == Ra) return false; LiveIntervals &LIs = G.getMetadata().LIS; if (TRI->isPhysicalRegister(Rd) || TRI->isPhysicalRegister(Ra)) { DEBUG(dbgs() << "Rd is a physical reg:" << TRI->isPhysicalRegister(Rd) << '\n'); DEBUG(dbgs() << "Ra is a physical reg:" << TRI->isPhysicalRegister(Ra) << '\n'); return false; } PBQPRAGraph::NodeId node1 = G.getMetadata().getNodeIdForVReg(Rd); PBQPRAGraph::NodeId node2 = G.getMetadata().getNodeIdForVReg(Ra); const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRdAllowed = &G.getNodeMetadata(node1).getAllowedRegs(); const PBQPRAGraph::NodeMetadata::AllowedRegVector *vRaAllowed = &G.getNodeMetadata(node2).getAllowedRegs(); PBQPRAGraph::EdgeId edge = G.findEdge(node1, node2); // The edge does not exist. Create one with the appropriate interference // costs. if (edge == G.invalidEdgeId()) { const LiveInterval &ld = LIs.getInterval(Rd); const LiveInterval &la = LIs.getInterval(Ra); bool livesOverlap = ld.overlaps(la); PBQPRAGraph::RawMatrix costs(vRdAllowed->size() + 1, vRaAllowed->size() + 1, 0); for (unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) { unsigned pRd = (*vRdAllowed)[i]; for (unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) { unsigned pRa = (*vRaAllowed)[j]; if (livesOverlap && TRI->regsOverlap(pRd, pRa)) costs[i + 1][j + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity(); else costs[i + 1][j + 1] = haveSameParity(pRd, pRa) ? 0.0 : 1.0; } } G.addEdge(node1, node2, std::move(costs)); return true; } if (G.getEdgeNode1Id(edge) == node2) { std::swap(node1, node2); std::swap(vRdAllowed, vRaAllowed); } // Enforce minCost(sameParity(RaClass)) > maxCost(otherParity(RdClass)) PBQPRAGraph::RawMatrix costs(G.getEdgeCosts(edge)); for (unsigned i = 0, ie = vRdAllowed->size(); i != ie; ++i) { unsigned pRd = (*vRdAllowed)[i]; // Get the maximum cost (excluding unallocatable reg) for same parity // registers PBQP::PBQPNum sameParityMax = std::numeric_limits<PBQP::PBQPNum>::min(); for (unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) { unsigned pRa = (*vRaAllowed)[j]; if (haveSameParity(pRd, pRa)) if (costs[i + 1][j + 1] != std::numeric_limits<PBQP::PBQPNum>::infinity() && costs[i + 1][j + 1] > sameParityMax) sameParityMax = costs[i + 1][j + 1]; } // Ensure all registers with a different parity have a higher cost // than sameParityMax for (unsigned j = 0, je = vRaAllowed->size(); j != je; ++j) { unsigned pRa = (*vRaAllowed)[j]; if (!haveSameParity(pRd, pRa)) if (sameParityMax > costs[i + 1][j + 1]) costs[i + 1][j + 1] = sameParityMax + 1.0; } } G.setEdgeCosts(edge, std::move(costs)); return true; }
void RegAllocPBQP::initializeGraph(PBQPRAGraph &G, VirtRegMap &VRM, Spiller &VRegSpiller) { MachineFunction &MF = G.getMetadata().MF; LiveIntervals &LIS = G.getMetadata().LIS; const MachineRegisterInfo &MRI = G.getMetadata().MF.getRegInfo(); const TargetRegisterInfo &TRI = *G.getMetadata().MF.getSubtarget().getRegisterInfo(); std::vector<unsigned> Worklist(VRegsToAlloc.begin(), VRegsToAlloc.end()); while (!Worklist.empty()) { unsigned VReg = Worklist.back(); Worklist.pop_back(); const TargetRegisterClass *TRC = MRI.getRegClass(VReg); LiveInterval &VRegLI = LIS.getInterval(VReg); // Record any overlaps with regmask operands. BitVector RegMaskOverlaps; LIS.checkRegMaskInterference(VRegLI, RegMaskOverlaps); // Compute an initial allowed set for the current vreg. std::vector<unsigned> VRegAllowed; ArrayRef<MCPhysReg> RawPRegOrder = TRC->getRawAllocationOrder(MF); for (unsigned I = 0; I != RawPRegOrder.size(); ++I) { unsigned PReg = RawPRegOrder[I]; if (MRI.isReserved(PReg)) continue; // vregLI crosses a regmask operand that clobbers preg. if (!RegMaskOverlaps.empty() && !RegMaskOverlaps.test(PReg)) continue; // vregLI overlaps fixed regunit interference. bool Interference = false; for (MCRegUnitIterator Units(PReg, &TRI); Units.isValid(); ++Units) { if (VRegLI.overlaps(LIS.getRegUnit(*Units))) { Interference = true; break; } } if (Interference) continue; // preg is usable for this virtual register. VRegAllowed.push_back(PReg); } // Check for vregs that have no allowed registers. These should be // pre-spilled and the new vregs added to the worklist. if (VRegAllowed.empty()) { SmallVector<unsigned, 8> NewVRegs; spillVReg(VReg, NewVRegs, MF, LIS, VRM, VRegSpiller); Worklist.insert(Worklist.end(), NewVRegs.begin(), NewVRegs.end()); continue; } PBQPRAGraph::RawVector NodeCosts(VRegAllowed.size() + 1, 0); // Tweak cost of callee saved registers, as using then force spilling and // restoring them. This would only happen in the prologue / epilogue though. for (unsigned i = 0; i != VRegAllowed.size(); ++i) if (isACalleeSavedRegister(VRegAllowed[i], TRI, MF)) NodeCosts[1 + i] += 1.0; PBQPRAGraph::NodeId NId = G.addNode(std::move(NodeCosts)); G.getNodeMetadata(NId).setVReg(VReg); G.getNodeMetadata(NId).setAllowedRegs( G.getMetadata().getAllowedRegs(std::move(VRegAllowed))); G.getMetadata().setNodeIdForVReg(VReg, NId); } }