107 lines · cpp
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-exception6//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 22using namespace llvm;23 24#define DEBUG_TYPE "flatten-cfg"25 26namespace {27struct FlattenCFGLegacyPass : public FunctionPass {28 static char ID; // Pass identification, replacement for typeid29public: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 39private:40 AliasAnalysis *AA;41};42} // namespace43 44/// iterativelyFlattenCFG - Call FlattenCFG on all the blocks in the function,45/// iterating until no more changes are made.46static bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) {47 bool Changed = false;48 bool LocalChange = true;49 50 // Use block handles instead of iterating over function blocks directly51 // to avoid using iterators invalidated by erasing blocks.52 std::vector<WeakVH> Blocks;53 Blocks.reserve(F.size());54 for (auto &BB : F)55 Blocks.push_back(&BB);56 57 while (LocalChange) {58 LocalChange = false;59 60 // Loop over all of the basic blocks and try to flatten them.61 for (WeakVH &BlockHandle : Blocks) {62 // Skip blocks erased by FlattenCFG.63 if (auto *BB = cast_or_null<BasicBlock>(BlockHandle))64 if (FlattenCFG(BB, AA))65 LocalChange = true;66 }67 Changed |= LocalChange;68 }69 return Changed;70}71 72char FlattenCFGLegacyPass::ID = 0;73 74INITIALIZE_PASS_BEGIN(FlattenCFGLegacyPass, "flattencfg", "Flatten the CFG",75 false, false)76INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)77INITIALIZE_PASS_END(FlattenCFGLegacyPass, "flattencfg", "Flatten the CFG",78 false, false)79 80// Public interface to the FlattenCFG pass81FunctionPass *llvm::createFlattenCFGPass() {82 return new FlattenCFGLegacyPass();83}84 85bool 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 96PreservedAnalyses FlattenCFGPass::run(Function &F,97 FunctionAnalysisManager &AM) {98 bool EverChanged = false;99 AliasAnalysis *AA = &AM.getResult<AAManager>(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