Vpoint emitCall(Vout& v, CppCall call, RegSet args) { PhysReg arg0(argReg(0)); PhysReg rHostCall(rHostCallReg); switch (call.kind()) { case CppCall::Kind::Direct: v << ldimm{reinterpret_cast<intptr_t>(call.address()), rHostCall}; break; case CppCall::Kind::Virtual: v << loadq{arg0[0], rHostCall}; v << loadq{rHostCall[call.vtableOffset()], rHostCall}; break; case CppCall::Kind::IndirectReg: case CppCall::Kind::IndirectVreg: // call indirect currently not implemented. It'll be something like // a.Br(x2a(call.getReg())) not_implemented(); always_assert(0); break; case CppCall::Kind::ArrayVirt: case CppCall::Kind::Destructor: not_implemented(); always_assert(0); break; } uint8_t argc = args.size(); args.add(rHostCall); auto fixupAddr = v.makePoint(); v << hostcall{args, argc, fixupAddr}; return fixupAddr; }
void RegAlloc::reset() { TRACE(1, ">>> regalloc reset! <<<\n"); m_epoch = 0; m_contToRegMap.clear(); // m_info is sparse. for (int i = 0; i < kMaxRegs; ++i) { m_info[i].m_epoch = 0; m_info[i].m_pReg = PhysReg(i); m_info[i].m_cont = RegContent(); m_info[i].m_type = KindOfInvalid; m_info[i].m_state = RegInfo::INVALID; } RegSet all = m_allRegs; PhysReg pr; for (int i = 0; all.findFirst(pr); i++) { all.remove(pr); physRegToInfo(pr)->m_pReg = PhysReg(pr); stateTransition(physRegToInfo(pr), RegInfo::FREE); // Put the most favorable register last, so it is picked first. m_lru[(m_numRegs - 1) - i] = pr; } m_branchSynced = false; verify(); }
/* * Check that each destination register or spill slot is unique, * and that sources have the same number or less operands than * destinations. */ bool checkShuffle(const IRInstruction& inst, const RegAllocInfo& regs) { auto n = inst.numSrcs(); assert(n == inst.extra<Shuffle>()->size); RegSet destRegs; std::bitset<NumPreAllocatedSpillLocs> destSlots; auto& inst_regs = regs[inst]; for (uint32_t i = 0; i < n; ++i) { DEBUG_ONLY auto& rs = inst_regs.src(i); DEBUG_ONLY auto& rd = inst.extra<Shuffle>()->dests[i]; if (rd.numAllocated() == 0) continue; // dest was unused; ignore. if (rd.spilled()) { assert(!rs.spilled()); // no mem-mem copies } else { // rs could have less assigned registers/slots than rd, in these cases: // - when rs is empty, because the source is a constant. // - when rs has 1 register because it's untagged but rd needs 2 because // it's a more general (tagged) type, because of a phi. assert(rs.numWords() <= rd.numWords()); assert(rs.spilled() || rs.isFullSIMD() == rd.isFullSIMD()); } for (int j = 0; j < rd.numAllocated(); ++j) { if (rd.spilled()) { assert(!destSlots.test(rd.slot(j))); destSlots.set(rd.slot(j)); } else { assert(!destRegs.contains(rd.reg(j))); // no duplicate dests destRegs.add(rd.reg(j)); } } } return true; }
void Vxls::allocate(Interval* current) { PhysReg::Map<unsigned> free_until; // 0 by default RegSet allow; unsigned conflict = constrain(current, allow); allow.forEach([&](PhysReg r) { free_until[r] = conflict; }); for (auto ivl : active) { free_until[ivl->reg] = 0; } for (auto ivl : inactive) { auto until = current->nextIntersect(ivl); free_until[ivl->reg] = std::min(until, free_until[ivl->reg]); } auto r = find(free_until); auto pos = free_until[r]; if (pos >= current->end()) { return assignReg(current, r); } if (pos > current->start()) { // r is free for the first part of current auto prev_use = current->lastUseBefore(pos); auto min_split = std::max(prev_use, current->start() + 1); auto max_split = pos; assert(min_split <= max_split); auto split_pos = std::max(min_split, max_split); // todo: find good spot split_pos = nearestSplitBefore(split_pos); if (split_pos > current->start()) { auto second = current->split(split_pos, true); pending.push(second); return assignReg(current, r); } } // must spill current or another victim allocBlocked(current); }
RegSet PhysLoc::regs() const { RegSet regs; if (hasReg(0)) { regs.add(reg(0)); if (hasReg(1)) regs.add(reg(1)); } return regs; }
void getEffects(const Abi& abi, const Vinstr& i, RegSet& uses, RegSet& across, RegSet& defs) { uses = defs = across = RegSet(); switch (i.op) { case Vinstr::mccall: case Vinstr::call: case Vinstr::callm: case Vinstr::callr: defs = abi.all() - abi.calleeSaved; switch (arch()) { case Arch::ARM: defs.add(PhysReg(arm::rLinkReg)); defs.remove(PhysReg(arm::rVmFp)); break; case Arch::X64: defs.remove(reg::rbp); break; } break; case Vinstr::bindcall: defs = abi.all(); switch (arch()) { case Arch::ARM: break; case Arch::X64: defs.remove(x64::rVmTl); break; } break; case Vinstr::contenter: case Vinstr::callstub: defs = abi.all(); switch (arch()) { case Arch::ARM: defs.remove(PhysReg(arm::rVmFp)); break; case Arch::X64: defs -= reg::rbp | x64::rVmTl; break; } break; case Vinstr::cqo: uses = RegSet(reg::rax); defs = reg::rax | reg::rdx; break; case Vinstr::idiv: uses = defs = reg::rax | reg::rdx; break; case Vinstr::shlq: case Vinstr::sarq: across = RegSet(reg::rcx); break; // arm instrs case Vinstr::hostcall: defs = (abi.all() - abi.calleeSaved) | RegSet(PhysReg(arm::rHostCallReg)); break; case Vinstr::vcall: case Vinstr::vinvoke: case Vinstr::vcallstub: always_assert(false && "Unsupported instruction in vxls"); default: break; } }
void CodeGenerator::cgCallHelper(Vout& v, CppCall call, const CallDest& dstInfo, SyncOptions sync, ArgGroup& args) { auto dstReg0 = dstInfo.reg0; DEBUG_ONLY auto dstReg1 = dstInfo.reg1; RegSet argRegs; for (size_t i = 0; i < args.numGpArgs(); i++) { auto const r = rarg(i); args.gpArg(i).setDstReg(r); argRegs.add(r); } always_assert_flog( args.numStackArgs() == 0, "Stack arguments not yet supported on ARM: `{}'", *m_curInst ); shuffleArgs(v, args, call); auto syncPoint = emitCall(v, call, argRegs); if (RuntimeOption::HHProfServerEnabled || sync != SyncOptions::kNoSyncPoint) { recordHostCallSyncPoint(v, syncPoint); } auto* taken = m_curInst->taken(); if (taken && taken->isCatch()) { assert_not_implemented(args.numStackArgs() == 0); auto next = v.makeBlock(); v << hcunwind{syncPoint, {next, m_state.labels[taken]}}; v = next; } else if (!m_curInst->is(Call, CallArray, ContEnter)) { v << hcnocatch{syncPoint}; } switch (dstInfo.type) { case DestType::TV: CG_PUNT(cgCall-ReturnTV); case DestType::SIMD: CG_PUNT(cgCall-ReturnSIMD); case DestType::SSA: case DestType::Byte: assertx(dstReg1 == InvalidReg); v << copy{PhysReg(vixl::x0), dstReg0}; break; case DestType::None: assertx(dstReg0 == InvalidReg && dstReg1 == InvalidReg); break; case DestType::Dbl: assertx(dstReg1 == InvalidReg); v << copy{PhysReg(vixl::d0), dstReg0}; break; } }
// When all registers are in use, find a good interval to split and spill, // which could be the current interval. When an interval is split and the // second part is spilled, possibly split the second part again before the // next use-pos that requires a register, and enqueue the third part. void Vxls::allocBlocked(Interval* current) { PhysReg::Map<unsigned> used, blocked; RegSet allow; unsigned conflict = constrain(current, allow); // repeated from allocate allow.forEach([&](PhysReg r) { used[r] = blocked[r] = conflict; }); auto const cur_start = current->start(); // compute next use of active registers, so we can pick the furthest one for (auto ivl : active) { if (ivl->fixed()) { blocked[ivl->reg] = used[ivl->reg] = 0; } else { auto use_pos = ivl->firstUseAfter(cur_start); used[ivl->reg] = std::min(use_pos, used[ivl->reg]); } } // compute next intersection/use of inactive regs to find whats free longest for (auto ivl : inactive) { auto intersect_pos = current->nextIntersect(ivl); if (intersect_pos == kMaxPos) continue; if (ivl->fixed()) { blocked[ivl->reg] = std::min(intersect_pos, blocked[ivl->reg]); used[ivl->reg] = std::min(blocked[ivl->reg], used[ivl->reg]); } else { auto use_pos = ivl->firstUseAfter(cur_start); used[ivl->reg] = std::min(use_pos, used[ivl->reg]); } } // choose the best victim register(s) to spill auto r = find(used); auto used_pos = used[r]; if (used_pos < current->firstUse()) { // all other intervals are used before current's first register-use return spill(current); } auto block_pos = blocked[r]; if (block_pos < current->end()) { auto prev_use = current->lastUseBefore(block_pos); auto min_split = std::max(prev_use, cur_start + 1); auto max_split = block_pos; assert(cur_start < min_split && min_split <= max_split); auto split_pos = std::max(min_split, max_split); split_pos = nearestSplitBefore(split_pos); if (split_pos > current->start()) { auto second = current->split(split_pos, true); pending.push(second); } } spillOthers(current, r); assignReg(current, r); }
std::string show(RegSet regs) { std::ostringstream out; auto sep = ""; out << '{'; regs.forEach([&](PhysReg r) { out << sep << show(r); sep = ", "; }); out << '}'; return out.str(); }
PhysRegSaverParity::PhysRegSaverParity(int parity, X64Assembler& as, RegSet regs) : m_as(as) , m_regs(regs) , m_adjust((parity & 0x1) == (regs.size() & 0x1) ? 8 : 0) { m_regs.forEach([&] (PhysReg pr) { m_as. push (pr); }); if (m_adjust) { // Maintain stack evenness for SIMD compatibility. m_as. subq (m_adjust, reg::rsp); } }
std::string show(RegSet regs) { auto& backEnd = mcg->backEnd(); std::ostringstream out; auto sep = ""; out << '{'; regs.forEach([&](PhysReg r) { out << sep; backEnd.streamPhysReg(out, r); sep = ", "; }); out << '}'; return out.str(); }
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; }
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::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.take(); }
void getEffects(const Abi& abi, const Vinstr& i, RegSet& uses, RegSet& across, RegSet& defs) { uses = defs = across = RegSet(); switch (i.op) { case Vinstr::mccall: case Vinstr::call: case Vinstr::callm: case Vinstr::callr: defs = abi.all() - (abi.calleeSaved | rvmfp()); switch (arch()) { case Arch::ARM: defs.add(PhysReg(arm::rLinkReg)); break; case Arch::X64: break; case Arch::PPC64: not_implemented(); break; } break; case Vinstr::bindcall: defs = abi.all(); switch (arch()) { case Arch::ARM: break; case Arch::X64: defs.remove(rvmtl()); break; case Arch::PPC64: not_implemented(); break; } break; case Vinstr::contenter: case Vinstr::callarray: defs = abi.all() - RegSet(rvmfp()); switch (arch()) { case Arch::ARM: break; case Arch::X64: defs.remove(rvmtl()); break; case Arch::PPC64: not_implemented(); break; } break; case Vinstr::callfaststub: defs = abi.all() - abi.calleeSaved - abi.gpUnreserved; break; case Vinstr::cqo: uses = RegSet(reg::rax); defs = reg::rax | reg::rdx; break; case Vinstr::idiv: uses = defs = reg::rax | reg::rdx; break; case Vinstr::shlq: case Vinstr::sarq: across = RegSet(reg::rcx); break; // arm instrs case Vinstr::hostcall: defs = (abi.all() - abi.calleeSaved) | RegSet(PhysReg(arm::rHostCallReg)); break; case Vinstr::vcall: case Vinstr::vinvoke: case Vinstr::vcallarray: always_assert(false && "Unsupported instruction in vxls"); default: break; } }
void PhysRegSaverParity::emitPops(X64Assembler& as, RegSet regs) { regs.forEachR([&] (PhysReg pr) { as. pop (pr); }); }
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; }