Index: llvm/lib/Transforms/IPO/HotColdSplitting.cpp =================================================================== --- llvm/lib/Transforms/IPO/HotColdSplitting.cpp +++ llvm/lib/Transforms/IPO/HotColdSplitting.cpp @@ -261,8 +261,8 @@ private: bool shouldOutlineFrom(const Function &F) const; - const Function *outlineColdBlocks(Function &F, const DenseSetBB &ColdBlock, - DominatorTree *DT, PostDomTree *PDT); + void outlineColdBlocks(Function &F, const DenseSetBB &ColdBlock, + DominatorTree *DT, PostDomTree *PDT); Function *extractColdRegion(const SmallVectorImpl &Region, DominatorTree *DT, BlockFrequencyInfo *BFI, OptimizationRemarkEmitter &ORE); @@ -380,10 +380,9 @@ } // Return the function created after outlining, nullptr otherwise. -const Function *HotColdSplitting::outlineColdBlocks(Function &F, - const DenseSetBB &HotBlocks, - DominatorTree *DT, - PostDomTree *PDT) { +void HotColdSplitting::outlineColdBlocks(Function &F, + const DenseSetBB &HotBlocks, + DominatorTree *DT, PostDomTree *PDT) { auto BFI = GetBFI(F); auto &ORE = (*GetORE)(F); // Walking the dominator tree allows us to find the largest @@ -393,10 +392,16 @@ // 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; + return; + DenseSetBB OutlinedBBs; for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) { BasicBlock *BB = *I; + + // Skip over outlined blocks. + if (OutlinedBBs.count(BB)) + continue; + if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) { SmallVector ValidColdRegion, Region; BasicBlock *Exit = (*PDT)[BB]->getIDom()->getBlock(); @@ -411,6 +416,7 @@ // Update Exit recursively to its dom-frontier. Exit = (*PDT)[Exit]->getIDom()->getBlock(); } + if (ExitColdRegion) { // Do not outline a region with only one block. if (ValidColdRegion.size() == 1) @@ -418,12 +424,16 @@ ++NumColdSESEFound; ValidColdRegion.push_back(ExitColdRegion); - // Candidate for outlining. FIXME: Continue outlining. - return extractColdRegion(ValidColdRegion, DT, BFI, ORE); + + if (const Function *Outlined = + extractColdRegion(ValidColdRegion, DT, BFI, ORE)) { + OutlinedFunctions.insert(Outlined); + for (BasicBlock *I : ValidColdRegion) + OutlinedBBs.insert(I); + } } } } - return nullptr; } bool HotColdSplitting::run(Module &M) { @@ -437,9 +447,7 @@ if (EnableStaticAnalyis) // Static analysis of cold blocks. HotBlocks = getHotBlocks(F); - const Function *Outlined = outlineColdBlocks(F, HotBlocks, &DT, &PDT); - if (Outlined) - OutlinedFunctions.insert(Outlined); + outlineColdBlocks(F, HotBlocks, &DT, &PDT); } return true; } Index: llvm/test/Transforms/HotColdSplit/split-cold-3.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/HotColdSplit/split-cold-3.ll @@ -0,0 +1,50 @@ +; RUN: opt -hotcoldsplit -pass-remarks=hotcoldsplit < %s 2>&1 | FileCheck %s +; RUN: opt -passes=hotcoldsplit -pass-remarks=hotcoldsplit < %s 2>&1 | FileCheck %s + +; CHECK: remark: :0:0: fun split cold code into fun_B.else +; CHECK: remark: :0:0: fun split cold code into fun_A.else + +define void @fun() { +entry: + br i1 undef, label %A.then, label %A.else + +A.else: + br label %A.then4 + +A.then4: + br i1 undef, label %A.then5, label %A.end + +A.then5: + br label %A.cleanup + +A.end: + br label %A.cleanup + +A.cleanup: + %A.cleanup.dest.slot.0 = phi i32 [ 1, %A.then5 ], [ 0, %A.end ] + unreachable + +A.then: + br i1 undef, label %B.then, label %B.else + +B.then: + ret void + +B.else: + br label %B.then4 + +B.then4: + br i1 undef, label %B.then5, label %B.end + +B.then5: + br label %B.cleanup + +B.end: + br label %B.cleanup + +B.cleanup: + %B.cleanup.dest.slot.0 = phi i32 [ 1, %B.then5 ], [ 0, %B.end ] + unreachable + + +}