From 8db96548bdf3dc55a5300b1027b3fe4e6d0a0bdd Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Sat, 2 Oct 2021 18:19:33 -0400 Subject: [PATCH 1/3] [LLVM][PM] Make LateLowerGC NewPM compatible --- src/aotcompile.cpp | 48 +++++++++++++----------- src/llvm-late-gc-lowering.cpp | 63 ++++++++++++++++++++------------ src/passes.h | 4 ++ test/llvmpasses/late-lower-gc.ll | 1 + 4 files changed, 71 insertions(+), 45 deletions(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 8eb718836da6d..0e40452f69e4a 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -879,33 +879,37 @@ static void registerCallbacks(PassBuilder &PB) { PB.registerPipelineParsingCallback( [](StringRef Name, FunctionPassManager &PM, ArrayRef InnerPipeline) { - if (Name == "DemoteFloat16") { - PM.addPass(DemoteFloat16()); - return true; - } - if (Name == "CombineMulAdd") { - PM.addPass(CombineMulAdd()); - return true; - } - return false; + if (Name == "DemoteFloat16") { + PM.addPass(DemoteFloat16()); + return true; + } + if (Name == "CombineMulAdd") { + PM.addPass(CombineMulAdd()); + return true; + } + if (Name == "LateLowerGCFrame") { + PM.addPass(LateLowerGC()); + return true; + } + return false; }); PB.registerPipelineParsingCallback( [](StringRef Name, ModulePassManager &PM, ArrayRef InnerPipeline) { - if (Name == "CPUFeatures") { - PM.addPass(CPUFeatures()); - return true; - } - if (Name == "RemoveNI") { - PM.addPass(RemoveNI()); - return true; - } - if (Name == "LowerSIMDLoop") { - PM.addPass(LowerSIMDLoop()); - return true; - } - return false; + if (Name == "CPUFeatures") { + PM.addPass(CPUFeatures()); + return true; + } + if (Name == "RemoveNI") { + PM.addPass(RemoveNI()); + return true; + } + if (Name == "LowerSIMDLoop") { + PM.addPass(LowerSIMDLoop()); + return true; + } + return false; }); } diff --git a/src/llvm-late-gc-lowering.cpp b/src/llvm-late-gc-lowering.cpp index 3586527668135..6069c7f2e2869 100644 --- a/src/llvm-late-gc-lowering.cpp +++ b/src/llvm-late-gc-lowering.cpp @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" +#include "passes.h" #include #include @@ -301,16 +302,11 @@ struct State { State(Function &F) : F(&F), DT(nullptr), MaxPtrNumber(-1), MaxSafepointNumber(-1) {} }; -namespace llvm { - void initializeLateLowerGCFramePass(PassRegistry &Registry); -} -struct LateLowerGCFrame: public FunctionPass, private JuliaPassContext { + +struct LateLowerGCFrameLegacy: public FunctionPass { static char ID; - LateLowerGCFrame() : FunctionPass(ID) - { - llvm::initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); - } + LateLowerGCFrameLegacy() : FunctionPass(ID) {} protected: void getAnalysisUsage(AnalysisUsage &AU) const override { @@ -320,6 +316,17 @@ struct LateLowerGCFrame: public FunctionPass, private JuliaPassContext { AU.setPreservesCFG(); } +private: + bool runOnFunction(Function &F) override; +}; + +struct LateLowerGCFrame: private JuliaPassContext { + function_ref GetDT; + LateLowerGCFrame(function_ref GetDT) : GetDT(GetDT) {} + +public: + bool runOnFunction(Function &F); + private: CallInst *pgcstack; @@ -350,8 +357,6 @@ struct LateLowerGCFrame: public FunctionPass, private JuliaPassContext { void PlaceGCFrameStore(State &S, unsigned R, unsigned MinColorRoot, const std::vector &Colors, Value *GCFrame, Instruction *InsertBefore); void PlaceGCFrameStores(State &S, unsigned MinColorRoot, const std::vector &Colors, Value *GCFrame); void PlaceRootsAndUpdateCalls(std::vector &Colors, State &S, std::map>); - bool doInitialization(Module &M) override; - bool runOnFunction(Function &F) override; bool CleanupIR(Function &F, State *S=nullptr); void NoteUseChain(State &S, BBState &BBS, User *TheUser); SmallVector GetPHIRefinements(PHINode *phi, State &S); @@ -1385,7 +1390,7 @@ void LateLowerGCFrame::FixUpRefinements(ArrayRef PHINumbers, State &S) j++; if (auto inst = dyn_cast(S.ReversePtrNumbering[refine])) { if (!S.DT) - S.DT = &getAnalysis().getDomTree(); + S.DT = &GetDT(); if (S.DT->dominates(inst, Phi)) continue; // Decrement `j` so we'll overwrite/ignore it. @@ -1997,7 +2002,7 @@ void LateLowerGCFrame::ComputeLiveSets(State &S) { // add in any extra live values. if (!S.GCPreserves.empty()) { if (!S.DT) { - S.DT = &getAnalysis().getDomTree(); + S.DT = &GetDT(); } for (auto it2 : S.GCPreserves) { if (!S.DT->dominates(it2.first, Safepoint)) @@ -2669,16 +2674,9 @@ void LateLowerGCFrame::PlaceRootsAndUpdateCalls(std::vector &Colors, State } } -bool LateLowerGCFrame::doInitialization(Module &M) { - // Initialize platform-agnostic references. - initAll(M); - return true; -} - bool LateLowerGCFrame::runOnFunction(Function &F) { + initAll(*F.getParent()); LLVM_DEBUG(dbgs() << "GC ROOT PLACEMENT: Processing function " << F.getName() << "\n"); - // Check availability of functions again since they might have been deleted. - initFunctions(*F.getParent()); if (!pgcstack_getter) return CleanupIR(F); @@ -2695,11 +2693,30 @@ bool LateLowerGCFrame::runOnFunction(Function &F) { return true; } -char LateLowerGCFrame::ID = 0; -static RegisterPass X("LateLowerGCFrame", "Late Lower GCFrame Pass", false, false); +bool LateLowerGCFrameLegacy::runOnFunction(Function &F) { + auto GetDT = [this]() -> DominatorTree & { + return getAnalysis().getDomTree(); + }; + auto lateLowerGCFrame = LateLowerGCFrame(GetDT); + return lateLowerGCFrame.runOnFunction(F); +} + +PreservedAnalyses LateLowerGC::run(Function &F, FunctionAnalysisManager &AM) +{ + auto GetDT = [&AM, &F]() -> DominatorTree & { + return AM.getResult(F); + }; + auto lateLowerGCFrame = LateLowerGCFrame(GetDT); + lateLowerGCFrame.runOnFunction(F); + return PreservedAnalyses::all(); +} + + +char LateLowerGCFrameLegacy::ID = 0; +static RegisterPass X("LateLowerGCFrame", "Late Lower GCFrame Pass", false, false); Pass *createLateLowerGCFramePass() { - return new LateLowerGCFrame(); + return new LateLowerGCFrameLegacy(); } extern "C" JL_DLLEXPORT void LLVMExtraAddLateLowerGCFramePass_impl(LLVMPassManagerRef PM) diff --git a/src/passes.h b/src/passes.h index 6a18eedf1ea7e..12f57a57731ce 100644 --- a/src/passes.h +++ b/src/passes.h @@ -16,6 +16,10 @@ struct CombineMulAdd : PassInfoMixin { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; +struct LateLowerGC : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; + // Module Passes struct CPUFeatures : PassInfoMixin { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); diff --git a/test/llvmpasses/late-lower-gc.ll b/test/llvmpasses/late-lower-gc.ll index 22cb558c54158..a7ab932dc08f1 100644 --- a/test/llvmpasses/late-lower-gc.ll +++ b/test/llvmpasses/late-lower-gc.ll @@ -1,4 +1,5 @@ ; RUN: opt -enable-new-pm=0 -load libjulia-codegen%shlibext -LateLowerGCFrame -S %s | FileCheck %s +; RUN: opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame)' -S %s | FileCheck %s @tag = external addrspace(10) global {}, align 16 From 7600bfddedddd17e6c4fd5d4334f53bd11efaade Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Thu, 17 Feb 2022 14:17:54 -0500 Subject: [PATCH 2/3] [LLVM][PM] Make JuliaLICM NewPM compatible --- src/aotcompile.cpp | 10 ++++++ src/llvm-julia-licm.cpp | 63 +++++++++++++++++++++++++++-------- src/passes.h | 7 ++++ test/llvmpasses/julia-licm.ll | 1 + 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 0e40452f69e4a..b9b3da10d432d 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -911,6 +911,16 @@ static void registerCallbacks(PassBuilder &PB) { } return false; }); + + PB.registerPipelineParsingCallback( + [](StringRef Name, LoopPassManager &PM, + ArrayRef InnerPipeline) { + if (Name == "JuliaLICM") { + PM.addPass(JuliaLICMPass()); + return true; + } + return false; + }); } extern "C" JL_DLLEXPORT ::llvm::PassPluginLibraryInfo diff --git a/src/llvm-julia-licm.cpp b/src/llvm-julia-licm.cpp index 02d06696330d9..c17fbcda58fed 100644 --- a/src/llvm-julia-licm.cpp +++ b/src/llvm-julia-licm.cpp @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" +#include "passes.h" #include #include @@ -28,11 +29,27 @@ using namespace llvm; namespace { -struct JuliaLICMPass : public LoopPass, public JuliaPassContext { +struct JuliaLICMPassLegacy : public LoopPass { static char ID; - JuliaLICMPass() : LoopPass(ID) {}; + JuliaLICMPassLegacy() : LoopPass(ID) {}; - bool runOnLoop(Loop *L, LPPassManager &LPM) override + bool runOnLoop(Loop *L, LPPassManager &LPM) override; + + protected: + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addRequired(); + AU.setPreservesAll(); + } +}; + +struct JuliaLICM : public JuliaPassContext { + function_ref GetDT; + function_ref GetLI; + JuliaLICM(function_ref GetDT, + function_ref GetLI) : GetDT(GetDT), GetLI(GetLI) {} + + bool runOnLoop(Loop *L) { // Get the preheader block to move instructions into, // required to run this pass. @@ -48,8 +65,8 @@ struct JuliaLICMPass : public LoopPass, public JuliaPassContext { // We also hoist write barriers here, so we don't exit if write_barrier_func exists if (!gc_preserve_begin_func && !write_barrier_func && !alloc_obj_func) return false; - auto LI = &getAnalysis().getLoopInfo(); - auto DT = &getAnalysis().getDomTree(); + auto LI = &GetLI(); + auto DT = &GetDT(); // Lazy initialization of exit blocks insertion points. bool exit_pts_init = false; @@ -159,22 +176,42 @@ struct JuliaLICMPass : public LoopPass, public JuliaPassContext { } return changed; } - - void getAnalysisUsage(AnalysisUsage &AU) const override - { - getLoopAnalysisUsage(AU); - } }; -char JuliaLICMPass::ID = 0; -static RegisterPass +bool JuliaLICMPassLegacy::runOnLoop(Loop *L, LPPassManager &LPM) { + auto GetDT = [this]() -> DominatorTree & { + return getAnalysis().getDomTree(); + }; + auto GetLI = [this]() -> LoopInfo & { + return getAnalysis().getLoopInfo(); + }; + auto juliaLICM = JuliaLICM(GetDT, GetLI); + return juliaLICM.runOnLoop(L); +} + +char JuliaLICMPassLegacy::ID = 0; +static RegisterPass Y("JuliaLICM", "LICM for julia specific intrinsics.", false, false); +} //namespace + +PreservedAnalyses JuliaLICMPass::run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U) +{ + auto GetDT = [&AR]() -> DominatorTree & { + return AR.DT; + }; + auto GetLI = [&AR]() -> LoopInfo & { + return AR.LI; + }; + auto juliaLICM = JuliaLICM(GetDT, GetLI); + juliaLICM.runOnLoop(&L); + return PreservedAnalyses::all(); } Pass *createJuliaLICMPass() { - return new JuliaLICMPass(); + return new JuliaLICMPassLegacy(); } extern "C" JL_DLLEXPORT void LLVMExtraJuliaLICMPass_impl(LLVMPassManagerRef PM) diff --git a/src/passes.h b/src/passes.h index 12f57a57731ce..311ac6de5a09a 100644 --- a/src/passes.h +++ b/src/passes.h @@ -4,6 +4,7 @@ #define JL_PASSES_H #include +#include using namespace llvm; @@ -33,4 +34,10 @@ struct LowerSIMDLoop : PassInfoMixin { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; +// Loop Passes +struct JuliaLICMPass : PassInfoMixin { + PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, + LoopStandardAnalysisResults &AR, LPMUpdater &U); +}; + #endif diff --git a/test/llvmpasses/julia-licm.ll b/test/llvmpasses/julia-licm.ll index 2ffc7f45ca787..b7c088062ce10 100644 --- a/test/llvmpasses/julia-licm.ll +++ b/test/llvmpasses/julia-licm.ll @@ -1,4 +1,5 @@ ; RUN: opt -enable-new-pm=0 -load libjulia-codegen%shlibext -JuliaLICM -S %s | FileCheck %s +; RUN: opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='JuliaLICM' -S %s | FileCheck %s @tag = external addrspace(10) global {}, align 16 From ea3d788823e21bd8d25f22da79cedbbb86eb0b2e Mon Sep 17 00:00:00 2001 From: Valentin Churavy Date: Thu, 17 Feb 2022 23:09:10 -0500 Subject: [PATCH 3/3] [LLVM][PM] Make FinalLowerGC NewPM compatible --- src/aotcompile.cpp | 4 ++ src/llvm-final-gc-lowering.cpp | 63 ++++++++++++++++++++++++----- src/passes.h | 8 ++++ test/llvmpasses/final-lower-gc.ll | 2 + test/llvmpasses/gcroots.ll | 1 + test/llvmpasses/refinements.ll | 1 + test/llvmpasses/returnstwicegc.ll | 1 + test/llvmpasses/safepoint_stress.jl | 2 + 8 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index b9b3da10d432d..344e1ad8942d0 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -909,6 +909,10 @@ static void registerCallbacks(PassBuilder &PB) { PM.addPass(LowerSIMDLoop()); return true; } + if (Name == "FinalLowerGC") { + PM.addPass(FinalLowerGCPass()); + return true; + } return false; }); diff --git a/src/llvm-final-gc-lowering.cpp b/src/llvm-final-gc-lowering.cpp index 2f1ae2be32080..8a7d82b9381a7 100644 --- a/src/llvm-final-gc-lowering.cpp +++ b/src/llvm-final-gc-lowering.cpp @@ -1,6 +1,7 @@ // This file is a part of Julia. License is MIT: https://julialang.org/license #include "llvm-version.h" +#include "passes.h" #include #include @@ -28,10 +29,11 @@ using namespace llvm; // This pass targets typical back-ends for which the standard Julia // runtime library is available. Atypical back-ends should supply // their own lowering pass. -struct FinalLowerGC: public FunctionPass, private JuliaPassContext { - static char ID; - FinalLowerGC() : FunctionPass(ID) - { } + +struct FinalLowerGC: private JuliaPassContext { + bool runOnFunction(Function &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); private: Function *queueRootFunc; @@ -39,10 +41,6 @@ struct FinalLowerGC: public FunctionPass, private JuliaPassContext { Function *bigAllocFunc; Instruction *pgcstack; - bool doInitialization(Module &M) override; - bool doFinalization(Module &M) override; - bool runOnFunction(Function &F) override; - // Lowers a `julia.new_gc_frame` intrinsic. Value *lowerNewGCFrame(CallInst *target, Function &F); @@ -325,12 +323,55 @@ bool FinalLowerGC::runOnFunction(Function &F) return true; } -char FinalLowerGC::ID = 0; -static RegisterPass X("FinalLowerGC", "Final GC intrinsic lowering pass", false, false); +struct FinalLowerGCLegacy: public FunctionPass { + static char ID; + FinalLowerGCLegacy() : FunctionPass(ID), finalLowerGC(FinalLowerGC()) {} + +protected: + void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); + } + +private: + bool runOnFunction(Function &F) override; + bool doInitialization(Module &M) override; + bool doFinalization(Module &M) override; + + FinalLowerGC finalLowerGC; +}; + +bool FinalLowerGCLegacy::runOnFunction(Function &F) { + return finalLowerGC.runOnFunction(F); +} + +bool FinalLowerGCLegacy::doInitialization(Module &M) { + return finalLowerGC.doInitialization(M); +} + +bool FinalLowerGCLegacy::doFinalization(Module &M) { + return finalLowerGC.doFinalization(M); +} + + +PreservedAnalyses FinalLowerGCPass::run(Module &M, ModuleAnalysisManager &AM) +{ + auto finalLowerGC = FinalLowerGC(); + finalLowerGC.doInitialization(M); + for (auto &F : M.functions()) { + if (F.isDeclaration()) + continue; + finalLowerGC.runOnFunction(F); + } + finalLowerGC.doFinalization(M); + return PreservedAnalyses::all(); +} + +char FinalLowerGCLegacy::ID = 0; +static RegisterPass X("FinalLowerGC", "Final GC intrinsic lowering pass", false, false); Pass *createFinalLowerGCPass() { - return new FinalLowerGC(); + return new FinalLowerGCLegacy(); } extern "C" JL_DLLEXPORT void LLVMExtraAddFinalLowerGCPass_impl(LLVMPassManagerRef PM) diff --git a/src/passes.h b/src/passes.h index 311ac6de5a09a..9327c6e4065f2 100644 --- a/src/passes.h +++ b/src/passes.h @@ -11,6 +11,7 @@ using namespace llvm; // Function Passes struct DemoteFloat16 : PassInfoMixin { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + static bool isRequired() { return true; } }; struct CombineMulAdd : PassInfoMixin { @@ -19,11 +20,13 @@ struct CombineMulAdd : PassInfoMixin { struct LateLowerGC : PassInfoMixin { PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + static bool isRequired() { return true; } }; // Module Passes struct CPUFeatures : PassInfoMixin { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + static bool isRequired() { return true; } }; struct RemoveNI : PassInfoMixin { @@ -34,6 +37,11 @@ struct LowerSIMDLoop : PassInfoMixin { PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; +struct FinalLowerGCPass : PassInfoMixin { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + static bool isRequired() { return true; } +}; + // Loop Passes struct JuliaLICMPass : PassInfoMixin { PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, diff --git a/test/llvmpasses/final-lower-gc.ll b/test/llvmpasses/final-lower-gc.ll index 5e4a23770c4e0..176b695ba918b 100644 --- a/test/llvmpasses/final-lower-gc.ll +++ b/test/llvmpasses/final-lower-gc.ll @@ -1,4 +1,6 @@ ; RUN: opt -enable-new-pm=0 -load libjulia-codegen%shlibext -FinalLowerGC -S %s | FileCheck %s +; RUN: opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='FinalLowerGC' -S %s | FileCheck %s + @tag = external addrspace(10) global {} diff --git a/test/llvmpasses/gcroots.ll b/test/llvmpasses/gcroots.ll index 29cb8683244d1..84f120712734b 100644 --- a/test/llvmpasses/gcroots.ll +++ b/test/llvmpasses/gcroots.ll @@ -1,4 +1,5 @@ ; RUN: opt -enable-new-pm=0 -load libjulia-codegen%shlibext -LateLowerGCFrame -FinalLowerGC -S %s | FileCheck %s +; RUN: opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame),FinalLowerGC' -S %s | FileCheck %s declare void @boxed_simple({} addrspace(10)*, {} addrspace(10)*) diff --git a/test/llvmpasses/refinements.ll b/test/llvmpasses/refinements.ll index 0da965e538db8..cb2dea816c56b 100644 --- a/test/llvmpasses/refinements.ll +++ b/test/llvmpasses/refinements.ll @@ -1,4 +1,5 @@ ; RUN: opt -enable-new-pm=0 -load libjulia-codegen%shlibext -LateLowerGCFrame -FinalLowerGC -S %s | FileCheck %s +; RUN: opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame),FinalLowerGC' -S %s | FileCheck %s declare {}*** @julia.ptls_states() diff --git a/test/llvmpasses/returnstwicegc.ll b/test/llvmpasses/returnstwicegc.ll index ebc6127813876..17791d630d61a 100644 --- a/test/llvmpasses/returnstwicegc.ll +++ b/test/llvmpasses/returnstwicegc.ll @@ -1,4 +1,5 @@ ; RUN: opt -enable-new-pm=0 -load libjulia-codegen%shlibext -LateLowerGCFrame -FinalLowerGC -S %s | FileCheck %s +; RUN: opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame),FinalLowerGC' -S %s | FileCheck %s declare void @boxed_simple({} addrspace(10)*, {} addrspace(10)*) diff --git a/test/llvmpasses/safepoint_stress.jl b/test/llvmpasses/safepoint_stress.jl index 7ecf01a194851..dc6752e76d595 100644 --- a/test/llvmpasses/safepoint_stress.jl +++ b/test/llvmpasses/safepoint_stress.jl @@ -1,6 +1,8 @@ # 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 -LateLowerGCFrame -FinalLowerGC -S - | FileCheck %s +# RUN: julia --startup-file=no %s | opt -enable-new-pm=1 --load-pass-plugin=libjulia-codegen%shlibext -passes='function(LateLowerGCFrame),FinalLowerGC' -S - | FileCheck %s + println(""" declare {} addrspace(10)* @alloc()