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 @@ -428,7 +428,7 @@ void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAAWrapperPassPass(PassRegistry&); void initializeTypePromotionPass(PassRegistry&); -void initializeUnifyFunctionExitNodesPass(PassRegistry&); +void initializeUnifyFunctionExitNodesLegacyPassPass(PassRegistry &); void initializeUnifyLoopExitsPass(PassRegistry &); void initializeUnpackMachineBundlesPass(PassRegistry&); void initializeUnreachableBlockElimLegacyPassPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h --- a/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h +++ b/llvm/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -14,19 +14,17 @@ #ifndef LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H #define LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_H +#include "llvm/IR/PassManager.h" #include "llvm/Pass.h" namespace llvm { class BasicBlock; -class UnifyFunctionExitNodes : public FunctionPass { - bool unifyUnreachableBlocks(Function &F); - bool unifyReturnBlocks(Function &F); - +class UnifyFunctionExitNodesLegacyPass : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid - UnifyFunctionExitNodes(); + UnifyFunctionExitNodesLegacyPass(); // We can preserve non-critical-edgeness when we unify function exit nodes void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -36,6 +34,12 @@ Pass *createUnifyFunctionExitNodesPass(); +class UnifyFunctionExitNodesPass + : public PassInfoMixin { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + } // end namespace llvm #endif // LLVM_TRANSFORMS_UTILS_UNIFYFUNCTIONEXITNODES_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 @@ -212,6 +212,7 @@ #include "llvm/Transforms/Utils/StripGCRelocates.h" #include "llvm/Transforms/Utils/StripNonLineTableDebugInfo.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize/LoadStoreVectorizer.h" #include "llvm/Transforms/Vectorize/LoopVectorize.h" #include "llvm/Transforms/Vectorize/SLPVectorizer.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 @@ -240,6 +240,7 @@ FUNCTION_PASS("mem2reg", PromotePass()) FUNCTION_PASS("memcpyopt", MemCpyOptPass()) FUNCTION_PASS("mergeicmps", MergeICmpsPass()) +FUNCTION_PASS("mergereturn", UnifyFunctionExitNodesPass()) FUNCTION_PASS("nary-reassociate", NaryReassociatePass()) FUNCTION_PASS("newgvn", NewGVNPass()) FUNCTION_PASS("jump-threading", JumpThreadingPass()) diff --git a/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp b/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp --- a/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp +++ b/llvm/lib/Transforms/Utils/UnifyFunctionExitNodes.cpp @@ -20,28 +20,33 @@ #include "llvm/Transforms/Utils.h" using namespace llvm; -char UnifyFunctionExitNodes::ID = 0; +char UnifyFunctionExitNodesLegacyPass::ID = 0; -UnifyFunctionExitNodes::UnifyFunctionExitNodes() : FunctionPass(ID) { - initializeUnifyFunctionExitNodesPass(*PassRegistry::getPassRegistry()); +UnifyFunctionExitNodesLegacyPass::UnifyFunctionExitNodesLegacyPass() + : FunctionPass(ID) { + initializeUnifyFunctionExitNodesLegacyPassPass( + *PassRegistry::getPassRegistry()); } -INITIALIZE_PASS(UnifyFunctionExitNodes, "mergereturn", +INITIALIZE_PASS(UnifyFunctionExitNodesLegacyPass, "mergereturn", "Unify function exit nodes", false, false) Pass *llvm::createUnifyFunctionExitNodesPass() { - return new UnifyFunctionExitNodes(); + return new UnifyFunctionExitNodesLegacyPass(); } -void UnifyFunctionExitNodes::getAnalysisUsage(AnalysisUsage &AU) const{ +void UnifyFunctionExitNodesLegacyPass::getAnalysisUsage( + AnalysisUsage &AU) const { // We preserve the non-critical-edgeness property AU.addPreservedID(BreakCriticalEdgesID); // This is a cluster of orthogonal Transforms AU.addPreservedID(LowerSwitchID); } -bool UnifyFunctionExitNodes::unifyUnreachableBlocks(Function &F) { - std::vector UnreachableBlocks; +namespace { + +bool unifyUnreachableBlocks(Function &F) { + std::vector UnreachableBlocks; for (BasicBlock &I : F) if (isa(I.getTerminator())) @@ -62,7 +67,7 @@ return true; } -bool UnifyFunctionExitNodes::unifyReturnBlocks(Function &F) { +bool unifyReturnBlocks(Function &F) { std::vector ReturningBlocks; for (BasicBlock &I : F) @@ -103,13 +108,22 @@ return true; } +} // namespace // Unify all exit nodes of the CFG by creating a new BasicBlock, and converting // all returns to unconditional branches to this new basic block. Also, unify // all unreachable blocks. -bool UnifyFunctionExitNodes::runOnFunction(Function &F) { +bool UnifyFunctionExitNodesLegacyPass::runOnFunction(Function &F) { bool Changed = false; Changed |= unifyUnreachableBlocks(F); Changed |= unifyReturnBlocks(F); return Changed; } + +PreservedAnalyses UnifyFunctionExitNodesPass::run(Function &F, + FunctionAnalysisManager &AM) { + bool Changed = false; + Changed |= unifyUnreachableBlocks(F); + Changed |= unifyReturnBlocks(F); + return Changed ? PreservedAnalyses() : PreservedAnalyses::all(); +} diff --git a/llvm/lib/Transforms/Utils/Utils.cpp b/llvm/lib/Transforms/Utils/Utils.cpp --- a/llvm/lib/Transforms/Utils/Utils.cpp +++ b/llvm/lib/Transforms/Utils/Utils.cpp @@ -38,7 +38,7 @@ initializeNameAnonGlobalLegacyPassPass(Registry); initializePromoteLegacyPassPass(Registry); initializeStripNonLineTableDebugLegacyPassPass(Registry); - initializeUnifyFunctionExitNodesPass(Registry); + initializeUnifyFunctionExitNodesLegacyPassPass(Registry); initializeMetaRenamerPass(Registry); initializeStripGCRelocatesLegacyPass(Registry); initializePredicateInfoPrinterLegacyPassPass(Registry); diff --git a/llvm/test/Transforms/UnifyFunctionExitNodes/unreachable-blocks-status.ll b/llvm/test/Transforms/UnifyFunctionExitNodes/unreachable-blocks-status.ll --- a/llvm/test/Transforms/UnifyFunctionExitNodes/unreachable-blocks-status.ll +++ b/llvm/test/Transforms/UnifyFunctionExitNodes/unreachable-blocks-status.ll @@ -1,4 +1,5 @@ ; RUN: opt -mergereturn -enable-new-pm=0 -S < %s | FileCheck %s +; RUN: opt -passes='break-crit-edges,lowerswitch,mergereturn' -S < %s | FileCheck %s ; The pass did previously not report the correct Modified status in the case ; where a function had at most one return block, and an unified unreachable