Ejemplo n.º 1
0
RegionDescPtr selectHotRegion(TransID transId,
                              MCGenerator* mcg) {
  auto const profData = jit::profData();
  assertx(profData);
  auto const& func = *profData->transRec(transId)->func();
  FuncId funcId = func.getFuncId();
  TransCFG cfg(funcId, profData, mcg->srcDB());
  assertx(regionMode() != RegionMode::Method);
  RegionDescPtr region;
  HotTransContext ctx;
  ctx.cfg = &cfg;
  ctx.profData = profData;
  ctx.tid = transId;
  ctx.maxBCInstrs = RuntimeOption::EvalJitMaxRegionInstrs;
  switch (pgoRegionMode(func)) {
    case PGORegionMode::Hottrace:
      region = selectHotTrace(ctx);
      break;

    case PGORegionMode::Hotblock:
      region = selectHotBlock(transId, profData, cfg);
      break;

    case PGORegionMode::WholeCFG:
    case PGORegionMode::HotCFG:
      region = selectHotCFG(ctx);
      break;
  }
  assertx(region);

  if (Trace::moduleEnabled(HPHP::Trace::pgo, 5)) {
    std::string dotFileName = std::string("/tmp/trans-cfg-") +
                              folly::to<std::string>(transId) + ".dot";

    std::ofstream outFile(dotFileName);
    if (outFile.is_open()) {
      cfg.print(outFile, funcId, profData);
      outFile.close();
    }

    FTRACE(5, "selectHotRegion: New Translation (file: {}) {}\n",
           dotFileName, region ? show(*region) : std::string("empty region"));
  }

  always_assert(region->instrSize() <= RuntimeOption::EvalJitMaxRegionInstrs);

  if (region->empty()) return nullptr;
  return region;
}
Ejemplo n.º 2
0
RegionDescPtr selectHotRegion(TransID transId,
                              MCGenerator* mcg) {

  assertx(RuntimeOption::EvalJitPGO);

  const ProfData* profData = mcg->tx().profData();
  auto const& func = *(profData->transFunc(transId));
  FuncId funcId = func.getFuncId();
  TransCFG cfg(funcId, profData, mcg->tx().getSrcDB(),
               mcg->getJmpToTransIDMap());
  TransIDSet selectedTIDs;
  assertx(regionMode() != RegionMode::Method);
  RegionDescPtr region;
  HotTransContext ctx;
  ctx.cfg = &cfg;
  ctx.profData = profData;
  ctx.tid = transId;
  ctx.maxBCInstrs = RuntimeOption::EvalJitMaxRegionInstrs;
  switch (pgoRegionMode(func)) {
    case PGORegionMode::Hottrace:
      region = selectHotTrace(ctx, selectedTIDs);
      break;

    case PGORegionMode::Hotblock:
      region = selectHotBlock(transId, profData, cfg);
      break;

    case PGORegionMode::WholeCFG:
    case PGORegionMode::HotCFG:
      region = selectHotCFG(ctx, selectedTIDs);
      break;
  }
  assertx(region);

  if (Trace::moduleEnabled(HPHP::Trace::pgo, 5)) {
    std::string dotFileName = std::string("/tmp/trans-cfg-") +
                              folly::to<std::string>(transId) + ".dot";

    cfg.print(dotFileName, funcId, profData, &selectedTIDs);
    FTRACE(5, "selectHotRegion: New Translation {} (file: {}) {}\n",
           mcg->tx().profData()->curTransID(), dotFileName,
           region ? show(*region) : std::string("empty region"));
  }

  always_assert(region->instrSize() <= RuntimeOption::EvalJitMaxRegionInstrs);

  return region;
}
Ejemplo n.º 3
0
/**
 * Regionize a func, so that each node and each arc in its TransCFG is
 * "covered".  A node is covered if any region contains it.  An arc T1->T2
 * is covered if either:
 *
 *   a) T1 and T2 are in the same region R and R contains arc T1->T2.
 *   b) T2 is the head (first translation) of a region.
 *
 * Basic algorithm:
 *
 *   1) sort nodes in decreasing weight order
 *   2) for each node N:
 *      2.1) if N and all its incoming arcs are covered, then continue
 *      2.2) select a region starting at this node and mark nodes/arcs as
 *           covered appropriately
 */
