1 | //===- FlattenCFGPass.cpp - CFG Flatten Pass ----------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements flattening of CFG. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/Analysis/AliasAnalysis.h" |
14 | #include "llvm/IR/PassManager.h" |
15 | #include "llvm/IR/ValueHandle.h" |
16 | #include "llvm/InitializePasses.h" |
17 | #include "llvm/Pass.h" |
18 | #include "llvm/Transforms/Scalar.h" |
19 | #include "llvm/Transforms/Scalar/FlattenCFG.h" |
20 | #include "llvm/Transforms/Utils/Local.h" |
21 | |
22 | using namespace llvm; |
23 | |
24 | #define DEBUG_TYPE "flatten-cfg" |
25 | |
26 | namespace { |
27 | struct FlattenCFGLegacyPass : public FunctionPass { |
28 | static char ID; // Pass identification, replacement for typeid |
29 | public: |
30 | FlattenCFGLegacyPass() : FunctionPass(ID) { |
31 | initializeFlattenCFGLegacyPassPass(*PassRegistry::getPassRegistry()); |
32 | } |
33 | bool runOnFunction(Function &F) override; |
34 | |
35 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
36 | AU.addRequired<AAResultsWrapperPass>(); |
37 | } |
38 | |
39 | private: |
40 | AliasAnalysis *AA; |
41 | }; |
42 | |
43 | /// iterativelyFlattenCFG - Call FlattenCFG on all the blocks in the function, |
44 | /// iterating until no more changes are made. |
45 | bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) { |
46 | bool Changed = false; |
47 | bool LocalChange = true; |
48 | |
49 | // Use block handles instead of iterating over function blocks directly |
50 | // to avoid using iterators invalidated by erasing blocks. |
51 | std::vector<WeakVH> Blocks; |
52 | Blocks.reserve(n: F.size()); |
53 | for (auto &BB : F) |
54 | Blocks.push_back(x: &BB); |
55 | |
56 | while (LocalChange) { |
57 | LocalChange = false; |
58 | |
59 | // Loop over all of the basic blocks and try to flatten them. |
60 | for (WeakVH &BlockHandle : Blocks) { |
61 | // Skip blocks erased by FlattenCFG. |
62 | if (auto *BB = cast_or_null<BasicBlock>(Val&: BlockHandle)) |
63 | if (FlattenCFG(BB, AA)) |
64 | LocalChange = true; |
65 | } |
66 | Changed |= LocalChange; |
67 | } |
68 | return Changed; |
69 | } |
70 | } // namespace |
71 | |
72 | char FlattenCFGLegacyPass::ID = 0; |
73 | |
74 | INITIALIZE_PASS_BEGIN(FlattenCFGLegacyPass, "flattencfg" , "Flatten the CFG" , |
75 | false, false) |
76 | INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) |
77 | INITIALIZE_PASS_END(FlattenCFGLegacyPass, "flattencfg" , "Flatten the CFG" , |
78 | false, false) |
79 | |
80 | // Public interface to the FlattenCFG pass |
81 | FunctionPass *llvm::createFlattenCFGPass() { |
82 | return new FlattenCFGLegacyPass(); |
83 | } |
84 | |
85 | bool FlattenCFGLegacyPass::runOnFunction(Function &F) { |
86 | AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); |
87 | bool EverChanged = false; |
88 | // iterativelyFlattenCFG can make some blocks dead. |
89 | while (iterativelyFlattenCFG(F, AA)) { |
90 | removeUnreachableBlocks(F); |
91 | EverChanged = true; |
92 | } |
93 | return EverChanged; |
94 | } |
95 | |
96 | PreservedAnalyses FlattenCFGPass::run(Function &F, |
97 | FunctionAnalysisManager &AM) { |
98 | bool EverChanged = false; |
99 | AliasAnalysis *AA = &AM.getResult<AAManager>(IR&: F); |
100 | // iterativelyFlattenCFG can make some blocks dead. |
101 | while (iterativelyFlattenCFG(F, AA)) { |
102 | removeUnreachableBlocks(F); |
103 | EverChanged = true; |
104 | } |
105 | return EverChanged ? PreservedAnalyses::none() : PreservedAnalyses::all(); |
106 | } |
107 | |