summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
diff options
context:
space:
mode:
authorSebastian Pop <sebpop@gmail.com>2018-10-15 21:43:11 +0000
committerSebastian Pop <sebpop@gmail.com>2018-10-15 21:43:11 +0000
commit542e522b87bee4aae543da3a81259acac8790e1b (patch)
tree315e3baff49e5a145d27ceacf03af450dc8a7b3b /llvm/lib/Transforms/IPO/HotColdSplitting.cpp
parent212e23d01508e7b55f81ed7e64c02036ef22b981 (diff)
downloadbcm5719-llvm-542e522b87bee4aae543da3a81259acac8790e1b.tar.gz
bcm5719-llvm-542e522b87bee4aae543da3a81259acac8790e1b.zip
[hot-cold-split] fix static analysis of cold regions
Make the code of blockEndsInUnreachable to match the function blockEndsInUnreachable in CodeGen/BranchFolding.cpp. I also have added a note to make sure the code of this function will not be modified unless the back-end version is also modified. An early return before outlining has been added to avoid outlining the full function body when the first block in the function is marked cold. The static analysis of cold code has been amended to avoid marking the whole function as cold by back-propagation because the back-propagation would mark blocks with return statements as cold. The patch adds debug statements to help discover these problems. Differential Revision: https://reviews.llvm.org/D52904 llvm-svn: 344558
Diffstat (limited to 'llvm/lib/Transforms/IPO/HotColdSplitting.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/HotColdSplitting.cpp48
1 files changed, 41 insertions, 7 deletions
diff --git a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
index 9d2634f1bc9..fcea40dffd7 100644
--- a/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
+++ b/llvm/lib/Transforms/IPO/HotColdSplitting.cpp
@@ -101,14 +101,19 @@ static bool isSingleEntrySingleExit(BasicBlock *Entry, const BasicBlock *Exit,
return true;
}
+// Same as blockEndsInUnreachable in CodeGen/BranchFolding.cpp. Do not modify
+// this function unless you modify the MBB version as well.
+//
+/// A no successor, non-return block probably ends in unreachable and is cold.
+/// Also consider a block that ends in an indirect branch to be a return block,
+/// since many targets use plain indirect branches to return.
bool blockEndsInUnreachable(const BasicBlock &BB) {
+ if (!succ_empty(&BB))
+ return false;
if (BB.empty())
return true;
const Instruction *I = BB.getTerminator();
- if (isa<ReturnInst>(I) || isa<IndirectBrInst>(I))
- return true;
- // Unreachable blocks do not have any successor.
- return succ_empty(&BB);
+ return !(isa<ReturnInst>(I) || isa<IndirectBrInst>(I));
}
static bool exceptionHandlingFunctions(const CallInst *CI) {
@@ -123,8 +128,7 @@ static bool exceptionHandlingFunctions(const CallInst *CI) {
FName == "__cxa_end_catch";
}
-static
-bool unlikelyExecuted(const BasicBlock &BB) {
+static bool unlikelyExecuted(const BasicBlock &BB) {
if (blockEndsInUnreachable(BB))
return true;
// Exception handling blocks are unlikely executed.
@@ -145,13 +149,32 @@ bool unlikelyExecuted(const BasicBlock &BB) {
return false;
}
+static bool returnsOrHasSideEffects(const BasicBlock &BB) {
+ const TerminatorInst *I = BB.getTerminator();
+ if (isa<ReturnInst>(I) || isa<IndirectBrInst>(I) || isa<InvokeInst>(I))
+ return true;
+
+ for (const Instruction &I : BB)
+ if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
+ if (CI->hasFnAttr(Attribute::NoReturn))
+ return true;
+
+ if (isa<InlineAsm>(CI->getCalledValue()))
+ return true;
+ }
+
+ return false;
+}
+
static DenseSetBB getHotBlocks(Function &F) {
// Mark all cold basic blocks.
DenseSetBB ColdBlocks;
for (BasicBlock &BB : F)
- if (unlikelyExecuted(BB))
+ if (unlikelyExecuted(BB)) {
+ LLVM_DEBUG(llvm::dbgs() << "\nForward propagation marks cold: " << BB);
ColdBlocks.insert((const BasicBlock *)&BB);
+ }
// Forward propagation: basic blocks are hot when they are reachable from the
// beginning of the function through a path that does not contain cold blocks.
@@ -203,7 +226,12 @@ static DenseSetBB getHotBlocks(Function &F) {
if (ColdBlocks.count(It))
continue;
+ // Do not back-propagate to blocks that return or have side effects.
+ if (returnsOrHasSideEffects(*It))
+ continue;
+
// Move the block from HotBlocks to ColdBlocks.
+ LLVM_DEBUG(llvm::dbgs() << "\nBack propagation marks cold: " << *It);
HotBlocks.erase(It);
ColdBlocks.insert(It);
@@ -353,6 +381,12 @@ const Function *HotColdSplitting::outlineColdBlocks(Function &F,
// Walking the dominator tree allows us to find the largest
// cold region.
BasicBlock *Begin = DT->getRootNode()->getBlock();
+
+ // Early return if the beginning of the function has been marked cold,
+ // otherwise all the function gets outlined.
+ if (PSI->isColdBB(Begin, BFI) || !HotBlocks.count(Begin))
+ return nullptr;
+
for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) {
BasicBlock *BB = *I;
if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) {
OpenPOWER on IntegriCloud