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