void PEI::assignCalleeSavedSpillSlots(MachineFunction &F, const BitVector &SavedRegs) { // These are used to keep track the callee-save area. Initialize them. MinCSFrameIndex = INT_MAX; MaxCSFrameIndex = 0; if (SavedRegs.empty()) return; const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo(); const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&F); std::vector<CalleeSavedInfo> CSI; for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; if (SavedRegs.test(Reg)) CSI.push_back(CalleeSavedInfo(Reg)); } const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); MachineFrameInfo *MFI = F.getFrameInfo(); if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { // If target doesn't implement this, use generic code. if (CSI.empty()) return; // Early exit if no callee saved registers are modified! unsigned NumFixedSpillSlots; const TargetFrameLowering::SpillSlot *FixedSpillSlots = TFI->getCalleeSavedSpillSlots(NumFixedSpillSlots); // Now that we know which registers need to be saved and restored, allocate // stack slots for them. for (auto &CS : CSI) { unsigned Reg = CS.getReg(); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); int FrameIdx; if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) { CS.setFrameIdx(FrameIdx); continue; } // Check to see if this physreg must be spilled to a particular stack slot // on this target. const TargetFrameLowering::SpillSlot *FixedSlot = FixedSpillSlots; while (FixedSlot != FixedSpillSlots + NumFixedSpillSlots && FixedSlot->Reg != Reg) ++FixedSlot; if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. unsigned Align = RC->getAlignment(); unsigned StackAlign = TFI->getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; } else { // Spill it to the stack where we must. FrameIdx = MFI->CreateFixedSpillStackObject(RC->getSize(), FixedSlot->Offset); } CS.setFrameIdx(FrameIdx); } } MFI->setCalleeSavedInfo(CSI); }
PBQPRAProblem *PBQPBuilder::build(MachineFunction *mf, const LiveIntervals *lis, const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs) { LiveIntervals *LIS = const_cast<LiveIntervals*>(lis); MachineRegisterInfo *mri = &mf->getRegInfo(); const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo(); OwningPtr<PBQPRAProblem> p(new PBQPRAProblem()); PBQP::Graph &g = p->getGraph(); RegSet pregs; // Collect the set of preg intervals, record that they're used in the MF. for (unsigned Reg = 1, e = tri->getNumRegs(); Reg != e; ++Reg) { if (mri->def_empty(Reg)) continue; pregs.insert(Reg); mri->setPhysRegUsed(Reg); } // Iterate over vregs. for (RegSet::const_iterator vregItr = vregs.begin(), vregEnd = vregs.end(); vregItr != vregEnd; ++vregItr) { unsigned vreg = *vregItr; 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. typedef std::vector<unsigned> VRAllowed; VRAllowed vrAllowed; ArrayRef<uint16_t> rawOrder = trc->getRawAllocationOrder(*mf); for (unsigned i = 0; i != rawOrder.size(); ++i) { unsigned preg = rawOrder[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. vrAllowed.push_back(preg); } // Construct the node. PBQP::Graph::NodeId node = g.addNode(PBQP::Vector(vrAllowed.size() + 1, 0)); // Record the mapping and allowed set in the problem. p->recordVReg(vreg, node, vrAllowed.begin(), vrAllowed.end()); PBQP::PBQPNum spillCost = (vregLI->weight != 0.0) ? vregLI->weight : std::numeric_limits<PBQP::PBQPNum>::min(); addSpillCosts(g.getNodeCosts(node), spillCost); } for (RegSet::const_iterator vr1Itr = vregs.begin(), vrEnd = vregs.end(); vr1Itr != vrEnd; ++vr1Itr) { unsigned vr1 = *vr1Itr; const LiveInterval &l1 = lis->getInterval(vr1); const PBQPRAProblem::AllowedSet &vr1Allowed = p->getAllowedSet(vr1); for (RegSet::const_iterator vr2Itr = llvm::next(vr1Itr); vr2Itr != vrEnd; ++vr2Itr) { unsigned vr2 = *vr2Itr; const LiveInterval &l2 = lis->getInterval(vr2); const PBQPRAProblem::AllowedSet &vr2Allowed = p->getAllowedSet(vr2); assert(!l2.empty() && "Empty interval in vreg set?"); if (l1.overlaps(l2)) { PBQP::Graph::EdgeId edge = g.addEdge(p->getNodeForVReg(vr1), p->getNodeForVReg(vr2), PBQP::Matrix(vr1Allowed.size()+1, vr2Allowed.size()+1, 0)); addInterferenceCosts(g.getEdgeCosts(edge), vr1Allowed, vr2Allowed, tri); } } } return p.take(); }
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); } }