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