Esempio n. 1
0
std::string show(const RegionDesc& region) {
  std::string ret{folly::sformat("Region ({} blocks):\n",
                                 region.blocks().size())};

  auto profData = mcg->tx().profData();

  auto weight = [&] (RegionDesc::BlockPtr b) -> int64_t {
    if (!profData) return 0;
    auto tid = b->profTransID();
    if (tid == kInvalidTransID) return 0;
    return profData->transCounter(tid);
  };

  uint64_t maxBlockWgt = 1; // avoid div by 0

  // Print contents of all blocks in pure text format.
  for (auto& b : region.blocks()) {
    folly::toAppend(show(*b), &ret);
    auto w = weight(b);
    if (w > maxBlockWgt) maxBlockWgt = w;
  }

  // Print CFG in dot format, coloring the blocks based on hotness.
  // Print all the blocks first.
  folly::toAppend("\ndigraph RegionCFG {\n node[shape=box,style=filled]\n",
                  &ret);
  for (auto& b : region.blocks()) {
    auto const id = b->id();
    auto const& mergedSet = region.merged(id);
    std::string mergedStr = mergedSet.empty() ? "" :
                            (" (" + folly::join(",", mergedSet) + ")");
    uint32_t coldness = 255 - (255 * weight(b) / maxBlockWgt);
    folly::format(&ret, " \"B{}\" [label=\"B {}{}\\np: {}\","
                  "fillcolor=\"#ff{:02x}{:02x}\"]\n",
                  id, id, mergedStr, weight(b), coldness, coldness);
  }

  // Print arcs in dot format.
  for (auto& b : region.blocks()) {
    if (auto r = region.nextRetrans(b->id())) {
      folly::toAppend(folly::format(" \"B{}\" -> \"B{}\" [label=R,color=red]\n",
                                    b->id(), r.value()), &ret);
    }
    for (auto s : region.succs(b->id())) {
      folly::toAppend(folly::format(" \"B{}\" -> \"B{}\"\n", b->id(), s),
                      &ret);
    }
  }

  ret += "}\n";

  return ret;
}
Esempio n. 2
0
/*
 * Computes the approximate number of times that `loop' was invoked
 * (i.e. entered) using profiling data.  This value is computed by
 * adding up the profiling weights of all the Profile translations
 * that may execute immediately before the Profile translation
 * containing the loop header.
 */
uint64_t countInvocations(const LoopInfo& loop, const IRUnit& unit) {
    always_assert(mcg->tx().profData());

    // Find the predecessor TransIDs along each non-back-edge
    // predecessor of the loop header.
    boost::dynamic_bitset<> visited(unit.numBlocks());
    TransIDSet predTIDs;
    auto headerTID = loop.header->front().marker().profTransID();
    for (auto& predEdge : loop.header->preds()) {
        if (loop.backEdges.count(&predEdge) == 0) {
            findPredTransIDs(headerTID, predEdge.from(), visited, predTIDs);
        }
    }
    auto const profData = mcg->tx().profData();
    uint64_t count = 0;
    for (auto tid : predTIDs) {
        count += profData->transCounter(tid);
    }
    return count;
}
Esempio n. 3
0
/**
 * Chain the retranslation blocks.  This method enforces that, for
 * each region block, all its successor have distinct SrcKeys.
 */
