Beispiel #1
0
void TraceBuilder::appendInstruction(IRInstruction* inst) {
  if (m_curWhere) {
    // We have a specific position to insert instructions.
    assert(!inst->isBlockEnd());
    auto& it = m_curWhere.get();
    it = m_curBlock->insert(it, inst);
    ++it;
    return;
  }

  Block* block = m_curTrace->back();
  if (!block->empty()) {
    IRInstruction* prev = &block->back();
    if (prev->isBlockEnd()) {
      // start a new block
      Block* next = m_unit.defBlock();
      FTRACE(2, "lazily adding B{}\n", next->id());
      m_curTrace->push_back(next);
      if (!prev->isTerminal()) {
        // new block is reachable from old block so link it.
        block->setNext(next);
        next->setHint(block->hint());
      }
      block = next;
    }
  }
  appendInstruction(inst, block);
  if (m_savedTraces.empty()) {
    // We don't track state on non-main traces for now. t2982555
    m_state.update(inst);
  }
}
Beispiel #2
0
void TraceBuilder::appendInstruction(IRInstruction* inst) {
  if (m_curWhere) {
    // We have a specific position to insert instructions.
    assert(!inst->isBlockEnd());
    auto& it = m_curWhere.get();
    it = m_curBlock->insert(it, inst);
    ++it;
    return;
  }

  Block* block = m_curTrace->back();
  if (!block->empty()) {
    IRInstruction* prev = block->back();
    if (prev->isBlockEnd()) {
      // start a new block
      Block* next = m_irFactory.defBlock(m_curFunc->getValFunc());
      m_curTrace->push_back(next);
      if (!prev->isTerminal()) {
        // new block is reachable from old block so link it.
        block->setNext(next);
      }
      block = next;
    }
  }
  appendInstruction(inst, block);
  updateTrackedState(inst);
}
Beispiel #3
0
void TraceBuilder::appendInstruction(IRInstruction* inst) {
  Block* block = m_trace->back();
  IRInstruction* prev = block->back();
  if (prev->isBlockEnd()) {
    // start a new block
    Block* next = m_irFactory.defBlock(m_curFunc->getValFunc());
    m_trace->push_back(next);
    if (!prev->isTerminal()) {
      // new block is reachable from old block so link it.
      block->setNext(next);
    }
    block = next;
  }
  appendInstruction(inst, block);
  updateTrackedState(inst);
}
void LinearScan::allocRegsToTrace() {
  // First, visit every instruction, allocating registers as we go,
  // and inserting Reload instructions where necessary.
  for (Block* block : m_blocks) {
    // clear remembered reloads that don't dominate this block
    for (SlotInfo& slot : m_slots) {
      if (SSATmp* reload = slot.m_latestReload) {
        if (!dominates(reload->getInstruction()->getBlock(), block, m_idoms)) {
          slot.m_latestReload = nullptr;
        }
      }
    }
    for (auto it = block->begin(), end = block->end(); it != end; ++it) {
      allocRegToInstruction(it);
      if (RuntimeOption::EvalDumpIR > 3) {
        std::cout << "--- allocated to instruction: ";
        it->print(std::cout);
        std::cout << "\n";
      }
    }
  }

  // Now that we have visited all instructions and inserted Reloads
  // for SSATmps which needed to be spilled, we can go back and insert
  // the spills.  All uses must have been visited before we do this.
  // For each spill slot, insert the spill right after the instruction
  // that generated the value (without traversing everything else).
  for (SlotInfo& slot : m_slots) {
    IRInstruction* spill = slot.m_spillTmp->getInstruction();
    IRInstruction* inst = spill->getSrc(0)->getInstruction();
    Block* block = inst->getBlock();
    if (inst->isBlockEnd()) {
      block->getNext()->prepend(spill);
    } else {
      auto pos = block->iteratorTo(inst);
      block->insert(++pos, spill);
    }
  }
}
Beispiel #5
0
void LinearScan::allocRegsOneTrace(BlockList::iterator& blockIt,
                                   ExitTraceMap& etm) {
  auto const trace = (*blockIt)->trace();

  collectInfo(blockIt, trace);
  computePreColoringHint();

  auto v = etm.find(*blockIt);
  if (v != etm.end()) {
    assert(!trace->isMain());
    v->second.restore(this);
  } else {
    assert(blockIt == m_blocks.begin() && trace->isMain());
    initFreeList();
  }

  // First, visit every instruction, allocating registers as we go,
  // and inserting Reload instructions where necessary.
  bool isMain = trace->isMain();
  size_t sz = m_slots.size();
  while (blockIt != m_blocks.end()) {
    Block* block = *blockIt;
    if (block->trace() != trace) {
      if (!isMain) {
        break;
      } else {
        ++blockIt;
        continue;
      }
    }
    FTRACE(5, "Block{}: {} ({})\n",
           trace->isMain() ? "" : " (exit trace)",
           (*blockIt)->id(), (*blockIt)->postId());

    // clear remembered reloads that don't dominate this block
    for (SlotInfo& slot : m_slots) {
      if (SSATmp* reload = slot.latestReload) {
        if (!dominates(reload->inst()->block(), block, m_idoms)) {
          slot.latestReload = nullptr;
        }
      }
    }
    for (auto it = block->begin(), end = block->end(); it != end; ++it) {
      allocRegToInstruction(it);
      dumpIR<IRInstruction, kExtraLevel>(&*it, "allocated to instruction ");
    }
    if (isMain) {
      assert(block->trace()->isMain());
      if (block->taken() &&
          !block->taken()->trace()->isMain()) {
        etm[block->taken()].save(this);
      }
    }
    ++blockIt;
  }

  // Now that we have visited all instructions on this trace,
  // and inserted Reloads for SSATmps which needed to be spilled,
  // we can go back and insert the spills.
  // On the main trace, insert the spill right after the instruction
  // that generated the value (without traversing everything else).
  // On exit traces, if the instruction that generated the value
  // is on the main trace, insert the spill at the start of the trace,
  // otherwise, after the instruction that generated the value
  size_t begin = sz;
  size_t end = m_slots.size();

  while (begin < end) {
    SlotInfo& slot = m_slots[begin++];
    IRInstruction* spill = slot.spillTmp->inst();
    IRInstruction* inst = spill->src(0)->inst();
    Block* block = inst->block();
    if (!isMain && block->trace()->isMain()) {
      // We're on an exit trace, but the def is on the
      // main trace, so put it at the start of this trace
      if (spill->block()) {
        // its already been inserted in another exit trace
        assert(!spill->block()->trace()->isMain());
        spill = m_unit.cloneInstruction(spill);
      }
      trace->front()->prepend(spill);
    } else if (inst->isBlockEnd()) {
      block->next()->prepend(spill);
    } else {
      auto pos = block->iteratorTo(inst);
      block->insert(++pos, spill);
    }
  }
}