Exemplo n.º 1
0
/*
 * Compute the stack and local type postconditions for a
 * single-entry/single-exit tracelet.
 */
std::vector<RegionDesc::TypePred> IRBuilder::getKnownTypes() {
  // This function is only correct when given a single-exit region, as
  // in TransProfile.  Furthermore, its output is only used to guide
  // formation of profile-driven regions.
  assert(tx->mode() == TransProfile);

  // We want the state for the last block on the "main trace".  Figure
  // out which that is.
  Block* mainExit = nullptr;
  for (auto* b : rpoSortCfg(m_unit)) {
    if (isMainExit(b)) {
      assert(mainExit == nullptr);
      mainExit = b;
    }
  }
  assert(mainExit != nullptr);

  // Load state for mainExit.  This feels hacky.
  FTRACE(1, "mainExit: B{}\n", mainExit->id());
  m_state.startBlock(mainExit);

  // Now use the current state to get all the types.
  std::vector<RegionDesc::TypePred> result;
  auto const curFunc  = m_state.func();
  auto const sp       = m_state.sp();
  auto const spOffset = m_state.spOffset();

  for (unsigned i = 0; i < curFunc->maxStackCells(); ++i) {
    auto t = getStackValue(sp, i).knownType;
    if (!t.equals(Type::StackElem)) {
      result.push_back({ RegionDesc::Location::Stack{i, spOffset - i}, t });
    }
  }

  for (unsigned i = 0; i < curFunc->numLocals(); ++i) {
    auto t = m_state.localType(i);
    if (!t.equals(Type::Gen)) {
      FTRACE(1, "Local {}: {}\n", i, t.toString());
      result.push_back({ RegionDesc::Location::Local{i}, t });
    }
  }
  return result;
}
Exemplo n.º 2
0
/*
 * Intended to be called after all optimizations are finished on a
 * single-entry, single-exit tracelet, this collects the types of all stack
 * slots and locals at the end of the main exit.
 */
void IRUnit::collectPostConditions() {
  // This function is only correct when given a single-exit region, as in
  // TransKind::Profile.  Furthermore, its output is only used to guide
  // formation of profile-driven regions.
  assert(mcg->tx().mode() == TransKind::Profile);
  assert(m_postConds.empty());
  Timer _t(Timer::collectPostConditions);

  // We want the state for the last block on the "main trace".  Figure
  // out which that is.
  Block* mainExit = nullptr;
  Block* lastMainBlock = nullptr;

  FrameStateMgr state{*this, entry()->front().marker()};
  // TODO(#5678127): this code is wrong for HHIRBytecodeControlFlow
  state.setLegacyReoptimize();
  ITRACE(2, "collectPostConditions starting\n");
  Trace::Indent _i;

  for (auto* block : rpoSortCfg(*this)) {
    state.startBlock(block, block->front().marker());

    for (auto& inst : *block) {
      state.update(&inst);
    }

    if (isMainBlock(block)) lastMainBlock = block;

    if (isMainExit(block)) {
      mainExit = block;
      break;
    }

    state.finishBlock(block);
  }

  // If we didn't find an obvious exit, then use the last block in the region.
  always_assert(lastMainBlock != nullptr);
  if (mainExit == nullptr) mainExit = lastMainBlock;

  FTRACE(1, "mainExit: B{}\n", mainExit->id());

  // state currently holds the state at the end of mainExit
  auto const curFunc  = state.func();
  auto const sp       = state.sp();
  auto const spOffset = state.spOffset();

  for (unsigned i = 0; i < spOffset; ++i) {
    auto t = getStackValue(sp, i).knownType;
    if (!t.equals(Type::StackElem)) {
      m_postConds.push_back({ RegionDesc::Location::Stack{i, spOffset - i},
                              t });
    }
  }

  for (unsigned i = 0; i < curFunc->numLocals(); ++i) {
    auto t = state.localType(i);
    if (!t.equals(Type::Gen)) {
      FTRACE(1, "Local {}: {}\n", i, t.toString());
      m_postConds.push_back({ RegionDesc::Location::Local{i}, t });
    }
  }
}