void RegionDesc::chainRetransBlocks() {

  jit::vector<Chain> chains;
  BlockToChainMap block2chain;

  // 1. Initially assign each region block to its own chain.
  for (auto b : blocks()) {
    auto bid = b->id();
    auto cid = chains.size();
    chains.push_back({cid, {bid}});
    block2chain[bid] = cid;
  }

  // 2. For each block, if it has 2 successors with the same SrcKey,
  //    then merge the successors' chains into one.
  for (auto b : blocks()) {
    auto bid = b->id();
    const auto& succSet = succs(bid);
    for (auto it1 = succSet.begin(); it1 != succSet.end(); it1++) {
      auto bid1 = *it1;
      auto cid1 = block2chain[bid1];
      for (auto it2 = it1 + 1; it2 != succSet.end(); it2++) {
        auto bid2 = *it2;
        auto cid2 = block2chain[bid2];
        if (data(bid1).block->start() == data(bid2).block->start()) {
          mergeChains(chains[cid1], chains[cid2], block2chain);
        }
      }
    }
  }

  // 3. Sort each chain.  In general, we want to sort each chain in
  //    decreasing order of profile weights.  However, note that this
  //    transformation can turn acyclic graphs into cyclic ones (see
  //    example below).  Therefore, if JitLoops are disabled, we
  //    instead sort each chain following the original block order,
  //    which prevents loops from being generated if the region was
  //    originally acyclic.
  //
  //    Here's an example showing how an acyclic CFG can become cyclic
  //    by chaining its retranslation blocks:
  //
  //      - Region before chaining retranslation blocks, where B2' and B2"
  //        are retranslations starting at the same SrcKey:
  //          B1  -> B2'
  //          B1  -> B2"
  //          B2' -> B3
  //          B3  -> B2"
  //
  //      - Region after sorting the chain as B2" -R-> B2':
  //          B1  ->   B2"
  //          B2" -R-> B2'
  //          B2' ->   B3
  //          B3  ->   B2"
  //        Note the cycle: B2" -R-> B2' -> B3 -> B2".
  //
  auto profData = mcg->tx().profData();

  auto weight = [&](RegionDesc::BlockId bid) {
    return hasTransID(bid) ? profData->transCounter(getTransID(bid)) : 0;
  };

  auto sortGeneral = [&](RegionDesc::BlockId bid1, RegionDesc::BlockId bid2) {
    return weight(bid1) > weight(bid2);
  };

  using SortFun = std::function<bool(RegionDesc::BlockId, RegionDesc::BlockId)>;
  SortFun sortFunc = sortGeneral;

  hphp_hash_map<RegionDesc::BlockId, uint32_t> origBlockOrder;
  if (!RuntimeOption::EvalJitLoops) {
    for (uint32_t i = 0; i < m_blocks.size(); i++) {
      origBlockOrder[m_blocks[i]->id()] = i;
    }
    auto sortAcyclic = [&](RegionDesc::BlockId bid1, RegionDesc::BlockId bid2) {
      return origBlockOrder[bid1] < origBlockOrder[bid2];
    };
    sortFunc = sortAcyclic;
  }

  TRACE(1, "chainRetransBlocks: computed chains:\n");
  for (auto& c : chains) {
    std::sort(c.blocks.begin(), c.blocks.end(), sortFunc);

    if (Trace::moduleEnabled(Trace::region, 1) && c.blocks.size() > 0) {
      FTRACE(1, "  -> {} (w={})", c.blocks[0], weight(c.blocks[0]));
      for (size_t i = 1; i < c.blocks.size(); i++) {
        FTRACE(1, ", {} (w={})", c.blocks[i], weight(c.blocks[i]));
      }
      FTRACE(1, "\n");
    }
  }

  // 4. Set the nextRetrans blocks according to the computed chains.
  for (auto& c : chains) {
    if (c.blocks.size() == 0) continue;
    for (size_t i = 0; i < c.blocks.size() - 1; i++) {
      setNextRetrans(c.blocks[i], c.blocks[i + 1]);
    }
  }

  // 5. For each block with multiple successors in the same chain,
  //    only keep the successor that first appears in the chain.
  for (auto b : blocks()) {
    auto& succSet = data(b->id()).succs;
    for (auto s : succSet) {
      auto& c = chains[block2chain[s]];
      auto selectedSucc = findFirstInSet(c, succSet);
      for (auto other : c.blocks) {
        if (other == selectedSucc) continue;
        succSet.erase(other);
        data(other).preds.erase(b->id());
      }
    }
  }

  // 6. Reorder the blocks in the region in topological order (if
  //    region is acyclic), since the previous steps may break it.
  sortBlocks();
}