diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 344e1ad8942d0..92cf3994e08de 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -891,6 +891,10 @@ static void registerCallbacks(PassBuilder &PB) { PM.addPass(LateLowerGC()); return true; } + if (Name == "AllocOpt") { + PM.addPass(AllocOptPass()); + return true; + } return false; }); diff --git a/src/llvm-alloc-opt.cpp b/src/llvm-alloc-opt.cpp index 3f270cde8d96d..4397992d79f43 100644 --- a/src/llvm-alloc-opt.cpp +++ b/src/llvm-alloc-opt.cpp @@ -31,6 +31,7 @@ #include "julia_internal.h" #include "llvm-pass-helpers.h" #include "llvm-alloc-helpers.h" +#include "passes.h" #include #include @@ -85,13 +86,7 @@ static void removeGCPreserve(CallInst *call, Instruction *val) * * Handle jl_box* */ -struct AllocOpt : public FunctionPass, public JuliaPassContext { - static char ID; - AllocOpt() - : FunctionPass(ID) - { - llvm::initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); - } +struct AllocOpt : public JuliaPassContext { const DataLayout *DL; @@ -100,22 +95,15 @@ struct AllocOpt : public FunctionPass, public JuliaPassContext { Type *T_int64; -private: - bool doInitialization(Module &m) override; - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override - { - FunctionPass::getAnalysisUsage(AU); - AU.addRequired(); - AU.addPreserved(); - AU.setPreservesCFG(); - } + bool doInitialization(Module &m); + bool runOnFunction(Function &F, function_ref GetDT); }; struct Optimizer { - Optimizer(Function &F, AllocOpt &pass) + Optimizer(Function &F, AllocOpt &pass, function_ref GetDT) : F(F), - pass(pass) + pass(pass), + GetDT(std::move(GetDT)) {} void initialize(); @@ -143,11 +131,12 @@ struct Optimizer { Function &F; AllocOpt &pass; DominatorTree *_DT = nullptr; + function_ref GetDT; DominatorTree &getDomTree() { if (!_DT) - _DT = &pass.getAnalysis().getDomTree(); + _DT = &GetDT(); return *_DT; } struct Lifetime { @@ -1159,18 +1148,39 @@ bool AllocOpt::doInitialization(Module &M) return true; } -bool AllocOpt::runOnFunction(Function &F) +bool AllocOpt::runOnFunction(Function &F, function_ref GetDT) { if (!alloc_obj_func) return false; - Optimizer optimizer(F, *this); + Optimizer optimizer(F, *this, std::move(GetDT)); optimizer.initialize(); optimizer.optimizeAll(); return optimizer.finalize(); } -char AllocOpt::ID = 0; -static RegisterPass X("AllocOpt", "Promote heap allocation to stack", +struct AllocOptLegacy : public FunctionPass { + static char ID; + AllocOpt opt; + AllocOptLegacy() : FunctionPass(ID) { + llvm::initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); + } + bool doInitialization(Module &m) override { + return opt.doInitialization(m); + } + bool runOnFunction(Function &F) override { + return opt.runOnFunction(F, [this]() -> DominatorTree & {return getAnalysis().getDomTree();}); + } + void getAnalysisUsage(AnalysisUsage &AU) const override + { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addPreserved(); + AU.setPreservesCFG(); + } +}; + +char AllocOptLegacy::ID = 0; +static RegisterPass X("AllocOpt", "Promote heap allocation to stack", false /* Only looks at CFG */, false /* Analysis Pass */); @@ -1178,7 +1188,22 @@ static RegisterPass X("AllocOpt", "Promote heap allocation to stack", Pass *createAllocOptPass() { - return new AllocOpt(); + return new AllocOptLegacy(); +} + +PreservedAnalyses AllocOptPass::run(Function &F, FunctionAnalysisManager &AM) { + AllocOpt opt; + bool modified = opt.doInitialization(*F.getParent()); + if (opt.runOnFunction(F, [&]()->DominatorTree &{ return AM.getResult(F); })) { + modified = true; + } + if (modified) { + auto preserved = PreservedAnalyses::allInSet(); + preserved.preserve(); + return preserved; + } else { + return PreservedAnalyses::all(); + } } extern "C" JL_DLLEXPORT void LLVMExtraAddAllocOptPass_impl(LLVMPassManagerRef PM) diff --git a/src/llvm-julia-licm.cpp b/src/llvm-julia-licm.cpp index c17fbcda58fed..c45aa66b1d805 100644 --- a/src/llvm-julia-licm.cpp +++ b/src/llvm-julia-licm.cpp @@ -205,7 +205,12 @@ PreservedAnalyses JuliaLICMPass::run(Loop &L, LoopAnalysisManager &AM, return AR.LI; }; auto juliaLICM = JuliaLICM(GetDT, GetLI); - juliaLICM.runOnLoop(&L); + if (juliaLICM.runOnLoop(&L)) { + auto preserved = PreservedAnalyses::allInSet(); + preserved.preserve(); + preserved.preserve(); + return preserved; + } return PreservedAnalyses::all(); } diff --git a/src/passes.h b/src/passes.h index 9327c6e4065f2..d6a613d3b149b 100644 --- a/src/passes.h +++ b/src/passes.h @@ -23,6 +23,10 @@ struct LateLowerGC : PassInfoMixin { static bool isRequired() { return true; } }; +struct AllocOptPass : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + // Module Passes struct CPUFeatures : PassInfoMixin { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); diff --git a/test/llvmpasses/alloc-opt-gcframe.jl b/test/llvmpasses/alloc-opt-gcframe.jl index 8e3de7645595e..78323c15e793f 100644 --- a/test/llvmpasses/alloc-opt-gcframe.jl +++ b/test/llvmpasses/alloc-opt-gcframe.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # RUN: julia --startup-file=no %s | opt -enable-new-pm=0 -load libjulia-codegen%shlibext -AllocOpt -LateLowerGCFrame -FinalLowerGC -S - | FileCheck %s +# RUN: julia --startup-file=no %s | opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(AllocOpt,LateLowerGCFrame),FinalLowerGC' -S - | FileCheck %s isz = sizeof(UInt) == 8 ? "i64" : "i32" diff --git a/test/llvmpasses/alloc-opt-pass.jl b/test/llvmpasses/alloc-opt-pass.jl index 3f2b09ebabb4a..4912a1dc26194 100644 --- a/test/llvmpasses/alloc-opt-pass.jl +++ b/test/llvmpasses/alloc-opt-pass.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # RUN: julia --startup-file=no %s | opt -enable-new-pm=0 -load libjulia-codegen%shlibext -AllocOpt -S - | FileCheck %s +# RUN: julia --startup-file=no %s | opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(AllocOpt)' -S - | FileCheck %s isz = sizeof(UInt) == 8 ? "i64" : "i32"