/* * Records any type/reffiness predictions we depend on in the region. Guards * for locals and stack cells that are not used will be eliminated by the call * to relaxGuards. */ void RegionFormer::recordDependencies() { // Record the incrementally constructed reffiness predictions. assertx(!m_region->empty()); auto& frontBlock = *m_region->blocks().front(); for (auto const& dep : m_refDeps.m_arMap) { frontBlock.addReffinessPred(m_startSk, {dep.second.m_mask, dep.second.m_vals, dep.first}); } // Relax guards and record the ones that survived. auto& firstBlock = *m_region->blocks().front(); auto blockStart = firstBlock.start(); auto& unit = m_irgs.unit; auto const doRelax = RuntimeOption::EvalHHIRRelaxGuards; bool changed = false; if (doRelax) { Timer _t(Timer::selectTracelet_relaxGuards); // The IR is going to be discarded immediately, so skip reflowing // the types in relaxGuards to save JIT time. RelaxGuardsFlags flags = m_profiling ? RelaxSimple : RelaxNormal; changed = relaxGuards(unit, *m_irgs.irb->guards(), flags); } auto guardMap = std::map<RegionDesc::Location,Type>{}; ITRACE(2, "Visiting guards\n"); visitGuards(unit, [&](const RegionDesc::Location& loc, Type type) { Trace::Indent indent; ITRACE(3, "{}: {}\n", show(loc), type); if (type <= TCls) return; auto inret = guardMap.insert(std::make_pair(loc, type)); if (inret.second) return; auto& oldTy = inret.first->second; if (oldTy == TGen) { // This is the case that we see an inner type prediction for a GuardLoc // that got relaxed to Gen. return; } oldTy &= type; }); for (auto& kv : guardMap) { if (kv.second == TGen) { // Guard was relaxed to Gen---don't record it. continue; } auto const preCond = RegionDesc::TypedLocation { kv.first, kv.second }; ITRACE(1, "selectTracelet adding guard {}\n", show(preCond)); firstBlock.addPreCondition(blockStart, preCond); } if (changed) { printUnit(3, unit, " after guard relaxation ", nullptr, m_irgs.irb->guards()); } }
/* * Records any type/reffiness predictions we depend on in the region. */ void recordDependencies(Env& env) { // Record the incrementally constructed reffiness predictions. assertx(!env.region->empty()); auto& frontBlock = *env.region->blocks().front(); for (auto const& dep : env.refDeps.m_arMap) { frontBlock.addReffinessPred({dep.second.m_mask, dep.second.m_vals, dep.first}); } // Relax guards and record the ones that survived. auto& firstBlock = *env.region->blocks().front(); auto& unit = env.irgs.unit; auto guardMap = std::map<RegionDesc::Location,Type>{}; ITRACE(2, "Visiting guards\n"); auto hintMap = std::map<RegionDesc::Location,Type>{}; auto catMap = std::map<RegionDesc::Location,DataTypeCategory>{}; const auto& guards = env.irgs.irb->guards()->guards; visitGuards(unit, [&](IRInstruction* guard, const RegionDesc::Location& loc, Type type, bool hint) { Trace::Indent indent; ITRACE(3, "{}: {}\n", show(loc), type); if (type <= TCls) return; auto& whichMap = hint ? hintMap : guardMap; auto inret = whichMap.insert(std::make_pair(loc, type)); if (inret.second) { if (!hint) { catMap[loc] = folly::get_default(guards, guard).category; } return; } auto& oldTy = inret.first->second; oldTy &= type; if (!hint) { auto& oldCat = catMap[loc]; auto newCat = folly::get_default(guards, guard).category; oldCat = std::max(oldCat, newCat); } }); for (auto& kv : guardMap) { auto const hint_it = hintMap.find(kv.first); // If we have a hinted type that's better than the guarded type, we want to // keep it around. This can really only when a guard is relaxed away to // Gen because we knew something was a BoxedCell statically, but we may // need to keep information about what inner type we were predicting. if (hint_it != end(hintMap) && hint_it->second < kv.second) { auto const pred = RegionDesc::TypedLocation { hint_it->first, hint_it->second }; FTRACE(1, "selectTracelet adding prediction {}\n", show(pred)); firstBlock.addPredicted(pred); } if (kv.second == TGen) { // Guard was relaxed to Gen---don't record it. But if there's a hint, we // may have needed that (recorded already above). continue; } auto const preCond = RegionDesc::GuardedLocation { kv.first, kv.second, catMap[kv.first] }; ITRACE(1, "selectTracelet adding guard {}\n", show(preCond)); firstBlock.addPreCondition(preCond); } }
/* * Records any type/reffiness predictions we depend on in the region. */ void recordDependencies(Env& env) { // Record the incrementally constructed reffiness predictions. assertx(!env.region->empty()); auto& frontBlock = *env.region->blocks().front(); for (auto const& dep : env.refDeps.m_arMap) { frontBlock.addReffinessPred({dep.second.m_mask, dep.second.m_vals, dep.first}); } // Relax guards and record the ones that survived. auto& firstBlock = *env.region->blocks().front(); auto& unit = env.irgs.unit; auto guardMap = std::map<Location,Type>{}; ITRACE(2, "Visiting guards\n"); auto hintMap = std::map<Location,Type>{}; auto catMap = std::map<Location,DataTypeCategory>{}; const auto& guards = env.irgs.irb->guards()->guards; auto predictionMap = std::map<Location,Type>{}; visitGuards(unit, [&] (const IRInstruction* guard, const Location& loc, Type type, bool hint) { Trace::Indent indent; ITRACE(3, "{}: {}\n", show(loc), type); assertx(type <= TGen); auto& whichMap = hint ? hintMap : guardMap; auto inret = whichMap.insert(std::make_pair(loc, type)); // Unconstrained pseudo-main guards will be relaxed to Gen by the guard // relaxation pass. Since we don't allow loading TGen locals // in pseudo-main, save the predicted type here. if (guard->marker().func()->isPseudoMain()) { auto ret = predictionMap.insert(std::make_pair(loc,type)); if (ret.second) { FTRACE(1, "selectTracelet saving prediction for PseudoMain {}\n", show(RegionDesc::TypedLocation {loc, type})); } else { auto& oldTy = ret.first->second; oldTy &= type; } } if (inret.second) { if (!hint) { catMap[loc] = folly::get_default(guards, guard).category; } return; } auto& oldTy = inret.first->second; oldTy &= type; if (!hint) { auto& oldCat = catMap[loc]; auto newCat = folly::get_default(guards, guard).category; oldCat = std::max(oldCat, newCat); } }); for (auto& kv : guardMap) { auto const hint_it = hintMap.find(kv.first); // If we have a hinted type that's better than the guarded type, we want to // keep it around. This can really only when a guard is relaxed away to // Gen because we knew something was a BoxedCell statically, but we may // need to keep information about what inner type we were predicting. if (hint_it != end(hintMap) && hint_it->second < kv.second) { FTRACE(1, "selectTracelet adding prediction {}\n", show(RegionDesc::TypedLocation {hint_it->first, hint_it->second})); predictionMap.insert(*hint_it); } if (kv.second == TGen) { // Guard was relaxed to Gen---don't record it. But if there's a hint, we // may have needed that (recorded already above). continue; } auto const preCond = RegionDesc::GuardedLocation { kv.first, kv.second, catMap[kv.first] }; ITRACE(1, "selectTracelet adding guard {}\n", show(preCond)); firstBlock.addPreCondition(preCond); } // Predictions are already sorted by location, so we can simply compare // the type-prediction vectors for different blocks later. for (auto& pred : predictionMap) { firstBlock.addPredicted(RegionDesc::TypedLocation{pred.first, pred.second}); } }