From 06aa8b189ab3a13580d0abdcd5bf30ef22b119bd Mon Sep 17 00:00:00 2001 From: paperchalice Date: Wed, 13 Dec 2023 15:56:12 +0800 Subject: [PATCH] [CodeGen] Add analyses to help for porting GC passes (#74972) - `CollectorMetadataAnalysis` provides `GCStrategyMap`. - `GCFunctionAnalysis` provides `GCFunctionInfo`. `GCStrategyMap` owns `GCStrategy` pointers and this pass is used by `AsmPrinter` to iterate all GC strategies. Most passes that require `GCModuleInfo` actually require the `GCFunctionInfo`, so add `GCFunctionAnalysis` for convenience. --- .../include/llvm/CodeGen/CodeGenPassBuilder.h | 1 + llvm/include/llvm/CodeGen/GCMetadata.h | 40 +++++++++++++++ .../llvm/CodeGen/MachinePassRegistry.def | 2 + llvm/lib/CodeGen/GCMetadata.cpp | 50 +++++++++++++++++++ llvm/lib/Passes/PassBuilder.cpp | 1 + llvm/lib/Passes/PassRegistry.def | 2 + 6 files changed, 96 insertions(+) diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h index 2a8aa7b158ed..502a2bb4853b 100644 --- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h +++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h @@ -26,6 +26,7 @@ #include "llvm/CodeGen/CallBrPrepare.h" #include "llvm/CodeGen/DwarfEHPrepare.h" #include "llvm/CodeGen/ExpandReductions.h" +#include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/InterleavedAccess.h" #include "llvm/CodeGen/InterleavedLoadCombine.h" #include "llvm/CodeGen/JMCInstrumenter.h" diff --git a/llvm/include/llvm/CodeGen/GCMetadata.h b/llvm/include/llvm/CodeGen/GCMetadata.h index 334c5c23b8fa..9e4e8342ea29 100644 --- a/llvm/include/llvm/CodeGen/GCMetadata.h +++ b/llvm/include/llvm/CodeGen/GCMetadata.h @@ -38,6 +38,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/GCStrategy.h" +#include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include #include @@ -101,6 +102,10 @@ public: GCFunctionInfo(const Function &F, GCStrategy &S); ~GCFunctionInfo(); + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); + /// getFunction - Return the function to which this metadata applies. const Function &getFunction() const { return F; } @@ -146,6 +151,41 @@ public: size_t live_size(const iterator &p) const { return roots_size(); } }; +struct GCStrategyMap { + StringMap> StrategyMap; + + GCStrategyMap() = default; + GCStrategyMap(GCStrategyMap &&) = default; + + /// Handle invalidation explicitly. + bool invalidate(Module &M, const PreservedAnalyses &PA, + ModuleAnalysisManager::Invalidator &Inv); +}; + +/// An analysis pass which caches information about the entire Module. +/// Records a cache of the 'active' gc strategy objects for the current Module. +class CollectorMetadataAnalysis + : public AnalysisInfoMixin { + friend struct AnalysisInfoMixin; + static AnalysisKey Key; + +public: + using Result = GCStrategyMap; + Result run(Module &M, ModuleAnalysisManager &MAM); +}; + +/// An analysis pass which caches information about the Function. +/// Records the function level information used by GCRoots. +/// This pass depends on `CollectorMetadataAnalysis`. +class GCFunctionAnalysis : public AnalysisInfoMixin { + friend struct AnalysisInfoMixin; + static AnalysisKey Key; + +public: + using Result = GCFunctionInfo; + Result run(Function &F, FunctionAnalysisManager &FAM); +}; + /// An analysis pass which caches information about the entire Module. /// Records both the function level information used by GCRoots and a /// cache of the 'active' gc strategy objects for the current Module. diff --git a/llvm/include/llvm/CodeGen/MachinePassRegistry.def b/llvm/include/llvm/CodeGen/MachinePassRegistry.def index 4e2bee49a71c..f5d2834d598e 100644 --- a/llvm/include/llvm/CodeGen/MachinePassRegistry.def +++ b/llvm/include/llvm/CodeGen/MachinePassRegistry.def @@ -16,6 +16,7 @@ #ifndef MODULE_ANALYSIS #define MODULE_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) #endif +MODULE_ANALYSIS("collector-metadata", CollectorMetadataAnalysis, ()) MODULE_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) #undef MODULE_ANALYSIS @@ -29,6 +30,7 @@ MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass, ()) #ifndef FUNCTION_ANALYSIS #define FUNCTION_ANALYSIS(NAME, PASS_NAME, CONSTRUCTOR) #endif +FUNCTION_ANALYSIS("gc-function", GCFunctionAnalysis, ()) FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, (PIC)) FUNCTION_ANALYSIS("targetir", TargetIRAnalysis, (std::move(TM.getTargetIRAnalysis()))) diff --git a/llvm/lib/CodeGen/GCMetadata.cpp b/llvm/lib/CodeGen/GCMetadata.cpp index 49e03b4b132c..cad7d1f1137b 100644 --- a/llvm/lib/CodeGen/GCMetadata.cpp +++ b/llvm/lib/CodeGen/GCMetadata.cpp @@ -24,6 +24,50 @@ using namespace llvm; +bool GCStrategyMap::invalidate(Module &M, const PreservedAnalyses &PA, + ModuleAnalysisManager::Invalidator &) { + for (const auto &F : M) { + if (F.isDeclaration() || !F.hasGC()) + continue; + if (!StrategyMap.contains(F.getGC())) + return true; + } + return false; +} + +AnalysisKey CollectorMetadataAnalysis::Key; + +CollectorMetadataAnalysis::Result +CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) { + Result R; + auto &Map = R.StrategyMap; + for (auto &F : M) { + if (F.isDeclaration() || !F.hasGC()) + continue; + if (auto GCName = F.getGC(); !Map.contains(GCName)) + Map[GCName] = getGCStrategy(GCName); + } + return R; +} + +AnalysisKey GCFunctionAnalysis::Key; + +GCFunctionAnalysis::Result +GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { + assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); + assert(F.hasGC() && "Function doesn't have GC!"); + + auto &MAMProxy = FAM.getResult(F); + assert( + MAMProxy.cachedResultExists(*F.getParent()) && + "This pass need module analysis `collector-metadata`!"); + auto &Map = + MAMProxy.getCachedResult(*F.getParent()) + ->StrategyMap; + GCFunctionInfo Info(F, *Map[F.getGC()]); + return Info; +} + INITIALIZE_PASS(GCModuleInfo, "collector-metadata", "Create Garbage Collector Module Metadata", false, false) @@ -34,6 +78,12 @@ GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) GCFunctionInfo::~GCFunctionInfo() = default; +bool GCFunctionInfo::invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &) { + auto PAC = PA.getChecker(); + return !PAC.preserved() && !PAC.preservedSet>(); +} + // ----------------------------------------------------------------------------- char GCModuleInfo::ID = 0; diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 302fac68782c..e1ffa071e426 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -76,6 +76,7 @@ #include "llvm/CodeGen/DwarfEHPrepare.h" #include "llvm/CodeGen/ExpandLargeDivRem.h" #include "llvm/CodeGen/ExpandLargeFpConvert.h" +#include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/HardwareLoops.h" #include "llvm/CodeGen/InterleavedAccess.h" #include "llvm/CodeGen/InterleavedLoadCombine.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 746446d61325..22190e2ed76f 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -19,6 +19,7 @@ #define MODULE_ANALYSIS(NAME, CREATE_PASS) #endif MODULE_ANALYSIS("callgraph", CallGraphAnalysis()) +MODULE_ANALYSIS("collector-metadata", CollectorMetadataAnalysis()) MODULE_ANALYSIS("inline-advisor", InlineAdvisorAnalysis()) MODULE_ANALYSIS("ir-similarity", IRSimilarityAnalysis()) MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis()) @@ -235,6 +236,7 @@ FUNCTION_ANALYSIS("demanded-bits", DemandedBitsAnalysis()) FUNCTION_ANALYSIS("domfrontier", DominanceFrontierAnalysis()) FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis()) FUNCTION_ANALYSIS("func-properties", FunctionPropertiesAnalysis()) +FUNCTION_ANALYSIS("gc-function", GCFunctionAnalysis()) FUNCTION_ANALYSIS("inliner-size-estimator", InlineSizeEstimatorAnalysis()) FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis())