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
24*0fca6ea1SDimitry Andric #define DEBUG_TYPE "flatten-cfg"
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__anon8bd4eb880111::FlattenCFGLegacyPass300eae32dcSDimitry Andric FlattenCFGLegacyPass() : FunctionPass(ID) {
310eae32dcSDimitry Andric initializeFlattenCFGLegacyPassPass(*PassRegistry::getPassRegistry());
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric bool runOnFunction(Function &F) override;
340b57cec5SDimitry Andric
getAnalysisUsage__anon8bd4eb880111::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