diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -165,7 +165,7 @@ void initializeFinalizeMachineBundlesPass(PassRegistry&); void initializeFixIrreduciblePass(PassRegistry &); void initializeFixupStatepointCallerSavedPass(PassRegistry&); -void initializeFlattenCFGPassPass(PassRegistry&); +void initializeFlattenCFGLegacyPassPass(PassRegistry &); void initializeFloat2IntLegacyPassPass(PassRegistry&); void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&); void initializeForwardControlFlowIntegrityPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Scalar/FlattenCFG.h b/llvm/include/llvm/Transforms/Scalar/FlattenCFG.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Transforms/Scalar/FlattenCFG.h @@ -0,0 +1,25 @@ +//===- FlattenCFG.h -------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The FlattenCFG pass flattens a function's CFG using the FlattenCFG utility +// function, iteratively flattening until no further changes are made. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_FLATTENCFG_H +#define LLVM_TRANSFORMS_SCALAR_FLATTENCFG_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { +struct FlattenCFGPass : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; +} // namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_FLATTENCFG_H diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -152,6 +152,7 @@ #include "llvm/Transforms/Scalar/DeadStoreElimination.h" #include "llvm/Transforms/Scalar/DivRemPairs.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" +#include "llvm/Transforms/Scalar/FlattenCFG.h" #include "llvm/Transforms/Scalar/Float2Int.h" #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/GuardWidening.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -254,6 +254,7 @@ FUNCTION_PASS("dot-cfg", CFGPrinterPass()) FUNCTION_PASS("dot-cfg-only", CFGOnlyPrinterPass()) FUNCTION_PASS("fix-irreducible", FixIrreduciblePass()) +FUNCTION_PASS("flattencfg", FlattenCFGPass()) FUNCTION_PASS("make-guards-explicit", MakeGuardsExplicitPass()) FUNCTION_PASS("gvn-hoist", GVNHoistPass()) FUNCTION_PASS("gvn-sink", GVNSinkPass()) diff --git a/llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp b/llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp --- a/llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/FlattenCFGPass.cpp @@ -13,10 +13,12 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/CFG.h" #include "llvm/IR/InstrTypes.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/ValueHandle.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Scalar/FlattenCFG.h" #include "llvm/Transforms/Utils/Local.h" using namespace llvm; @@ -24,11 +26,11 @@ #define DEBUG_TYPE "flattencfg" namespace { -struct FlattenCFGPass : public FunctionPass { +struct FlattenCFGLegacyPass : public FunctionPass { static char ID; // Pass identification, replacement for typeid public: - FlattenCFGPass() : FunctionPass(ID) { - initializeFlattenCFGPassPass(*PassRegistry::getPassRegistry()); + FlattenCFGLegacyPass() : FunctionPass(ID) { + initializeFlattenCFGLegacyPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override; @@ -39,21 +41,10 @@ private: AliasAnalysis *AA; }; -} - -char FlattenCFGPass::ID = 0; -INITIALIZE_PASS_BEGIN(FlattenCFGPass, "flattencfg", "Flatten the CFG", false, - false) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(FlattenCFGPass, "flattencfg", "Flatten the CFG", false, - false) - -// Public interface to the FlattenCFG pass -FunctionPass *llvm::createFlattenCFGPass() { return new FlattenCFGPass(); } /// iterativelyFlattenCFG - Call FlattenCFG on all the blocks in the function, /// iterating until no more changes are made. -static bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) { +bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) { bool Changed = false; bool LocalChange = true; @@ -78,8 +69,22 @@ } return Changed; } +} // namespace -bool FlattenCFGPass::runOnFunction(Function &F) { +char FlattenCFGLegacyPass::ID = 0; + +INITIALIZE_PASS_BEGIN(FlattenCFGLegacyPass, "flattencfg", "Flatten the CFG", + false, false) +INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) +INITIALIZE_PASS_END(FlattenCFGLegacyPass, "flattencfg", "Flatten the CFG", + false, false) + +// Public interface to the FlattenCFG pass +FunctionPass *llvm::createFlattenCFGPass() { + return new FlattenCFGLegacyPass(); +} + +bool FlattenCFGLegacyPass::runOnFunction(Function &F) { AA = &getAnalysis().getAAResults(); bool EverChanged = false; // iterativelyFlattenCFG can make some blocks dead. @@ -89,3 +94,15 @@ } return EverChanged; } + +PreservedAnalyses FlattenCFGPass::run(Function &F, + FunctionAnalysisManager &AM) { + bool EverChanged = false; + AliasAnalysis *AA = &AM.getResult(F); + // iterativelyFlattenCFG can make some blocks dead. + while (iterativelyFlattenCFG(F, AA)) { + removeUnreachableBlocks(F); + EverChanged = true; + } + return EverChanged ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} diff --git a/llvm/lib/Transforms/Scalar/Scalar.cpp b/llvm/lib/Transforms/Scalar/Scalar.cpp --- a/llvm/lib/Transforms/Scalar/Scalar.cpp +++ b/llvm/lib/Transforms/Scalar/Scalar.cpp @@ -54,7 +54,7 @@ initializeMakeGuardsExplicitLegacyPassPass(Registry); initializeGVNHoistLegacyPassPass(Registry); initializeGVNSinkLegacyPassPass(Registry); - initializeFlattenCFGPassPass(Registry); + initializeFlattenCFGLegacyPassPass(Registry); initializeIRCELegacyPassPass(Registry); initializeIndVarSimplifyLegacyPassPass(Registry); initializeInferAddressSpacesPass(Registry); diff --git a/llvm/test/Transforms/Util/flattencfg.ll b/llvm/test/Transforms/Util/flattencfg.ll --- a/llvm/test/Transforms/Util/flattencfg.ll +++ b/llvm/test/Transforms/Util/flattencfg.ll @@ -1,4 +1,5 @@ ; RUN: opt -flattencfg -S < %s -enable-new-pm=0 | FileCheck %s +; RUN: opt -passes=flattencfg -S < %s | FileCheck %s ; This test checks whether the pass completes without a crash.