Exemple #1
0
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;
}
Exemple #2
0
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();
}
Exemple #3
0
/*
 * 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;
}
Exemple #4
0
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);
}
Exemple #5
0
RegSet PhysLoc::regs() const {
  RegSet regs;
  if (hasReg(0)) {
    regs.add(reg(0));
    if (hasReg(1)) regs.add(reg(1));
  }
  return regs;
}
Exemple #6
0
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;
  }
}
Exemple #7
0
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;
  }
}
Exemple #8
0
// 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);
}
Exemple #9
0
std::string show(RegSet regs) {
  std::ostringstream out;
  auto sep = "";

  out << '{';
  regs.forEach([&](PhysReg r) {
    out << sep << show(r);
    sep = ", ";
  });
  out << '}';

  return out.str();
}
Exemple #10
0
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);
  }
}
Exemple #11
0
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();
}
Exemple #12
0
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;
}
Exemple #13
0
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();
}
Exemple #14
0
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;
  }
}
Exemple #15
0
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;
}