void regionizeFunc(const Func* func,
                   MCGenerator* mcg,
                   RegionVec& regions) {
  const Timer rf_timer(Timer::regionizeFunc);
  assertx(RuntimeOption::EvalJitPGO);

  PGORegionMode regionMode = pgoRegionMode(*func);

  auto const funcId = func->getFuncId();
  auto const profData = mcg->tx().profData();
  TransCFG cfg(funcId, profData, mcg->tx().getSrcDB(),
               mcg->getJmpToTransIDMap());

  if (Trace::moduleEnabled(HPHP::Trace::pgo, 5)) {
    auto dotFileName = folly::to<std::string>(
      "/tmp/func-cfg-", funcId, ".dot");
    cfg.print(dotFileName, funcId, profData, nullptr);
    FTRACE(5, "regionizeFunc: initial CFG for func {} saved to file {}\n",
           funcId, dotFileName);
  }

  TransCFG::ArcPtrVec   arcs = cfg.arcs();
  std::vector<TransID> nodes = cfg.nodes();

  std::sort(nodes.begin(), nodes.end(),
            [&](TransID tid1, TransID tid2) -> bool {
              if (regionMode == PGORegionMode::WholeCFG ||
                  regionMode == PGORegionMode::HotCFG) {
                auto bcOff1 = profData->transStartBcOff(tid1);
                auto bcOff2 = profData->transStartBcOff(tid2);
                if (bcOff1 != bcOff2) return bcOff1 < bcOff2;
              }
              if (cfg.weight(tid1) != cfg.weight(tid2)) {
                return cfg.weight(tid1) > cfg.weight(tid2);
              }
              // In case of ties, pick older translations first, in an
              // attempt to start loops at their headers.
              return tid1 < tid2;
            });

  TransCFG::ArcPtrSet coveredArcs;
  TransIDSet          coveredNodes;
  TransIDSet          heads;
  TransIDToRegionMap  headToRegion;
  RegionToTransIDsMap regionToTransIds;
  regions.clear();

  for (auto node : nodes) {
    if (!coveredNodes.count(node) ||
        !allArcsCovered(cfg.inArcs(node),  coveredArcs)) {
      TransID newHead = node;
      FTRACE(6, "regionizeFunc: selecting trace to cover node {}\n", newHead);
      TransIDSet selectedSet;
      TransIDVec selectedVec;
      RegionDescPtr region;
      switch (regionMode) {
        case PGORegionMode::Hottrace:
          region = selectHotTrace(newHead, profData, cfg,
                                  RuntimeOption::EvalJitMaxRegionInstrs,
                                  selectedSet, &selectedVec);
          break;

        case PGORegionMode::WholeCFG:
        case PGORegionMode::HotCFG:
          region = selectHotCFG(newHead, profData, cfg,
                                RuntimeOption::EvalJitMaxRegionInstrs,
                                selectedSet, &selectedVec);
          break;

        case PGORegionMode::Hotblock:
          always_assert(0 && "Invalid value for EvalJitPGORegionSelector");
      }
      FTRACE(6, "regionizeFunc: selected region to cover node {}\n{}\n",
             newHead, show(*region));
      profData->setOptimized(profData->transSrcKey(newHead));
      assertx(selectedVec.size() > 0 && selectedVec[0] == newHead);
      regions.push_back(region);
      heads.insert(newHead);
      regionToTransIds[region] = selectedVec;
      headToRegion[newHead] = region;
      markCovered(cfg, region, selectedVec, heads, headToRegion,
                  coveredNodes, coveredArcs);

      FTRACE(6, "regionizeFunc: selected trace: {}\n",
             folly::join(", ", selectedVec));
    }
  }

  assertx(coveredNodes.size() == cfg.nodes().size());
  assertx(coveredArcs.size() == arcs.size());

  sortRegions(regions, func, cfg, profData, headToRegion, regionToTransIds);

  if (debug && Trace::moduleEnabled(HPHP::Trace::pgo, 5)) {
    FTRACE(5, "\n--------------------------------------------\n"
           "regionizeFunc({}): computed regions:\n", funcId);
    for (auto region : regions) {
      FTRACE(5, "{}\n\n", show(*region));
    }
  }
}