aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/IPO/HotColdSplitting.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/HotColdSplitting.cpp76
1 files changed, 69 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
index 599ace9ca79f..fabb3c5fb921 100644
--- a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
+++ b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
@@ -44,6 +44,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/CommandLine.h"
@@ -86,6 +87,11 @@ static cl::opt<int> MaxParametersForSplit(
"hotcoldsplit-max-params", cl::init(4), cl::Hidden,
cl::desc("Maximum number of parameters for a split function"));
+static cl::opt<int> ColdBranchProbDenom(
+ "hotcoldsplit-cold-probability-denom", cl::init(100), cl::Hidden,
+ cl::desc("Divisor of cold branch probability."
+ "BranchProbability = 1/ColdBranchProbDenom"));
+
namespace {
// Same as blockEndsInUnreachable in CodeGen/BranchFolding.cpp. Do not modify
// this function unless you modify the MBB version as well.
@@ -102,6 +108,32 @@ bool blockEndsInUnreachable(const BasicBlock &BB) {
return !(isa<ReturnInst>(I) || isa<IndirectBrInst>(I));
}
+void analyzeProfMetadata(BasicBlock *BB,
+ BranchProbability ColdProbThresh,
+ SmallPtrSetImpl<BasicBlock *> &AnnotatedColdBlocks) {
+ // TODO: Handle branches with > 2 successors.
+ BranchInst *CondBr = dyn_cast<BranchInst>(BB->getTerminator());
+ if (!CondBr)
+ return;
+
+ uint64_t TrueWt, FalseWt;
+ if (!extractBranchWeights(*CondBr, TrueWt, FalseWt))
+ return;
+
+ auto SumWt = TrueWt + FalseWt;
+ if (SumWt == 0)
+ return;
+
+ auto TrueProb = BranchProbability::getBranchProbability(TrueWt, SumWt);
+ auto FalseProb = BranchProbability::getBranchProbability(FalseWt, SumWt);
+
+ if (TrueProb <= ColdProbThresh)
+ AnnotatedColdBlocks.insert(CondBr->getSuccessor(0));
+
+ if (FalseProb <= ColdProbThresh)
+ AnnotatedColdBlocks.insert(CondBr->getSuccessor(1));
+}
+
bool unlikelyExecuted(BasicBlock &BB) {
// Exception handling blocks are unlikely executed.
if (BB.isEHPad() || isa<ResumeInst>(BB.getTerminator()))
@@ -183,6 +215,34 @@ bool HotColdSplitting::isFunctionCold(const Function &F) const {
return false;
}
+bool HotColdSplitting::isBasicBlockCold(BasicBlock *BB,
+ BranchProbability ColdProbThresh,
+ SmallPtrSetImpl<BasicBlock *> &ColdBlocks,
+ SmallPtrSetImpl<BasicBlock *> &AnnotatedColdBlocks,
+ BlockFrequencyInfo *BFI) const {
+ // This block is already part of some outlining region.
+ if (ColdBlocks.count(BB))
+ return true;
+
+ if (BFI) {
+ if (PSI->isColdBlock(BB, BFI))
+ return true;
+ } else {
+ // Find cold blocks of successors of BB during a reverse postorder traversal.
+ analyzeProfMetadata(BB, ColdProbThresh, AnnotatedColdBlocks);
+
+ // A statically cold BB would be known before it is visited
+ // because the prof-data of incoming edges are 'analyzed' as part of RPOT.
+ if (AnnotatedColdBlocks.count(BB))
+ return true;
+ }
+
+ if (EnableStaticAnalysis && unlikelyExecuted(*BB))
+ return true;
+
+ return false;
+}
+
// Returns false if the function should not be considered for hot-cold split
// optimization.
bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
@@ -565,6 +625,9 @@ bool HotColdSplitting::outlineColdRegions(Function &F, bool HasProfileSummary) {
// The set of cold blocks.
SmallPtrSet<BasicBlock *, 4> ColdBlocks;
+ // Set of cold blocks obtained with RPOT.
+ SmallPtrSet<BasicBlock *, 4> AnnotatedColdBlocks;
+
// The worklist of non-intersecting regions left to outline.
SmallVector<OutliningRegion, 2> OutliningWorklist;
@@ -587,16 +650,15 @@ bool HotColdSplitting::outlineColdRegions(Function &F, bool HasProfileSummary) {
TargetTransformInfo &TTI = GetTTI(F);
OptimizationRemarkEmitter &ORE = (*GetORE)(F);
AssumptionCache *AC = LookupAC(F);
+ auto ColdProbThresh = TTI.getPredictableBranchThreshold().getCompl();
+
+ if (ColdBranchProbDenom.getNumOccurrences())
+ ColdProbThresh = BranchProbability(1, ColdBranchProbDenom.getValue());
// Find all cold regions.
for (BasicBlock *BB : RPOT) {
- // This block is already part of some outlining region.
- if (ColdBlocks.count(BB))
- continue;
-
- bool Cold = (BFI && PSI->isColdBlock(BB, BFI)) ||
- (EnableStaticAnalysis && unlikelyExecuted(*BB));
- if (!Cold)
+ if (!isBasicBlockCold(BB, ColdProbThresh, ColdBlocks, AnnotatedColdBlocks,
+ BFI))
continue;
LLVM_DEBUG({