Exemple #1
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 #2
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 #3
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 #4
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();
}