std::auto_ptr<PBQPRAProblem> PBQPBuilder::build(MachineFunction *mf, const LiveIntervals *lis, const MachineLoopInfo *loopInfo, const RegSet &vregs) { typedef std::vector<const LiveInterval*> LIVector; MachineRegisterInfo *mri = &mf->getRegInfo(); const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo(); std::auto_ptr<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 (LiveIntervals::const_iterator itr = lis->begin(), end = lis->end(); itr != end; ++itr) { if (TargetRegisterInfo::isPhysicalRegister(itr->first)) { pregs.insert(itr->first); mri->setPhysRegUsed(itr->first); } } BitVector reservedRegs = tri->getReservedRegs(*mf); // 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); const LiveInterval *vregLI = &lis->getInterval(vreg); // Compute an initial allowed set for the current vreg. typedef std::vector<unsigned> VRAllowed; VRAllowed vrAllowed; ArrayRef<unsigned> rawOrder = trc->getRawAllocationOrder(*mf); for (unsigned i = 0; i != rawOrder.size(); ++i) { unsigned preg = rawOrder[i]; if (!reservedRegs.test(preg)) { vrAllowed.push_back(preg); } } // Remove any physical registers which overlap. for (RegSet::const_iterator pregItr = pregs.begin(), pregEnd = pregs.end(); pregItr != pregEnd; ++pregItr) { unsigned preg = *pregItr; const LiveInterval *pregLI = &lis->getInterval(preg); if (pregLI->empty()) { continue; } if (!vregLI->overlaps(*pregLI)) { continue; } // Remove the register from the allowed set. VRAllowed::iterator eraseItr = std::find(vrAllowed.begin(), vrAllowed.end(), preg); if (eraseItr != vrAllowed.end()) { vrAllowed.erase(eraseItr); } // Also remove any aliases. const unsigned *aliasItr = tri->getAliasSet(preg); if (aliasItr != 0) { for (; *aliasItr != 0; ++aliasItr) { VRAllowed::iterator eraseItr = std::find(vrAllowed.begin(), vrAllowed.end(), *aliasItr); if (eraseItr != vrAllowed.end()) { vrAllowed.erase(eraseItr); } } } } // Construct the node. PBQP::Graph::NodeItr 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::EdgeItr 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; }
std::auto_ptr<PBQPRAProblem> PBQPBuilder::build(MachineFunction *mf, const LiveIntervals *lis, const MachineLoopInfo *loopInfo, const RegSet &vregs) { typedef std::vector<const LiveInterval*> LIVector; ArrayRef<SlotIndex> regMaskSlots = lis->getRegMaskSlots(); MachineRegisterInfo *mri = &mf->getRegInfo(); const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo(); std::auto_ptr<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 (LiveIntervals::const_iterator itr = lis->begin(), end = lis->end(); itr != end; ++itr) { if (TargetRegisterInfo::isPhysicalRegister(itr->first)) { pregs.insert(itr->first); mri->setPhysRegUsed(itr->first); } } BitVector reservedRegs = tri->getReservedRegs(*mf); // 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); const LiveInterval *vregLI = &lis->getInterval(vreg); // 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 (!reservedRegs.test(preg)) { vrAllowed.push_back(preg); } } RegSet overlappingPRegs; // Record physical registers whose ranges overlap. for (RegSet::const_iterator pregItr = pregs.begin(), pregEnd = pregs.end(); pregItr != pregEnd; ++pregItr) { unsigned preg = *pregItr; const LiveInterval *pregLI = &lis->getInterval(preg); if (pregLI->empty()) { continue; } if (vregLI->overlaps(*pregLI)) overlappingPRegs.insert(preg); } // Record any overlaps with regmask operands. BitVector regMaskOverlaps(tri->getNumRegs()); for (ArrayRef<SlotIndex>::iterator rmItr = regMaskSlots.begin(), rmEnd = regMaskSlots.end(); rmItr != rmEnd; ++rmItr) { SlotIndex rmIdx = *rmItr; if (vregLI->liveAt(rmIdx)) { MachineInstr *rmMI = lis->getInstructionFromIndex(rmIdx); const uint32_t* regMask = 0; for (MachineInstr::mop_iterator mopItr = rmMI->operands_begin(), mopEnd = rmMI->operands_end(); mopItr != mopEnd; ++mopItr) { if (mopItr->isRegMask()) { regMask = mopItr->getRegMask(); break; } } assert(regMask != 0 && "Couldn't find register mask."); regMaskOverlaps.setBitsNotInMask(regMask); } } for (unsigned preg = 0; preg < tri->getNumRegs(); ++preg) { if (regMaskOverlaps.test(preg)) overlappingPRegs.insert(preg); } for (RegSet::const_iterator pregItr = overlappingPRegs.begin(), pregEnd = overlappingPRegs.end(); pregItr != pregEnd; ++pregItr) { unsigned preg = *pregItr; // Remove the register from the allowed set. VRAllowed::iterator eraseItr = std::find(vrAllowed.begin(), vrAllowed.end(), preg); if (eraseItr != vrAllowed.end()) { vrAllowed.erase(eraseItr); } // Also remove any aliases. for (MCRegAliasIterator AI(preg, tri, false); AI.isValid(); ++AI) { VRAllowed::iterator eraseItr = std::find(vrAllowed.begin(), vrAllowed.end(), *AI); if (eraseItr != vrAllowed.end()) { vrAllowed.erase(eraseItr); } } } // Construct the node. PBQP::Graph::NodeItr 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::EdgeItr 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; }