diff --git a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp --- a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp +++ b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp @@ -83,6 +83,12 @@ SplittingThreshold("hotcoldsplit-threshold", cl::init(2), cl::Hidden, cl::desc("Base penalty for splitting cold code (as a " "multiple of TCC_Basic)")); +static cl::opt + EnableRandomOutlining("hot-cold-randomly-outline-cold-code", cl::init(true), + cl::Hidden); + +static cl::opt EnableDeterministicRandomOutlining( + "hot-cold-deterministic-random-outline-code", cl::init(true), cl::Hidden); namespace { // Same as blockEndsInUnreachable in CodeGen/BranchFolding.cpp. Do not modify @@ -100,6 +106,20 @@ return !(isa(I) || isa(I)); } +static Optional> +hasSingleSuccAndPred(const BasicBlock &BB) { + auto FirstSucc = succ_begin(&BB); + auto SuccEnd = succ_end(&BB); + if (FirstSucc == SuccEnd || ++FirstSucc != SuccEnd) + return None; + auto FirstPred = pred_begin(&BB); + auto PredEnd = pred_end(&BB); + if (FirstPred == PredEnd || ++FirstPred != PredEnd) + return None; + return Optional>( + {*succ_begin(&BB), *pred_begin(&BB)}); +} + bool unlikelyExecuted(BasicBlock &BB) { // Exception handling blocks are unlikely executed. if (BB.isEHPad() || isa(BB.getTerminator())) @@ -122,6 +142,30 @@ return true; } + if (!EnableRandomOutlining) + return false; + + // Game of chance hypothesis: when most (80:20 rule) of the code is cold, + // a randomly selected basic block has a higher chance of being cold. Do this + // if the basic block is part of a diamond structure (if-else). + // NB: This causes non-deterministic outlining if rng is not seeded. + if (auto SuccPred = hasSingleSuccAndPred(BB)) { + auto Succ = SuccPred->first; + int SuccPredCount = pred_size(Succ); + if (SuccPredCount < 2) + return false; + auto Pred = SuccPred->second; + int PredSuccCount = succ_size(Pred); + if (PredSuccCount < 2) + return false; + double Chance = (std::rand() % PredSuccCount) / double(PredSuccCount); + // Threshold can be decreased to enable aggressive outlining. + if (Chance < 0.5) { + LLVM_DEBUG(dbgs() << "Randomly making cold: " << BB); + return true; + } + } + return false; } @@ -667,6 +711,9 @@ bool HotColdSplittingLegacyPass::runOnModule(Module &M) { if (skipModule(M)) return false; + // Initialize rng for deterministic aggressive outlining. + if (EnableDeterministicRandomOutlining) + std::srand(1); ProfileSummaryInfo *PSI = &getAnalysis().getPSI(); auto GTTI = [this](Function &F) -> TargetTransformInfo & {