/// This class provides access to building LLVM's passes. /// /// Its members provide the baseline state available to passes during their /// construction. The \c PassRegistry.def file specifies how to construct all /// of the built-in passes, and those may reference these members during /// construction. classPassBuilder { TargetMachine *TM; PipelineTuningOptions PTO; Optional<PGOOptions> PGOOpt; PassInstrumentationCallbacks *PIC; ... }
/// Get a cached analysis. If the analysis can be invalidated, this will /// assert. template <typename PassT, typename IRUnitTParam> typename PassT::Result *getCachedResult(IRUnitTParam &IR)const{ typename PassT::Result *Res = OuterAM->template getCachedResult<PassT>(IR); if (Res) OuterAM->template verifyNotInvalidated<PassT>(IR, Res); return Res; }
/// Method provided for unit testing, not intended for general use. template <typename PassT, typename IRUnitTParam> boolcachedResultExists(IRUnitTParam &IR)const{ typename PassT::Result *Res = OuterAM->template getCachedResult<PassT>(IR); return Res != nullptr; }
/// When invalidation occurs, remove any registered invalidation events. boolinvalidate( IRUnitT &IRUnit, const PreservedAnalyses &PA, typename AnalysisManager<IRUnitT, ExtraArgTs...>::Invalidator &Inv){ // Loop over the set of registered outer invalidation mappings and if any // of them map to an analysis that is now invalid, clear it out. SmallVector<AnalysisKey *, 4> DeadKeys; for (auto &KeyValuePair : OuterAnalysisInvalidationMap) { AnalysisKey *OuterID = KeyValuePair.first; auto &InnerIDs = KeyValuePair.second; llvm::erase_if(InnerIDs, [&](AnalysisKey *InnerID) { return Inv.invalidate(InnerID, IRUnit, PA); }); if (InnerIDs.empty()) DeadKeys.push_back(OuterID); }
for (auto OuterID : DeadKeys) OuterAnalysisInvalidationMap.erase(OuterID);
// The proxy itself remains valid regardless of anything else. returnfalse; }
/// Register a deferred invalidation event for when the outer analysis /// manager processes its invalidations. template <typename OuterAnalysisT, typename InvalidatedAnalysisT> voidregisterOuterAnalysisInvalidation(){ AnalysisKey *OuterID = OuterAnalysisT::ID(); AnalysisKey *InvalidatedID = InvalidatedAnalysisT::ID();
auto &InvalidatedIDList = OuterAnalysisInvalidationMap[OuterID]; // Note, this is a linear scan. If we end up with large numbers of // analyses that all trigger invalidation on the same outer analysis, // this entire system should be changed to some other deterministic // data structure such as a `SetVector` of a pair of pointers. if (!llvm::is_contained(InvalidatedIDList, InvalidatedID)) InvalidatedIDList.push_back(InvalidatedID); }
/// Access the map from outer analyses to deferred invalidation requiring /// analyses. const SmallDenseMap<AnalysisKey *, TinyPtrVector<AnalysisKey *>, 2> & getOuterInvalidations() const { return OuterAnalysisInvalidationMap; }
private: const AnalysisManagerT *OuterAM;
/// A map from an outer analysis ID to the set of this IR-unit's analyses /// which need to be invalidated. SmallDenseMap<AnalysisKey *, TinyPtrVector<AnalysisKey *>, 2> OuterAnalysisInvalidationMap; };
/// Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c OuterAM reference into the /// result. Result run(IRUnitT &, AnalysisManager<IRUnitT, ExtraArgTs...> &, ExtraArgTs...){ returnResult(*OuterAM); }
// Register all the standard instrumentation callbacks. If \p FAM is nullptr // then PreservedCFGChecker is not enabled. voidregisterCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM = nullptr);
Error PassBuilder::parseModulePass(ModulePassManager &MPM, const PipelineElement &E){ auto &Name = E.Name; auto &InnerPipeline = E.InnerPipeline;
// First handle complex passes like the pass managers which carry pipelines. if (!InnerPipeline.empty()) { if (Name == "module") { ModulePassManager NestedMPM; if (auto Err = parseModulePassPipeline(NestedMPM, InnerPipeline)) return Err; MPM.addPass(std::move(NestedMPM)); return Error::success(); } if (Name == "cgscc") { ... } if (Name == "function" || Name == "function<eager-inv>") { FunctionPassManager FPM; if (auto Err = parseFunctionPassPipeline(FPM, InnerPipeline)) return Err; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM), Name != "function")); return Error::success(); } if (auto Count = parseRepeatPassName(Name)) { ... }
for (auto &C : ModulePipelineParsingCallbacks) if (C(Name, MPM, InnerPipeline)) return Error::success();
// Normal passes can't have pipelines. return make_error<StringError>( formatv("invalid use of '{0}' pass as module pipeline", Name).str(), inconvertibleErrorCode()); ; }
// Manually handle aliases for pre-configured pipeline fragments. if (startsWithDefaultPipelineAliasPrefix(Name)) { SmallVector<StringRef, 3> Matches; if (!DefaultAliasRegex.match(Name, &Matches)) return make_error<StringError>( formatv("unknown default pipeline alias '{0}'", Name).str(), inconvertibleErrorCode());
assert(Matches.size() == 3 && "Must capture two matched strings!");
// This is consistent with old pass manager invoked via opt, but // inconsistent with clang. Clang doesn't enable loop vectorization // but does enable slp vectorization at Oz. PTO.LoopVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz; PTO.SLPVectorization = L.getSpeedupLevel() > 1 && L != OptimizationLevel::Oz;
ModulePassManager PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, bool LTOPreLink){ assert(Level == OptimizationLevel::O0 && "buildO0DefaultPipeline should only be used with O0");
ModulePassManager MPM;
... // Build a minimal pipeline based on the semantics required by LLVM, // which is just that always inlining occurs. Further, disable generating // lifetime intrinsics to avoid enabling further optimizations during // code generation. MPM.addPass(AlwaysInlinerPass( /*InsertLifetimeIntrinsics=*/false));
if (PTO.MergeFunctions) MPM.addPass(MergeFunctionsPass());
if (EnableMatrix) MPM.addPass( createModuleToFunctionPassAdaptor(LowerMatrixIntrinsicsPass(true)));
if (!CGSCCOptimizerLateEPCallbacks.empty()) { CGSCCPassManager CGPM; for (auto &C : CGSCCOptimizerLateEPCallbacks) C(CGPM, Level); if (!CGPM.isEmpty()) MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); } ... ModulePassManager CoroPM; CoroPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); CGSCCPassManager CGPM; CGPM.addPass(CoroSplitPass()); ... if (LTOPreLink) addRequiredLTOPreLinkPasses(MPM);
structPassPluginLibraryInfo { /// The API version understood by this plugin, usually \c /// LLVM_PLUGIN_API_VERSION uint32_t APIVersion; /// A meaningful name of the plugin. constchar *PluginName; /// The version of the plugin. constchar *PluginVersion;
/// The callback for registering plugin passes with a \c PassBuilder /// instance void (*RegisterPassBuilderCallbacks)(PassBuilder &); };