llvm.org GIT mirror llvm / e2d6b27
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344558 91177308-0d34-0410-b5e6-96231b3b80d8 Sebastian Pop 1 year, 1 month ago
3 changed file(s) with 66 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
100100 return true;
101101 }
102102
103 // Same as blockEndsInUnreachable in CodeGen/BranchFolding.cpp. Do not modify
104 // this function unless you modify the MBB version as well.
105 //
106 /// A no successor, non-return block probably ends in unreachable and is cold.
107 /// Also consider a block that ends in an indirect branch to be a return block,
108 /// since many targets use plain indirect branches to return.
103109 bool blockEndsInUnreachable(const BasicBlock &BB) {
110 if (!succ_empty(&BB))
111 return false;
104112 if (BB.empty())
105113 return true;
106114 const Instruction *I = BB.getTerminator();
107 if (isa(I) || isa(I))
108 return true;
109 // Unreachable blocks do not have any successor.
110 return succ_empty(&BB);
115 return !(isa(I) || isa(I));
111116 }
112117
113118 static bool exceptionHandlingFunctions(const CallInst *CI) {
122127 FName == "__cxa_end_catch";
123128 }
124129
125 static
126 bool unlikelyExecuted(const BasicBlock &BB) {
130 static bool unlikelyExecuted(const BasicBlock &BB) {
127131 if (blockEndsInUnreachable(BB))
128132 return true;
129133 // Exception handling blocks are unlikely executed.
144148 return false;
145149 }
146150
151 static bool returnsOrHasSideEffects(const BasicBlock &BB) {
152 const TerminatorInst *I = BB.getTerminator();
153 if (isa(I) || isa(I) || isa(I))
154 return true;
155
156 for (const Instruction &I : BB)
157 if (const CallInst *CI = dyn_cast(&I)) {
158 if (CI->hasFnAttr(Attribute::NoReturn))
159 return true;
160
161 if (isa(CI->getCalledValue()))
162 return true;
163 }
164
165 return false;
166 }
167
147168 static DenseSetBB getHotBlocks(Function &F) {
148169
149170 // Mark all cold basic blocks.
150171 DenseSetBB ColdBlocks;
151172 for (BasicBlock &BB : F)
152 if (unlikelyExecuted(BB))
173 if (unlikelyExecuted(BB)) {
174 LLVM_DEBUG(llvm::dbgs() << "\nForward propagation marks cold: " << BB);
153175 ColdBlocks.insert((const BasicBlock *)&BB);
176 }
154177
155178 // Forward propagation: basic blocks are hot when they are reachable from the
156179 // beginning of the function through a path that does not contain cold blocks.
202225 if (ColdBlocks.count(It))
203226 continue;
204227
228 // Do not back-propagate to blocks that return or have side effects.
229 if (returnsOrHasSideEffects(*It))
230 continue;
231
205232 // Move the block from HotBlocks to ColdBlocks.
233 LLVM_DEBUG(llvm::dbgs() << "\nBack propagation marks cold: " << *It);
206234 HotBlocks.erase(It);
207235 ColdBlocks.insert(It);
208236
352380 // Walking the dominator tree allows us to find the largest
353381 // cold region.
354382 BasicBlock *Begin = DT->getRootNode()->getBlock();
383
384 // Early return if the beginning of the function has been marked cold,
385 // otherwise all the function gets outlined.
386 if (PSI->isColdBB(Begin, BFI) || !HotBlocks.count(Begin))
387 return nullptr;
388
355389 for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) {
356390 BasicBlock *BB = *I;
357391 if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) {
0 ; RUN: opt -hotcoldsplit -S < %s | FileCheck %s
11 ; RUN: opt -passes=hotcoldsplit -S < %s | FileCheck %s
22
3 ; Outlined function is called from a basic block named codeRepl
4 ; CHECK: codeRepl:
5 ; CHECK-NEXT: call void @foo
3 ; Check that the function is not split. Outlined function is called from a
4 ; basic block named codeRepl.
5
6 ; CHECK-LABEL: @foo
7 ; CHECK-NOT: codeRepl
68 define void @foo() {
79 entry:
810 br i1 undef, label %if.then, label %if.end
2224 return: ; preds = %cleanup40
2325 ret void
2426 }
27
28 ; Check that the function is not split. We used to outline the full function.
29
30 ; CHECK-LABEL: @fun
31 ; CHECK-NOT: codeRepl
32
33 define void @fun() {
34 entry:
35 br i1 undef, label %if.then, label %if.end
36
37 if.then: ; preds = %entry
38 br label %if.end
39
40 if.end: ; preds = %entry
41 ret void
42 }
22
33 ; Make sure this compiles. This test used to fail with an invalid phi node: the
44 ; two predecessors were outlined and the SSA representation was invalid.
5
6 ; CHECK-LABEL: @fun
7 ; CHECK: codeRepl:
8 ; CHECK-NEXT: call void @fun_if.else
59
610 define void @fun() {
711 entry: