TransCFG::TransCFG(FuncId funcId, const ProfData* profData, const SrcDB& srcDB, const TcaTransIDMap& jmpToTransID) { assertx(profData); // add nodes for (auto tid : profData->funcProfTransIDs(funcId)) { assertx(profData->transRegion(tid) != nullptr); // This will skip DV Funclets if they were already // retranslated w/ the prologues: if (!profData->optimized(profData->transSrcKey(tid))) { int64_t weight = profData->absTransCounter(tid); addNode(tid, weight); } } // add arcs for (TransID dstId : nodes()) { SrcKey dstSK = profData->transSrcKey(dstId); RegionDesc::BlockPtr dstBlock = profData->transRegion(dstId)->entry(); FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId); TransIDSet predIDs = findPredTrans(dstId, profData, srcDB, jmpToTransID); for (auto predId : predIDs) { if (hasNode(predId)) { auto predPostConds = profData->transRegion(predId)->blocks().back()->postConds(); SrcKey predSK = profData->transSrcKey(predId); if (preCondsAreSatisfied(dstBlock, predPostConds) && predSK.resumed() == dstSK.resumed()) { FTRACE(5, "TransCFG: adding arc {} -> {} ({} -> {})\n", predId, dstId, showShort(predSK), showShort(dstSK)); addArc(predId, dstId, TransCFG::Arc::kUnknownWeight); } } } } // infer arc weights bool changed; do { changed = false; for (TransID tid : nodes()) { int64_t nodeWeight = weight(tid); if (inferredArcWeight(inArcs(tid), nodeWeight)) changed = true; if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true; } } while (changed); // guess weight for non-inferred arcs for (TransID tid : nodes()) { for (auto arc : outArcs(tid)) { if (arc->weight() == Arc::kUnknownWeight) { arc->setGuessed(); int64_t arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2; arc->setWeight(arcWgt); } } } }
TransCFG::TransCFG(FuncId funcId, const ProfData* profData, const SrcDB& srcDB, const TcaTransIDMap& jmpToTransID) { assert(profData); // add nodes for (TransID tid = 0; tid < profData->numTrans(); tid++) { if (profData->transKind(tid) == TransProfile && profData->transRegion(tid) != nullptr && profData->transFuncId(tid) == funcId) { int64_t counter = profData->transCounter(tid); int64_t weight = RuntimeOption::EvalJitPGOThreshold - counter; addNode(tid, weight); } } // add arcs for (TransID dstId : nodes()) { SrcKey dstSK = profData->transSrcKey(dstId); const SrcRec* dstSR = srcDB.find(dstSK); FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId); TransIDSet predIDs = findPredTrans(dstSR, jmpToTransID); for (auto predId : predIDs) { if (hasNode(predId)) { FTRACE(5, "TransCFG: adding arc {} -> {}\n", predId, dstId); addArc(predId, dstId, TransCFG::Arc::kUnknownWeight); } } } // infer arc weights bool changed; do { changed = false; for (TransID tid : nodes()) { int64_t nodeWeight = weight(tid); if (inferredArcWeight(inArcs(tid), nodeWeight)) changed = true; if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true; } } while (changed); // guess weight or non-inferred arcs for (TransID tid : nodes()) { for (auto arc : outArcs(tid)) { if (arc->weight() == Arc::kUnknownWeight) { arc->setGuessed(); int64_t arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2; arc->setWeight(arcWgt); } } } }
bool TransCFG::hasArc(TransID srcId, TransID dstId) const { assertx(hasNode(srcId)); assertx(hasNode(dstId)); for (auto arc : outArcs(srcId)) { if (arc->dst() == dstId) return true; } return false; }
TransCFG::ArcPtrVec TransCFG::arcs() const { ArcPtrVec arcs; for (auto node : nodes()) { const ArcPtrVec& nodeOutArcs = outArcs(node); arcs.insert(arcs.end(), nodeOutArcs.begin(), nodeOutArcs.end()); } return arcs; }
void TransCFG::print(std::string fileName, FuncId funcId, const ProfData* profData, const TransIDSet* selected) const { FILE* file = fopen(fileName.c_str(), "wt"); if (!file) return; fprintf(file, "digraph CFG {\n"); fprintf(file, "# function: %s\n", Func::fromFuncId(funcId)->fullName()->data()); // find max node weight int64_t maxWeight = 1; // 1 to avoid div by 0 for (auto tid : nodes()) { auto w = weight(tid); if (w > maxWeight) maxWeight = w; } // print nodes for (auto tid : nodes()) { int64_t w = weight(tid); uint32_t coldness = 255 - (255 * w / maxWeight); Offset bcStart = profData->transStartBcOff(tid); Offset bcStop = profData->transStopBcOff(tid); const char* shape = selected && selected->count(tid) ? "oval" : "box"; fprintf(file, "t%u [shape=%s,label=\"T: %u\\np: %" PRId64 "\\n" "bc: [%" PRIu32 "-%" PRIu32 ")\"," "style=filled,fillcolor=\"#ff%02x%02x\"];\n", tid, shape, tid, w, bcStart, bcStop, coldness, coldness); } // print arcs for (auto srcId : nodes()) { for (auto arc : outArcs(srcId)) { int64_t w = arc->weight(); fprintf(file, "t%u -> t%u [color=\"%s\",label=\"%" PRId64 "\"] ;\n", srcId, arc->dst(), arc->guessed() ? "red" : "green4", w); } } fprintf(file, "}\n"); fclose(file); }
void TransCFG::print(std::ostream& out, FuncId funcId, const ProfData* profData) const { out << "digraph TransCFG { // function: " << Func::fromFuncId(funcId)->fullName()->data() << "\n"; // find max node weight int64_t maxWeight = 1; // 1 to avoid div by 0 for (auto tid : nodes()) { auto w = weight(tid); if (w > maxWeight) maxWeight = w; } // print nodes for (auto const tid : nodes()) { auto const w = weight(tid); uint32_t coldness = 255 - (255 * w / maxWeight); auto const rec = profData->transRec(tid); auto const bcStart = rec->startBcOff(); auto const bcStop = rec->lastBcOff(); auto const shape = "box"; out << folly::sformat( "t{} [shape={},label=\"T: {}\\np: {}\\n" "bc: [{}-{})\",style=filled,fillcolor=\"#ff{:02x}{:02x}\"];\n", tid, shape, tid, w, bcStart, bcStop, coldness, coldness); } // print arcs for (auto srcId : nodes()) { for (auto arc : outArcs(srcId)) { auto const w = arc->weight(); out << folly::sformat("t{} -> t{} [color=\"{}\",label=\"{}\"] ;\n", srcId, arc->dst(), arc->guessed() ? "red" : "green4", w); } } out << "}\n"; }
TransCFG::TransCFG(FuncId funcId, const ProfData* profData, bool inlining /* = false */) { assertx(profData); // add nodes for (auto const tid : profData->funcProfTransIDs(funcId)) { auto const rec = profData->transRec(tid); assertx(rec->region() != nullptr); // This will skip DV Funclets if they were already // retranslated w/ the prologues: if (inlining || !profData->optimized(rec->srcKey())) { int64_t weight = profData->transCounter(tid); addNode(tid, weight); } } // add arcs for (auto const dstId : nodes()) { auto const rec = profData->transRec(dstId); auto const dstSK = rec->srcKey(); auto const dstBlock = rec->region()->entry(); FTRACE(5, "TransCFG: adding incoming arcs in dstId = {}\n", dstId); TransIDSet predIDs = findPredTrans(dstId, profData); for (auto predId : predIDs) { if (hasNode(predId)) { auto const predRec = profData->transRec(predId); auto const predBlock = predRec->region()->blocks().back(); auto const& postConds = predBlock->postConds(); auto predPostConds = postConds.changed; predPostConds.insert(predPostConds.end(), postConds.refined.begin(), postConds.refined.end()); auto const predSK = predRec->srcKey(); if (preCondsAreSatisfied(dstBlock, predPostConds) && predSK.resumed() == dstSK.resumed()) { FTRACE(5, "TransCFG: adding arc {} -> {} ({} -> {})\n", predId, dstId, showShort(predSK), showShort(dstSK)); addArc(predId, dstId, TransCFG::Arc::kUnknownWeight); } } } } // infer arc weights bool changed; do { changed = false; for (auto const tid : nodes()) { auto const nodeWeight = weight(tid); if (inferredArcWeight(inArcs(tid), nodeWeight)) changed = true; if (inferredArcWeight(outArcs(tid), nodeWeight)) changed = true; } } while (changed); // guess weight for non-inferred arcs for (auto const tid : nodes()) { for (auto arc : outArcs(tid)) { if (arc->weight() == Arc::kUnknownWeight) { arc->setGuessed(); auto arcWgt = std::min(weight(arc->src()), weight(arc->dst())) / 2; arc->setWeight(arcWgt); } } } }