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 @@ -365,7 +365,7 @@ void initializeRedundantDbgInstEliminationPass(PassRegistry&); void initializeRegAllocFastPass(PassRegistry&); void initializeRegBankSelectPass(PassRegistry&); -void initializeRegToMemPass(PassRegistry&); +void initializeRegToMemLegacyPass(PassRegistry&); void initializeRegUsageInfoCollectorPass(PassRegistry&); void initializeRegUsageInfoPropagationPass(PassRegistry&); void initializeRegionInfoPassPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Scalar/Reg2Mem.h b/llvm/include/llvm/Transforms/Scalar/Reg2Mem.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Transforms/Scalar/Reg2Mem.h @@ -0,0 +1,27 @@ +//===- Reg2Mem.h - Convert registers to allocas -----------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file provides the interface for the RegToMem Pass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_REG2MEM_H +#define LLVM_TRANSFORMS_SCALAR_REG2MEM_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class RegToMemPass : public PassInfoMixin { +public: + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_SCALAR_REG2MEM_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 @@ -184,6 +184,7 @@ #include "llvm/Transforms/Scalar/NewGVN.h" #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h" #include "llvm/Transforms/Scalar/Reassociate.h" +#include "llvm/Transforms/Scalar/Reg2Mem.h" #include "llvm/Transforms/Scalar/RewriteStatepointsForGC.h" #include "llvm/Transforms/Scalar/SCCP.h" #include "llvm/Transforms/Scalar/SROA.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 @@ -282,6 +282,7 @@ FUNCTION_PASS("print-predicateinfo", PredicateInfoPrinterPass(dbgs())) FUNCTION_PASS("print-mustexecute", MustExecutePrinterPass(dbgs())) FUNCTION_PASS("reassociate", ReassociatePass()) +FUNCTION_PASS("reg2mem", RegToMemPass()) FUNCTION_PASS("scalarizer", ScalarizerPass()) FUNCTION_PASS("sccp", SCCPPass()) FUNCTION_PASS("simplifycfg", SimplifyCFGPass()) diff --git a/llvm/lib/Transforms/Scalar/Reg2Mem.cpp b/llvm/lib/Transforms/Scalar/Reg2Mem.cpp --- a/llvm/lib/Transforms/Scalar/Reg2Mem.cpp +++ b/llvm/lib/Transforms/Scalar/Reg2Mem.cpp @@ -15,18 +15,23 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Scalar/Reg2Mem.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include using namespace llvm; @@ -36,43 +41,17 @@ STATISTIC(NumRegsDemoted, "Number of registers demoted"); STATISTIC(NumPhisDemoted, "Number of phi-nodes demoted"); -namespace { - struct RegToMem : public FunctionPass { - static char ID; // Pass identification, replacement for typeid - RegToMem() : FunctionPass(ID) { - initializeRegToMemPass(*PassRegistry::getPassRegistry()); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequiredID(BreakCriticalEdgesID); - AU.addPreservedID(BreakCriticalEdgesID); - } - - bool valueEscapes(const Instruction &Inst) const { - const BasicBlock *BB = Inst.getParent(); - for (const User *U : Inst.users()) { - const Instruction *UI = cast(U); - if (UI->getParent() != BB || isa(UI)) - return true; - } - return false; - } - - bool runOnFunction(Function &F) override; - }; +static bool valueEscapes(const Instruction &Inst) { + const BasicBlock *BB = Inst.getParent(); + for (const User *U : Inst.users()) { + const Instruction *UI = cast(U); + if (UI->getParent() != BB || isa(UI)) + return true; + } + return false; } -char RegToMem::ID = 0; -INITIALIZE_PASS_BEGIN(RegToMem, "reg2mem", "Demote all values to stack slots", - false, false) -INITIALIZE_PASS_DEPENDENCY(BreakCriticalEdges) -INITIALIZE_PASS_END(RegToMem, "reg2mem", "Demote all values to stack slots", - false, false) - -bool RegToMem::runOnFunction(Function &F) { - if (F.isDeclaration() || skipFunction(F)) - return false; - +static bool runPass(Function &F) { // Insert all new allocas into entry block. BasicBlock *BBEntry = &F.getEntryBlock(); assert(pred_empty(BBEntry) && @@ -115,9 +94,48 @@ return true; } +PreservedAnalyses RegToMemPass::run(Function &F, FunctionAnalysisManager &AM) { + auto *DT = &AM.getResult(F); + auto *LI = &AM.getResult(F); + unsigned N = SplitAllCriticalEdges(F, CriticalEdgeSplittingOptions(DT, LI)); + bool Changed = runPass(F); + if (N == 0 && !Changed) + return PreservedAnalyses::all(); + PreservedAnalyses PA; + PA.preserve(); + PA.preserve(); + return PA; +} + +namespace { +struct RegToMemLegacy : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + RegToMemLegacy() : FunctionPass(ID) { + initializeRegToMemLegacyPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequiredID(BreakCriticalEdgesID); + AU.addPreservedID(BreakCriticalEdgesID); + } + + bool runOnFunction(Function &F) override { + if (F.isDeclaration() || skipFunction(F)) + return false; + return runPass(F); + } +}; +} // namespace + +char RegToMemLegacy::ID = 0; +INITIALIZE_PASS_BEGIN(RegToMemLegacy, "reg2mem", + "Demote all values to stack slots", false, false) +INITIALIZE_PASS_DEPENDENCY(BreakCriticalEdges) +INITIALIZE_PASS_END(RegToMemLegacy, "reg2mem", + "Demote all values to stack slots", false, false) // createDemoteRegisterToMemory - Provide an entry point to create this pass. -char &llvm::DemoteRegisterToMemoryID = RegToMem::ID; +char &llvm::DemoteRegisterToMemoryID = RegToMemLegacy::ID; FunctionPass *llvm::createDemoteRegisterToMemoryPass() { - return new RegToMem(); + return new RegToMemLegacy(); } 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 @@ -92,7 +92,7 @@ initializePartiallyInlineLibCallsLegacyPassPass(Registry); initializeReassociateLegacyPassPass(Registry); initializeRedundantDbgInstEliminationPass(Registry); - initializeRegToMemPass(Registry); + initializeRegToMemLegacyPass(Registry); initializeRewriteStatepointsForGCLegacyPassPass(Registry); initializeSCCPLegacyPassPass(Registry); initializeSROALegacyPassPass(Registry); diff --git a/llvm/test/Transforms/Reg2Mem/crash.ll b/llvm/test/Transforms/Reg2Mem/crash.ll --- a/llvm/test/Transforms/Reg2Mem/crash.ll +++ b/llvm/test/Transforms/Reg2Mem/crash.ll @@ -1,4 +1,5 @@ -; RUN: opt -reg2mem -disable-output -enable-new-pm=0 < %s +; RUN: opt -passes=reg2mem -disable-output -enable-new-pm=1 < %s +; RUN: opt -reg2mem -disable-output < %s ; PR14782 declare void @f1()