10b57cec5SDimitry Andric //===- FlattenCFGPass.cpp - CFG Flatten Pass ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements flattening of CFG.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
140eae32dcSDimitry Andric #include "llvm/IR/PassManager.h"
158bcb0991SDimitry Andric #include "llvm/IR/ValueHandle.h"
16480093f4SDimitry Andric #include "llvm/InitializePasses.h"
170b57cec5SDimitry Andric #include "llvm/Pass.h"
180b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h"
190eae32dcSDimitry Andric #include "llvm/Transforms/Scalar/FlattenCFG.h"
208bcb0991SDimitry Andric #include "llvm/Transforms/Utils/Local.h"
218bcb0991SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #define DEBUG_TYPE "flattencfg"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric namespace {
270eae32dcSDimitry Andric struct FlattenCFGLegacyPass : public FunctionPass {
280b57cec5SDimitry Andric   static char ID; // Pass identification, replacement for typeid
290b57cec5SDimitry Andric public:
FlattenCFGLegacyPass__anonb51340500111::FlattenCFGLegacyPass300eae32dcSDimitry Andric   FlattenCFGLegacyPass() : FunctionPass(ID) {
310eae32dcSDimitry Andric     initializeFlattenCFGLegacyPassPass(*PassRegistry::getPassRegistry());
320b57cec5SDimitry Andric   }
330b57cec5SDimitry Andric   bool runOnFunction(Function &F) override;
340b57cec5SDimitry Andric 
getAnalysisUsage__anonb51340500111::FlattenCFGLegacyPass350b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
360b57cec5SDimitry Andric     AU.addRequired<AAResultsWrapperPass>();
370b57cec5SDimitry Andric   }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric private:
400b57cec5SDimitry Andric   AliasAnalysis *AA;
410b57cec5SDimitry Andric };
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// iterativelyFlattenCFG - Call FlattenCFG on all the blocks in the function,
440b57cec5SDimitry Andric /// iterating until no more changes are made.
iterativelyFlattenCFG(Function & F,AliasAnalysis * AA)450eae32dcSDimitry Andric bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) {
460b57cec5SDimitry Andric   bool Changed = false;
470b57cec5SDimitry Andric   bool LocalChange = true;
488bcb0991SDimitry Andric 
498bcb0991SDimitry Andric   // Use block handles instead of iterating over function blocks directly
508bcb0991SDimitry Andric   // to avoid using iterators invalidated by erasing blocks.
518bcb0991SDimitry Andric   std::vector<WeakVH> Blocks;
528bcb0991SDimitry Andric   Blocks.reserve(F.size());
538bcb0991SDimitry Andric   for (auto &BB : F)
548bcb0991SDimitry Andric     Blocks.push_back(&BB);
558bcb0991SDimitry Andric 
560b57cec5SDimitry Andric   while (LocalChange) {
570b57cec5SDimitry Andric     LocalChange = false;
580b57cec5SDimitry Andric 
598bcb0991SDimitry Andric     // Loop over all of the basic blocks and try to flatten them.
608bcb0991SDimitry Andric     for (WeakVH &BlockHandle : Blocks) {
618bcb0991SDimitry Andric       // Skip blocks erased by FlattenCFG.
628bcb0991SDimitry Andric       if (auto *BB = cast_or_null<BasicBlock>(BlockHandle))
638bcb0991SDimitry Andric         if (FlattenCFG(BB, AA))
640b57cec5SDimitry Andric           LocalChange = true;
650b57cec5SDimitry Andric     }
660b57cec5SDimitry Andric     Changed |= LocalChange;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric   return Changed;
690b57cec5SDimitry Andric }
700eae32dcSDimitry Andric } // namespace
710b57cec5SDimitry Andric 
720eae32dcSDimitry Andric char FlattenCFGLegacyPass::ID = 0;
730eae32dcSDimitry Andric 
740eae32dcSDimitry Andric INITIALIZE_PASS_BEGIN(FlattenCFGLegacyPass, "flattencfg", "Flatten the CFG",
750eae32dcSDimitry Andric                       false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)760eae32dcSDimitry Andric INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
770eae32dcSDimitry Andric INITIALIZE_PASS_END(FlattenCFGLegacyPass, "flattencfg", "Flatten the CFG",
780eae32dcSDimitry Andric                     false, false)
790eae32dcSDimitry Andric 
800eae32dcSDimitry Andric // Public interface to the FlattenCFG pass
810eae32dcSDimitry Andric FunctionPass *llvm::createFlattenCFGPass() {
820eae32dcSDimitry Andric   return new FlattenCFGLegacyPass();
830eae32dcSDimitry Andric }
840eae32dcSDimitry Andric 
runOnFunction(Function & F)850eae32dcSDimitry Andric bool FlattenCFGLegacyPass::runOnFunction(Function &F) {
860b57cec5SDimitry Andric   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
870b57cec5SDimitry Andric   bool EverChanged = false;
880b57cec5SDimitry Andric   // iterativelyFlattenCFG can make some blocks dead.
890b57cec5SDimitry Andric   while (iterativelyFlattenCFG(F, AA)) {
900b57cec5SDimitry Andric     removeUnreachableBlocks(F);
910b57cec5SDimitry Andric     EverChanged = true;
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric   return EverChanged;
940b57cec5SDimitry Andric }
950eae32dcSDimitry Andric 
run(Function & F,FunctionAnalysisManager & AM)960eae32dcSDimitry Andric PreservedAnalyses FlattenCFGPass::run(Function &F,
970eae32dcSDimitry Andric                                       FunctionAnalysisManager &AM) {
980eae32dcSDimitry Andric   bool EverChanged = false;
990eae32dcSDimitry Andric   AliasAnalysis *AA = &AM.getResult<AAManager>(F);
1000eae32dcSDimitry Andric   // iterativelyFlattenCFG can make some blocks dead.
1010eae32dcSDimitry Andric   while (iterativelyFlattenCFG(F, AA)) {
1020eae32dcSDimitry Andric     removeUnreachableBlocks(F);
1030eae32dcSDimitry Andric     EverChanged = true;
1040eae32dcSDimitry Andric   }
1050eae32dcSDimitry Andric   return EverChanged ? PreservedAnalyses::none() : PreservedAnalyses::all();
1060eae32dcSDimitry Andric }
107