RegionDesc::BlockVec::iterator RegionDesc::deleteBlock(RegionDesc::BlockVec::iterator it) { const auto bid = (*it)->id(); for (auto pid : preds(bid)) removeArc(pid, bid); for (auto sid : succs(bid)) removeArc(bid, sid); if (auto nextR = nextRetrans(bid)) { auto prevR = prevRetrans(bid); clearPrevRetrans(nextR.value()); if (prevR) { clearNextRetrans(prevR.value()); setNextRetrans(prevR.value(), nextR.value()); } else { clearPrevRetrans(nextR.value()); } } else if (auto prevR = prevRetrans(bid)) { clearNextRetrans(prevR.value()); } m_data.erase(bid); return m_blocks.erase(it); }
/** * 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->absTransCounter(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); } } } // 6. Reorder the blocks in the region in topological order (if // region is acyclic), since the previous steps may break it. sortBlocks(); }