diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/include/llvm/Passes | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/include/llvm/Passes')
4 files changed, 1507 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/include/llvm/Passes/OptimizationLevel.h b/contrib/libs/llvm14/include/llvm/Passes/OptimizationLevel.h new file mode 100644 index 0000000000..0986b0f6de --- /dev/null +++ b/contrib/libs/llvm14/include/llvm/Passes/OptimizationLevel.h @@ -0,0 +1,138 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===-------- LLVM-provided High-Level Optimization levels -*- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header enumerates the LLVM-provided high-level optimization levels. +/// Each level has a specific goal and rationale. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_OPTIMIZATIONLEVEL_H +#define LLVM_PASSES_OPTIMIZATIONLEVEL_H + +#include <assert.h> + +namespace llvm { + +class OptimizationLevel final { + unsigned SpeedLevel = 2; + unsigned SizeLevel = 0; + OptimizationLevel(unsigned SpeedLevel, unsigned SizeLevel) + : SpeedLevel(SpeedLevel), SizeLevel(SizeLevel) { + // Check that only valid combinations are passed. + assert(SpeedLevel <= 3 && + "Optimization level for speed should be 0, 1, 2, or 3"); + assert(SizeLevel <= 2 && + "Optimization level for size should be 0, 1, or 2"); + assert((SizeLevel == 0 || SpeedLevel == 2) && + "Optimize for size should be encoded with speedup level == 2"); + } + +public: + OptimizationLevel() = default; + /// Disable as many optimizations as possible. This doesn't completely + /// disable the optimizer in all cases, for example always_inline functions + /// can be required to be inlined for correctness. + static const OptimizationLevel O0; + + /// Optimize quickly without destroying debuggability. + /// + /// This level is tuned to produce a result from the optimizer as quickly + /// as possible and to avoid destroying debuggability. This tends to result + /// in a very good development mode where the compiled code will be + /// immediately executed as part of testing. As a consequence, where + /// possible, we would like to produce efficient-to-execute code, but not + /// if it significantly slows down compilation or would prevent even basic + /// debugging of the resulting binary. + /// + /// As an example, complex loop transformations such as versioning, + /// vectorization, or fusion don't make sense here due to the degree to + /// which the executed code differs from the source code, and the compile + /// time cost. + static const OptimizationLevel O1; + /// Optimize for fast execution as much as possible without triggering + /// significant incremental compile time or code size growth. + /// + /// The key idea is that optimizations at this level should "pay for + /// themselves". So if an optimization increases compile time by 5% or + /// increases code size by 5% for a particular benchmark, that benchmark + /// should also be one which sees a 5% runtime improvement. If the compile + /// time or code size penalties happen on average across a diverse range of + /// LLVM users' benchmarks, then the improvements should as well. + /// + /// And no matter what, the compile time needs to not grow superlinearly + /// with the size of input to LLVM so that users can control the runtime of + /// the optimizer in this mode. + /// + /// This is expected to be a good default optimization level for the vast + /// majority of users. + static const OptimizationLevel O2; + /// Optimize for fast execution as much as possible. + /// + /// This mode is significantly more aggressive in trading off compile time + /// and code size to get execution time improvements. The core idea is that + /// this mode should include any optimization that helps execution time on + /// balance across a diverse collection of benchmarks, even if it increases + /// code size or compile time for some benchmarks without corresponding + /// improvements to execution time. + /// + /// Despite being willing to trade more compile time off to get improved + /// execution time, this mode still tries to avoid superlinear growth in + /// order to make even significantly slower compile times at least scale + /// reasonably. This does not preclude very substantial constant factor + /// costs though. + static const OptimizationLevel O3; + /// Similar to \c O2 but tries to optimize for small code size instead of + /// fast execution without triggering significant incremental execution + /// time slowdowns. + /// + /// The logic here is exactly the same as \c O2, but with code size and + /// execution time metrics swapped. + /// + /// A consequence of the different core goal is that this should in general + /// produce substantially smaller executables that still run in + /// a reasonable amount of time. + static const OptimizationLevel Os; + /// A very specialized mode that will optimize for code size at any and all + /// costs. + /// + /// This is useful primarily when there are absolute size limitations and + /// any effort taken to reduce the size is worth it regardless of the + /// execution time impact. You should expect this level to produce rather + /// slow, but very small, code. + static const OptimizationLevel Oz; + + bool isOptimizingForSpeed() const { return SizeLevel == 0 && SpeedLevel > 0; } + + bool isOptimizingForSize() const { return SizeLevel > 0; } + + bool operator==(const OptimizationLevel &Other) const { + return SizeLevel == Other.SizeLevel && SpeedLevel == Other.SpeedLevel; + } + bool operator!=(const OptimizationLevel &Other) const { + return SizeLevel != Other.SizeLevel || SpeedLevel != Other.SpeedLevel; + } + + unsigned getSpeedupLevel() const { return SpeedLevel; } + + unsigned getSizeLevel() const { return SizeLevel; } +}; +} // namespace llvm + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm14/include/llvm/Passes/PassBuilder.h b/contrib/libs/llvm14/include/llvm/Passes/PassBuilder.h new file mode 100644 index 0000000000..2535e2d523 --- /dev/null +++ b/contrib/libs/llvm14/include/llvm/Passes/PassBuilder.h @@ -0,0 +1,699 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Parsing, selection, and construction of pass pipelines --*- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Interfaces for registering analysis passes, producing common pass manager +/// configurations, and parsing of pass pipelines. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_PASSBUILDER_H +#define LLVM_PASSES_PASSBUILDER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/PGOOptions.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO/Inliner.h" +#include "llvm/Transforms/IPO/ModuleInliner.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/Scalar/LoopPassManager.h" +#include <vector> + +namespace llvm { +class StringRef; +class AAManager; +class TargetMachine; +class ModuleSummaryIndex; + +/// Tunable parameters for passes in the default pipelines. +class PipelineTuningOptions { +public: + /// Constructor sets pipeline tuning defaults based on cl::opts. Each option + /// can be set in the PassBuilder when using a LLVM as a library. + PipelineTuningOptions(); + + /// Tuning option to set loop interleaving on/off, set based on opt level. + bool LoopInterleaving; + + /// Tuning option to enable/disable loop vectorization, set based on opt + /// level. + bool LoopVectorization; + + /// Tuning option to enable/disable slp loop vectorization, set based on opt + /// level. + bool SLPVectorization; + + /// Tuning option to enable/disable loop unrolling. Its default value is true. + bool LoopUnrolling; + + /// Tuning option to forget all SCEV loops in LoopUnroll. Its default value + /// is that of the flag: `-forget-scev-loop-unroll`. + bool ForgetAllSCEVInLoopUnroll; + + /// Tuning option to cap the number of calls to retrive clobbering accesses in + /// MemorySSA, in LICM. + unsigned LicmMssaOptCap; + + /// Tuning option to disable promotion to scalars in LICM with MemorySSA, if + /// the number of access is too large. + unsigned LicmMssaNoAccForPromotionCap; + + /// Tuning option to enable/disable call graph profile. Its default value is + /// that of the flag: `-enable-npm-call-graph-profile`. + bool CallGraphProfile; + + /// Tuning option to enable/disable function merging. Its default value is + /// false. + bool MergeFunctions; + + // Experimental option to eagerly invalidate more analyses. This has the + // potential to decrease max memory usage in exchange for more compile time. + // This may affect codegen due to either passes using analyses only when + // cached, or invalidating and recalculating an analysis that was + // stale/imprecise but still valid. Currently this invalidates all function + // analyses after various module->function or cgscc->function adaptors in the + // default pipelines. + bool EagerlyInvalidateAnalyses; +}; + +/// 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. +class PassBuilder { + TargetMachine *TM; + PipelineTuningOptions PTO; + Optional<PGOOptions> PGOOpt; + PassInstrumentationCallbacks *PIC; + +public: + /// A struct to capture parsed pass pipeline names. + /// + /// A pipeline is defined as a series of names, each of which may in itself + /// recursively contain a nested pipeline. A name is either the name of a pass + /// (e.g. "instcombine") or the name of a pipeline type (e.g. "cgscc"). If the + /// name is the name of a pass, the InnerPipeline is empty, since passes + /// cannot contain inner pipelines. See parsePassPipeline() for a more + /// detailed description of the textual pipeline format. + struct PipelineElement { + StringRef Name; + std::vector<PipelineElement> InnerPipeline; + }; + + explicit PassBuilder(TargetMachine *TM = nullptr, + PipelineTuningOptions PTO = PipelineTuningOptions(), + Optional<PGOOptions> PGOOpt = None, + PassInstrumentationCallbacks *PIC = nullptr); + + /// Cross register the analysis managers through their proxies. + /// + /// This is an interface that can be used to cross register each + /// AnalysisManager with all the others analysis managers. + void crossRegisterProxies(LoopAnalysisManager &LAM, + FunctionAnalysisManager &FAM, + CGSCCAnalysisManager &CGAM, + ModuleAnalysisManager &MAM); + + /// Registers all available module analysis passes. + /// + /// This is an interface that can be used to populate a \c + /// ModuleAnalysisManager with all registered module analyses. Callers can + /// still manually register any additional analyses. Callers can also + /// pre-register analyses and this will not override those. + void registerModuleAnalyses(ModuleAnalysisManager &MAM); + + /// Registers all available CGSCC analysis passes. + /// + /// This is an interface that can be used to populate a \c CGSCCAnalysisManager + /// with all registered CGSCC analyses. Callers can still manually register any + /// additional analyses. Callers can also pre-register analyses and this will + /// not override those. + void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); + + /// Registers all available function analysis passes. + /// + /// This is an interface that can be used to populate a \c + /// FunctionAnalysisManager with all registered function analyses. Callers can + /// still manually register any additional analyses. Callers can also + /// pre-register analyses and this will not override those. + void registerFunctionAnalyses(FunctionAnalysisManager &FAM); + + /// Registers all available loop analysis passes. + /// + /// This is an interface that can be used to populate a \c LoopAnalysisManager + /// with all registered loop analyses. Callers can still manually register any + /// additional analyses. + void registerLoopAnalyses(LoopAnalysisManager &LAM); + + /// Construct the core LLVM function canonicalization and simplification + /// pipeline. + /// + /// This is a long pipeline and uses most of the per-function optimization + /// passes in LLVM to canonicalize and simplify the IR. It is suitable to run + /// repeatedly over the IR and is not expected to destroy important + /// information about the semantics of the IR. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + /// + /// \p Phase indicates the current ThinLTO phase. + FunctionPassManager + buildFunctionSimplificationPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase); + + /// Construct the core LLVM module canonicalization and simplification + /// pipeline. + /// + /// This pipeline focuses on canonicalizing and simplifying the entire module + /// of IR. Much like the function simplification pipeline above, it is + /// suitable to run repeatedly over the IR and is not expected to destroy + /// important information. It does, however, perform inlining and other + /// heuristic based simplifications that are not strictly reversible. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + /// + /// \p Phase indicates the current ThinLTO phase. + ModulePassManager buildModuleSimplificationPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase); + + /// Construct the module pipeline that performs inlining as well as + /// the inlining-driven cleanups. + ModuleInlinerWrapperPass buildInlinerPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase); + + /// Construct the module pipeline that performs inlining with + /// module inliner pass. + ModulePassManager buildModuleInlinerPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase); + + /// Construct the core LLVM module optimization pipeline. + /// + /// This pipeline focuses on optimizing the execution speed of the IR. It + /// uses cost modeling and thresholds to balance code growth against runtime + /// improvements. It includes vectorization and other information destroying + /// transformations. It also cannot generally be run repeatedly on a module + /// without potentially seriously regressing either runtime performance of + /// the code or serious code size growth. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + ModulePassManager buildModuleOptimizationPipeline(OptimizationLevel Level, + bool LTOPreLink = false); + + /// Build a per-module default optimization pipeline. + /// + /// This provides a good default optimization pipeline for per-module + /// optimization and code generation without any link-time optimization. It + /// typically correspond to frontend "-O[123]" options for optimization + /// levels \c O1, \c O2 and \c O3 resp. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + ModulePassManager buildPerModuleDefaultPipeline(OptimizationLevel Level, + bool LTOPreLink = false); + + /// Build a pre-link, ThinLTO-targeting default optimization pipeline to + /// a pass manager. + /// + /// This adds the pre-link optimizations tuned to prepare a module for + /// a ThinLTO run. It works to minimize the IR which needs to be analyzed + /// without making irreversible decisions which could be made better during + /// the LTO run. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + ModulePassManager buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level); + + /// Build an ThinLTO default optimization pipeline to a pass manager. + /// + /// This provides a good default optimization pipeline for link-time + /// optimization and code generation. It is particularly tuned to fit well + /// when IR coming into the LTO phase was first run through \c + /// addPreLinkLTODefaultPipeline, and the two coordinate closely. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + ModulePassManager + buildThinLTODefaultPipeline(OptimizationLevel Level, + const ModuleSummaryIndex *ImportSummary); + + /// Build a pre-link, LTO-targeting default optimization pipeline to a pass + /// manager. + /// + /// This adds the pre-link optimizations tuned to work well with a later LTO + /// run. It works to minimize the IR which needs to be analyzed without + /// making irreversible decisions which could be made better during the LTO + /// run. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + ModulePassManager buildLTOPreLinkDefaultPipeline(OptimizationLevel Level); + + /// Build an LTO default optimization pipeline to a pass manager. + /// + /// This provides a good default optimization pipeline for link-time + /// optimization and code generation. It is particularly tuned to fit well + /// when IR coming into the LTO phase was first run through \c + /// addPreLinkLTODefaultPipeline, and the two coordinate closely. + /// + /// Note that \p Level cannot be `O0` here. The pipelines produced are + /// only intended for use when attempting to optimize code. If frontends + /// require some transformations for semantic reasons, they should explicitly + /// build them. + ModulePassManager buildLTODefaultPipeline(OptimizationLevel Level, + ModuleSummaryIndex *ExportSummary); + + /// Build an O0 pipeline with the minimal semantically required passes. + /// + /// This should only be used for non-LTO and LTO pre-link pipelines. + ModulePassManager buildO0DefaultPipeline(OptimizationLevel Level, + bool LTOPreLink = false); + + /// Build the default `AAManager` with the default alias analysis pipeline + /// registered. + /// + /// This also adds target-specific alias analyses registered via + /// TargetMachine::registerDefaultAliasAnalyses(). + AAManager buildDefaultAAPipeline(); + + /// Parse a textual pass pipeline description into a \c + /// ModulePassManager. + /// + /// The format of the textual pass pipeline description looks something like: + /// + /// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...) + /// + /// Pass managers have ()s describing the nest structure of passes. All passes + /// are comma separated. As a special shortcut, if the very first pass is not + /// a module pass (as a module pass manager is), this will automatically form + /// the shortest stack of pass managers that allow inserting that first pass. + /// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop + /// passes 'lpassN', all of these are valid: + /// + /// fpass1,fpass2,fpass3 + /// cgpass1,cgpass2,cgpass3 + /// lpass1,lpass2,lpass3 + /// + /// And they are equivalent to the following (resp.): + /// + /// module(function(fpass1,fpass2,fpass3)) + /// module(cgscc(cgpass1,cgpass2,cgpass3)) + /// module(function(loop(lpass1,lpass2,lpass3))) + /// + /// This shortcut is especially useful for debugging and testing small pass + /// combinations. + /// + /// The sequence of passes aren't necessarily the exact same kind of pass. + /// You can mix different levels implicitly if adaptor passes are defined to + /// make them work. For example, + /// + /// mpass1,fpass1,fpass2,mpass2,lpass1 + /// + /// This pipeline uses only one pass manager: the top-level module manager. + /// fpass1,fpass2 and lpass1 are added into the the top-level module manager + /// using only adaptor passes. No nested function/loop pass managers are + /// added. The purpose is to allow easy pass testing when the user + /// specifically want the pass to run under a adaptor directly. This is + /// preferred when a pipeline is largely of one type, but one or just a few + /// passes are of different types(See PassBuilder.cpp for examples). + Error parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText); + + /// {{@ Parse a textual pass pipeline description into a specific PassManager + /// + /// Automatic deduction of an appropriate pass manager stack is not supported. + /// For example, to insert a loop pass 'lpass' into a FunctionPassManager, + /// this is the valid pipeline text: + /// + /// function(lpass) + Error parsePassPipeline(CGSCCPassManager &CGPM, StringRef PipelineText); + Error parsePassPipeline(FunctionPassManager &FPM, StringRef PipelineText); + Error parsePassPipeline(LoopPassManager &LPM, StringRef PipelineText); + /// @}} + + /// Parse a textual alias analysis pipeline into the provided AA manager. + /// + /// The format of the textual AA pipeline is a comma separated list of AA + /// pass names: + /// + /// basic-aa,globals-aa,... + /// + /// The AA manager is set up such that the provided alias analyses are tried + /// in the order specified. See the \c AAManaager documentation for details + /// about the logic used. This routine just provides the textual mapping + /// between AA names and the analyses to register with the manager. + /// + /// Returns false if the text cannot be parsed cleanly. The specific state of + /// the \p AA manager is unspecified if such an error is encountered and this + /// returns false. + Error parseAAPipeline(AAManager &AA, StringRef PipelineText); + + /// Returns true if the pass name is the name of an alias analysis pass. + bool isAAPassName(StringRef PassName); + + /// Returns true if the pass name is the name of a (non-alias) analysis pass. + bool isAnalysisPassName(StringRef PassName); + + /// Print pass names. + void printPassNames(raw_ostream &OS); + + /// Register a callback for a default optimizer pipeline extension + /// point + /// + /// This extension point allows adding passes that perform peephole + /// optimizations similar to the instruction combiner. These passes will be + /// inserted after each instance of the instruction combiner pass. + void registerPeepholeEPCallback( + const std::function<void(FunctionPassManager &, OptimizationLevel)> &C) { + PeepholeEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension + /// point + /// + /// This extension point allows adding late loop canonicalization and + /// simplification passes. This is the last point in the loop optimization + /// pipeline before loop deletion. Each pass added + /// here must be an instance of LoopPass. + /// This is the place to add passes that can remove loops, such as target- + /// specific loop idiom recognition. + void registerLateLoopOptimizationsEPCallback( + const std::function<void(LoopPassManager &, OptimizationLevel)> &C) { + LateLoopOptimizationsEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension + /// point + /// + /// This extension point allows adding loop passes to the end of the loop + /// optimizer. + void registerLoopOptimizerEndEPCallback( + const std::function<void(LoopPassManager &, OptimizationLevel)> &C) { + LoopOptimizerEndEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension + /// point + /// + /// This extension point allows adding optimization passes after most of the + /// main optimizations, but before the last cleanup-ish optimizations. + void registerScalarOptimizerLateEPCallback( + const std::function<void(FunctionPassManager &, OptimizationLevel)> &C) { + ScalarOptimizerLateEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension + /// point + /// + /// This extension point allows adding CallGraphSCC passes at the end of the + /// main CallGraphSCC passes and before any function simplification passes run + /// by CGPassManager. + void registerCGSCCOptimizerLateEPCallback( + const std::function<void(CGSCCPassManager &, OptimizationLevel)> &C) { + CGSCCOptimizerLateEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension + /// point + /// + /// This extension point allows adding optimization passes before the + /// vectorizer and other highly target specific optimization passes are + /// executed. + void registerVectorizerStartEPCallback( + const std::function<void(FunctionPassManager &, OptimizationLevel)> &C) { + VectorizerStartEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension point. + /// + /// This extension point allows adding optimization once at the start of the + /// pipeline. This does not apply to 'backend' compiles (LTO and ThinLTO + /// link-time pipelines). + void registerPipelineStartEPCallback( + const std::function<void(ModulePassManager &, OptimizationLevel)> &C) { + PipelineStartEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension point. + /// + /// This extension point allows adding optimization right after passes that do + /// basic simplification of the input IR. + void registerPipelineEarlySimplificationEPCallback( + const std::function<void(ModulePassManager &, OptimizationLevel)> &C) { + PipelineEarlySimplificationEPCallbacks.push_back(C); + } + + /// Register a callback for a default optimizer pipeline extension point + /// + /// This extension point allows adding optimizations at the very end of the + /// function optimization pipeline. + void registerOptimizerLastEPCallback( + const std::function<void(ModulePassManager &, OptimizationLevel)> &C) { + OptimizerLastEPCallbacks.push_back(C); + } + + /// Register a callback for parsing an AliasAnalysis Name to populate + /// the given AAManager \p AA + void registerParseAACallback( + const std::function<bool(StringRef Name, AAManager &AA)> &C) { + AAParsingCallbacks.push_back(C); + } + + /// {{@ Register callbacks for analysis registration with this PassBuilder + /// instance. + /// Callees register their analyses with the given AnalysisManager objects. + void registerAnalysisRegistrationCallback( + const std::function<void(CGSCCAnalysisManager &)> &C) { + CGSCCAnalysisRegistrationCallbacks.push_back(C); + } + void registerAnalysisRegistrationCallback( + const std::function<void(FunctionAnalysisManager &)> &C) { + FunctionAnalysisRegistrationCallbacks.push_back(C); + } + void registerAnalysisRegistrationCallback( + const std::function<void(LoopAnalysisManager &)> &C) { + LoopAnalysisRegistrationCallbacks.push_back(C); + } + void registerAnalysisRegistrationCallback( + const std::function<void(ModuleAnalysisManager &)> &C) { + ModuleAnalysisRegistrationCallbacks.push_back(C); + } + /// @}} + + /// {{@ Register pipeline parsing callbacks with this pass builder instance. + /// Using these callbacks, callers can parse both a single pass name, as well + /// as entire sub-pipelines, and populate the PassManager instance + /// accordingly. + void registerPipelineParsingCallback( + const std::function<bool(StringRef Name, CGSCCPassManager &, + ArrayRef<PipelineElement>)> &C) { + CGSCCPipelineParsingCallbacks.push_back(C); + } + void registerPipelineParsingCallback( + const std::function<bool(StringRef Name, FunctionPassManager &, + ArrayRef<PipelineElement>)> &C) { + FunctionPipelineParsingCallbacks.push_back(C); + } + void registerPipelineParsingCallback( + const std::function<bool(StringRef Name, LoopPassManager &, + ArrayRef<PipelineElement>)> &C) { + LoopPipelineParsingCallbacks.push_back(C); + } + void registerPipelineParsingCallback( + const std::function<bool(StringRef Name, ModulePassManager &, + ArrayRef<PipelineElement>)> &C) { + ModulePipelineParsingCallbacks.push_back(C); + } + /// @}} + + /// Register a callback for a top-level pipeline entry. + /// + /// If the PassManager type is not given at the top level of the pipeline + /// text, this Callback should be used to determine the appropriate stack of + /// PassManagers and populate the passed ModulePassManager. + void registerParseTopLevelPipelineCallback( + const std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>)> + &C); + + /// Add PGOInstrumenation passes for O0 only. + void addPGOInstrPassesForO0(ModulePassManager &MPM, bool RunProfileGen, + bool IsCS, std::string ProfileFile, + std::string ProfileRemappingFile); + + /// Returns PIC. External libraries can use this to register pass + /// instrumentation callbacks. + PassInstrumentationCallbacks *getPassInstrumentationCallbacks() const { + return PIC; + } + +private: + // O1 pass pipeline + FunctionPassManager + buildO1FunctionSimplificationPipeline(OptimizationLevel Level, + ThinOrFullLTOPhase Phase); + + void addRequiredLTOPreLinkPasses(ModulePassManager &MPM); + + void addVectorPasses(OptimizationLevel Level, FunctionPassManager &FPM, + bool IsFullLTO); + + static Optional<std::vector<PipelineElement>> + parsePipelineText(StringRef Text); + + Error parseModulePass(ModulePassManager &MPM, const PipelineElement &E); + Error parseCGSCCPass(CGSCCPassManager &CGPM, const PipelineElement &E); + Error parseFunctionPass(FunctionPassManager &FPM, const PipelineElement &E); + Error parseLoopPass(LoopPassManager &LPM, const PipelineElement &E); + bool parseAAPassName(AAManager &AA, StringRef Name); + + Error parseLoopPassPipeline(LoopPassManager &LPM, + ArrayRef<PipelineElement> Pipeline); + Error parseFunctionPassPipeline(FunctionPassManager &FPM, + ArrayRef<PipelineElement> Pipeline); + Error parseCGSCCPassPipeline(CGSCCPassManager &CGPM, + ArrayRef<PipelineElement> Pipeline); + Error parseModulePassPipeline(ModulePassManager &MPM, + ArrayRef<PipelineElement> Pipeline); + + void addPGOInstrPasses(ModulePassManager &MPM, OptimizationLevel Level, + bool RunProfileGen, bool IsCS, std::string ProfileFile, + std::string ProfileRemappingFile); + void invokePeepholeEPCallbacks(FunctionPassManager &, OptimizationLevel); + + // Extension Point callbacks + SmallVector<std::function<void(FunctionPassManager &, OptimizationLevel)>, 2> + PeepholeEPCallbacks; + SmallVector<std::function<void(LoopPassManager &, OptimizationLevel)>, 2> + LateLoopOptimizationsEPCallbacks; + SmallVector<std::function<void(LoopPassManager &, OptimizationLevel)>, 2> + LoopOptimizerEndEPCallbacks; + SmallVector<std::function<void(FunctionPassManager &, OptimizationLevel)>, 2> + ScalarOptimizerLateEPCallbacks; + SmallVector<std::function<void(CGSCCPassManager &, OptimizationLevel)>, 2> + CGSCCOptimizerLateEPCallbacks; + SmallVector<std::function<void(FunctionPassManager &, OptimizationLevel)>, 2> + VectorizerStartEPCallbacks; + SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2> + OptimizerLastEPCallbacks; + // Module callbacks + SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2> + PipelineStartEPCallbacks; + SmallVector<std::function<void(ModulePassManager &, OptimizationLevel)>, 2> + PipelineEarlySimplificationEPCallbacks; + + SmallVector<std::function<void(ModuleAnalysisManager &)>, 2> + ModuleAnalysisRegistrationCallbacks; + SmallVector<std::function<bool(StringRef, ModulePassManager &, + ArrayRef<PipelineElement>)>, + 2> + ModulePipelineParsingCallbacks; + SmallVector< + std::function<bool(ModulePassManager &, ArrayRef<PipelineElement>)>, 2> + TopLevelPipelineParsingCallbacks; + // CGSCC callbacks + SmallVector<std::function<void(CGSCCAnalysisManager &)>, 2> + CGSCCAnalysisRegistrationCallbacks; + SmallVector<std::function<bool(StringRef, CGSCCPassManager &, + ArrayRef<PipelineElement>)>, + 2> + CGSCCPipelineParsingCallbacks; + // Function callbacks + SmallVector<std::function<void(FunctionAnalysisManager &)>, 2> + FunctionAnalysisRegistrationCallbacks; + SmallVector<std::function<bool(StringRef, FunctionPassManager &, + ArrayRef<PipelineElement>)>, + 2> + FunctionPipelineParsingCallbacks; + // Loop callbacks + SmallVector<std::function<void(LoopAnalysisManager &)>, 2> + LoopAnalysisRegistrationCallbacks; + SmallVector<std::function<bool(StringRef, LoopPassManager &, + ArrayRef<PipelineElement>)>, + 2> + LoopPipelineParsingCallbacks; + // AA callbacks + SmallVector<std::function<bool(StringRef Name, AAManager &AA)>, 2> + AAParsingCallbacks; +}; + +/// This utility template takes care of adding require<> and invalidate<> +/// passes for an analysis to a given \c PassManager. It is intended to be used +/// during parsing of a pass pipeline when parsing a single PipelineName. +/// When registering a new function analysis FancyAnalysis with the pass +/// pipeline name "fancy-analysis", a matching ParsePipelineCallback could look +/// like this: +/// +/// static bool parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM, +/// ArrayRef<PipelineElement> P) { +/// if (parseAnalysisUtilityPasses<FancyAnalysis>("fancy-analysis", Name, +/// FPM)) +/// return true; +/// return false; +/// } +template <typename AnalysisT, typename IRUnitT, typename AnalysisManagerT, + typename... ExtraArgTs> +bool parseAnalysisUtilityPasses( + StringRef AnalysisName, StringRef PipelineName, + PassManager<IRUnitT, AnalysisManagerT, ExtraArgTs...> &PM) { + if (!PipelineName.endswith(">")) + return false; + // See if this is an invalidate<> pass name + if (PipelineName.startswith("invalidate<")) { + PipelineName = PipelineName.substr(11, PipelineName.size() - 12); + if (PipelineName != AnalysisName) + return false; + PM.addPass(InvalidateAnalysisPass<AnalysisT>()); + return true; + } + + // See if this is a require<> pass name + if (PipelineName.startswith("require<")) { + PipelineName = PipelineName.substr(8, PipelineName.size() - 9); + if (PipelineName != AnalysisName) + return false; + PM.addPass(RequireAnalysisPass<AnalysisT, IRUnitT, AnalysisManagerT, + ExtraArgTs...>()); + return true; + } + + return false; +} +} + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm14/include/llvm/Passes/PassPlugin.h b/contrib/libs/llvm14/include/llvm/Passes/PassPlugin.h new file mode 100644 index 0000000000..29b4691d37 --- /dev/null +++ b/contrib/libs/llvm14/include/llvm/Passes/PassPlugin.h @@ -0,0 +1,124 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- llvm/Passes/PassPlugin.h - Public Plugin API -----------------------===// +// +// 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 defines the public entry point for new-PM pass plugins. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_PASSPLUGIN_H +#define LLVM_PASSES_PASSPLUGIN_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Error.h" +#include <cstdint> +#include <string> + +namespace llvm { +class PassBuilder; + +/// \macro LLVM_PLUGIN_API_VERSION +/// Identifies the API version understood by this plugin. +/// +/// When a plugin is loaded, the driver will check it's supported plugin version +/// against that of the plugin. A mismatch is an error. The supported version +/// will be incremented for ABI-breaking changes to the \c PassPluginLibraryInfo +/// struct, i.e. when callbacks are added, removed, or reordered. +#define LLVM_PLUGIN_API_VERSION 1 + +extern "C" { +/// Information about the plugin required to load its passes +/// +/// This struct defines the core interface for pass plugins and is supposed to +/// be filled out by plugin implementors. LLVM-side users of a plugin are +/// expected to use the \c PassPlugin class below to interface with it. +struct PassPluginLibraryInfo { + /// The API version understood by this plugin, usually \c + /// LLVM_PLUGIN_API_VERSION + uint32_t APIVersion; + /// A meaningful name of the plugin. + const char *PluginName; + /// The version of the plugin. + const char *PluginVersion; + + /// The callback for registering plugin passes with a \c PassBuilder + /// instance + void (*RegisterPassBuilderCallbacks)(PassBuilder &); +}; +} + +/// A loaded pass plugin. +/// +/// An instance of this class wraps a loaded pass plugin and gives access to +/// its interface defined by the \c PassPluginLibraryInfo it exposes. +class PassPlugin { +public: + /// Attempts to load a pass plugin from a given file. + /// + /// \returns Returns an error if either the library cannot be found or loaded, + /// there is no public entry point, or the plugin implements the wrong API + /// version. + static Expected<PassPlugin> Load(const std::string &Filename); + + /// Get the filename of the loaded plugin. + StringRef getFilename() const { return Filename; } + + /// Get the plugin name + StringRef getPluginName() const { return Info.PluginName; } + + /// Get the plugin version + StringRef getPluginVersion() const { return Info.PluginVersion; } + + /// Get the plugin API version + uint32_t getAPIVersion() const { return Info.APIVersion; } + + /// Invoke the PassBuilder callback registration + void registerPassBuilderCallbacks(PassBuilder &PB) const { + Info.RegisterPassBuilderCallbacks(PB); + } + +private: + PassPlugin(const std::string &Filename, const sys::DynamicLibrary &Library) + : Filename(Filename), Library(Library), Info() {} + + std::string Filename; + sys::DynamicLibrary Library; + PassPluginLibraryInfo Info; +}; +} + +/// The public entry point for a pass plugin. +/// +/// When a plugin is loaded by the driver, it will call this entry point to +/// obtain information about this plugin and about how to register its passes. +/// This function needs to be implemented by the plugin, see the example below: +/// +/// ``` +/// extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +/// llvmGetPassPluginInfo() { +/// return { +/// LLVM_PLUGIN_API_VERSION, "MyPlugin", "v0.1", [](PassBuilder &PB) { ... } +/// }; +/// } +/// ``` +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo(); + +#endif /* LLVM_PASSES_PASSPLUGIN_H */ + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm14/include/llvm/Passes/StandardInstrumentations.h b/contrib/libs/llvm14/include/llvm/Passes/StandardInstrumentations.h new file mode 100644 index 0000000000..dd56fe8764 --- /dev/null +++ b/contrib/libs/llvm14/include/llvm/Passes/StandardInstrumentations.h @@ -0,0 +1,546 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- StandardInstrumentations.h ------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header defines a class that provides bookkeeping for all standard +/// (i.e in-tree) pass instrumentations. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSES_STANDARDINSTRUMENTATIONS_H +#define LLVM_PASSES_STANDARDINSTRUMENTATIONS_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/OptBisect.h" +#include "llvm/IR/PassTimingInfo.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/IPO/SampleProfileProbe.h" + +#include <string> +#include <utility> + +namespace llvm { + +class Module; +class Function; +class PassInstrumentationCallbacks; + +/// Instrumentation to print IR before/after passes. +/// +/// Needs state to be able to print module after pass that invalidates IR unit +/// (typically Loop or SCC). +class PrintIRInstrumentation { +public: + ~PrintIRInstrumentation(); + + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +private: + void printBeforePass(StringRef PassID, Any IR); + void printAfterPass(StringRef PassID, Any IR); + void printAfterPassInvalidated(StringRef PassID); + + bool shouldPrintBeforePass(StringRef PassID); + bool shouldPrintAfterPass(StringRef PassID); + + using PrintModuleDesc = std::tuple<const Module *, std::string, StringRef>; + + void pushModuleDesc(StringRef PassID, Any IR); + PrintModuleDesc popModuleDesc(StringRef PassID); + + PassInstrumentationCallbacks *PIC; + /// Stack of Module description, enough to print the module after a given + /// pass. + SmallVector<PrintModuleDesc, 2> ModuleDescStack; +}; + +class OptNoneInstrumentation { +public: + OptNoneInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +private: + bool DebugLogging; + bool shouldRun(StringRef PassID, Any IR); +}; + +class OptBisectInstrumentation { +public: + OptBisectInstrumentation() = default; + void registerCallbacks(PassInstrumentationCallbacks &PIC); +}; + +struct PrintPassOptions { + /// Print adaptors and pass managers. + bool Verbose = false; + /// Don't print information for analyses. + bool SkipAnalyses = false; + /// Indent based on hierarchy. + bool Indent = false; +}; + +// Debug logging for transformation and analysis passes. +class PrintPassInstrumentation { + raw_ostream &print(); + +public: + PrintPassInstrumentation(bool Enabled, PrintPassOptions Opts) + : Enabled(Enabled), Opts(Opts) {} + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +private: + bool Enabled; + PrintPassOptions Opts; + int Indent = 0; +}; + +class PreservedCFGCheckerInstrumentation { +public: + // Keeps sticky poisoned flag for the given basic block once it has been + // deleted or RAUWed. + struct BBGuard final : public CallbackVH { + BBGuard(const BasicBlock *BB) : CallbackVH(BB) {} + void deleted() override { CallbackVH::deleted(); } + void allUsesReplacedWith(Value *) override { CallbackVH::deleted(); } + bool isPoisoned() const { return !getValPtr(); } + }; + + // CFG is a map BB -> {(Succ, Multiplicity)}, where BB is a non-leaf basic + // block, {(Succ, Multiplicity)} set of all pairs of the block's successors + // and the multiplicity of the edge (BB->Succ). As the mapped sets are + // unordered the order of successors is not tracked by the CFG. In other words + // this allows basic block successors to be swapped by a pass without + // reporting a CFG change. CFG can be guarded by basic block tracking pointers + // in the Graph (BBGuard). That is if any of the block is deleted or RAUWed + // then the CFG is treated poisoned and no block pointer of the Graph is used. + struct CFG { + Optional<DenseMap<intptr_t, BBGuard>> BBGuards; + DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph; + + CFG(const Function *F, bool TrackBBLifetime); + + bool operator==(const CFG &G) const { + return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph; + } + + bool isPoisoned() const { + return BBGuards && + std::any_of(BBGuards->begin(), BBGuards->end(), + [](const auto &BB) { return BB.second.isPoisoned(); }); + } + + static void printDiff(raw_ostream &out, const CFG &Before, + const CFG &After); + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); + }; + +#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS + SmallVector<StringRef, 8> PassStack; +#endif + + static cl::opt<bool> VerifyPreservedCFG; + void registerCallbacks(PassInstrumentationCallbacks &PIC, + FunctionAnalysisManager &FAM); +}; + +// Base class for classes that report changes to the IR. +// It presents an interface for such classes and provides calls +// on various events as the new pass manager transforms the IR. +// It also provides filtering of information based on hidden options +// specifying which functions are interesting. +// Calls are made for the following events/queries: +// 1. The initial IR processed. +// 2. To get the representation of the IR (of type \p T). +// 3. When a pass does not change the IR. +// 4. When a pass changes the IR (given both before and after representations +// of type \p T). +// 5. When an IR is invalidated. +// 6. When a pass is run on an IR that is not interesting (based on options). +// 7. When a pass is ignored (pass manager or adapter pass). +// 8. To compare two IR representations (of type \p T). +template <typename IRUnitT> class ChangeReporter { +protected: + ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {} + +public: + virtual ~ChangeReporter(); + + // Determine if this pass/IR is interesting and if so, save the IR + // otherwise it is left on the stack without data. + void saveIRBeforePass(Any IR, StringRef PassID); + // Compare the IR from before the pass after the pass. + void handleIRAfterPass(Any IR, StringRef PassID); + // Handle the situation where a pass is invalidated. + void handleInvalidatedPass(StringRef PassID); + +protected: + // Register required callbacks. + void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC); + + // Return true when this is a defined function for which printing + // of changes is desired. + bool isInterestingFunction(const Function &F); + + // Return true when this is a pass for which printing of changes is desired. + bool isInterestingPass(StringRef PassID); + + // Return true when this is a pass on IR for which printing + // of changes is desired. + bool isInteresting(Any IR, StringRef PassID); + + // Called on the first IR processed. + virtual void handleInitialIR(Any IR) = 0; + // Called before and after a pass to get the representation of the IR. + virtual void generateIRRepresentation(Any IR, StringRef PassID, + IRUnitT &Output) = 0; + // Called when the pass is not iteresting. + virtual void omitAfter(StringRef PassID, std::string &Name) = 0; + // Called when an interesting IR has changed. + virtual void handleAfter(StringRef PassID, std::string &Name, + const IRUnitT &Before, const IRUnitT &After, + Any) = 0; + // Called when an interesting pass is invalidated. + virtual void handleInvalidated(StringRef PassID) = 0; + // Called when the IR or pass is not interesting. + virtual void handleFiltered(StringRef PassID, std::string &Name) = 0; + // Called when an ignored pass is encountered. + virtual void handleIgnored(StringRef PassID, std::string &Name) = 0; + + // Stack of IRs before passes. + std::vector<IRUnitT> BeforeStack; + // Is this the first IR seen? + bool InitialIR = true; + + // Run in verbose mode, printing everything? + const bool VerboseMode; +}; + +// An abstract template base class that handles printing banners and +// reporting when things have not changed or are filtered out. +template <typename IRUnitT> +class TextChangeReporter : public ChangeReporter<IRUnitT> { +protected: + TextChangeReporter(bool Verbose); + + // Print a module dump of the first IR that is changed. + void handleInitialIR(Any IR) override; + // Report that the IR was omitted because it did not change. + void omitAfter(StringRef PassID, std::string &Name) override; + // Report that the pass was invalidated. + void handleInvalidated(StringRef PassID) override; + // Report that the IR was filtered out. + void handleFiltered(StringRef PassID, std::string &Name) override; + // Report that the pass was ignored. + void handleIgnored(StringRef PassID, std::string &Name) override; + // Make substitutions in \p S suitable for reporting changes + // after the pass and then print it. + + raw_ostream &Out; +}; + +// A change printer based on the string representation of the IR as created +// by unwrapAndPrint. The string representation is stored in a std::string +// to preserve it as the IR changes in each pass. Note that the banner is +// included in this representation but it is massaged before reporting. +class IRChangedPrinter : public TextChangeReporter<std::string> { +public: + IRChangedPrinter(bool VerboseMode) + : TextChangeReporter<std::string>(VerboseMode) {} + ~IRChangedPrinter() override; + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +protected: + // Called before and after a pass to get the representation of the IR. + void generateIRRepresentation(Any IR, StringRef PassID, + std::string &Output) override; + // Called when an interesting IR has changed. + void handleAfter(StringRef PassID, std::string &Name, + const std::string &Before, const std::string &After, + Any) override; +}; + +// Information that needs to be saved for a basic block in order to compare +// before and after the pass to determine if it was changed by a pass. +template <typename T> class BlockDataT { +public: + BlockDataT(const BasicBlock &B) : Label(B.getName().str()), Data(B) { + raw_string_ostream SS(Body); + B.print(SS, nullptr, true, true); + } + + bool operator==(const BlockDataT &That) const { return Body == That.Body; } + bool operator!=(const BlockDataT &That) const { return Body != That.Body; } + + // Return the label of the represented basic block. + StringRef getLabel() const { return Label; } + // Return the string representation of the basic block. + StringRef getBody() const { return Body; } + + // Return the associated data + const T &getData() const { return Data; } + +protected: + std::string Label; + std::string Body; + + // Extra data associated with a basic block + T Data; +}; + +template <typename T> class OrderedChangedData { +public: + // Return the names in the order they were saved + std::vector<std::string> &getOrder() { return Order; } + const std::vector<std::string> &getOrder() const { return Order; } + + // Return a map of names to saved representations + StringMap<T> &getData() { return Data; } + const StringMap<T> &getData() const { return Data; } + + bool operator==(const OrderedChangedData<T> &That) const { + return Data == That.getData(); + } + + // Call the lambda \p HandlePair on each corresponding pair of data from + // \p Before and \p After. The order is based on the order in \p After + // with ones that are only in \p Before interspersed based on where they + // occur in \p Before. This is used to present the output in an order + // based on how the data is ordered in LLVM. + static void report(const OrderedChangedData &Before, + const OrderedChangedData &After, + function_ref<void(const T *, const T *)> HandlePair); + +protected: + std::vector<std::string> Order; + StringMap<T> Data; +}; + +// Do not need extra information for patch-style change reporter. +class EmptyData { +public: + EmptyData(const BasicBlock &) {} +}; + +// The data saved for comparing functions. +template <typename T> +class FuncDataT : public OrderedChangedData<BlockDataT<T>> { +public: + FuncDataT(std::string S) : EntryBlockName(S) {} + + // Return the name of the entry block + std::string getEntryBlockName() const { return EntryBlockName; } + +protected: + std::string EntryBlockName; +}; + +// The data saved for comparing IRs. +template <typename T> +class IRDataT : public OrderedChangedData<FuncDataT<T>> {}; + +// Abstract template base class for a class that compares two IRs. The +// class is created with the 2 IRs to compare and then compare is called. +// The static function analyzeIR is used to build up the IR representation. +template <typename T> class IRComparer { +public: + IRComparer(const IRDataT<T> &Before, const IRDataT<T> &After) + : Before(Before), After(After) {} + + // Compare the 2 IRs. \p handleFunctionCompare is called to handle the + // compare of a function. When \p InModule is set, + // this function is being handled as part of comparing a module. + void compare( + bool CompareModule, + std::function<void(bool InModule, unsigned Minor, + const FuncDataT<T> &Before, const FuncDataT<T> &After)> + CompareFunc); + + // Analyze \p IR and build the IR representation in \p Data. + static void analyzeIR(Any IR, IRDataT<T> &Data); + +protected: + // Generate the data for \p F into \p Data. + static bool generateFunctionData(IRDataT<T> &Data, const Function &F); + + const IRDataT<T> &Before; + const IRDataT<T> &After; +}; + +// A change printer that prints out in-line differences in the basic +// blocks. It uses an InlineComparer to do the comparison so it shows +// the differences prefixed with '-' and '+' for code that is removed +// and added, respectively. Changes to the IR that do not affect basic +// blocks are not reported as having changed the IR. The option +// -print-module-scope does not affect this change reporter. +class InLineChangePrinter : public TextChangeReporter<IRDataT<EmptyData>> { +public: + InLineChangePrinter(bool VerboseMode, bool ColourMode) + : TextChangeReporter<IRDataT<EmptyData>>(VerboseMode), + UseColour(ColourMode) {} + ~InLineChangePrinter() override; + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +protected: + // Create a representation of the IR. + virtual void generateIRRepresentation(Any IR, StringRef PassID, + IRDataT<EmptyData> &Output) override; + + // Called when an interesting IR has changed. + virtual void handleAfter(StringRef PassID, std::string &Name, + const IRDataT<EmptyData> &Before, + const IRDataT<EmptyData> &After, Any) override; + + void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, + StringRef Divider, bool InModule, unsigned Minor, + const FuncDataT<EmptyData> &Before, + const FuncDataT<EmptyData> &After); + + bool UseColour; +}; + +class VerifyInstrumentation { + bool DebugLogging; + +public: + VerifyInstrumentation(bool DebugLogging) : DebugLogging(DebugLogging) {} + void registerCallbacks(PassInstrumentationCallbacks &PIC); +}; + +// Class that holds transitions between basic blocks. The transitions +// are contained in a map of values to names of basic blocks. +class DCData { +public: + // Fill the map with the transitions from basic block \p B. + DCData(const BasicBlock &B); + + // Return an iterator to the names of the successor blocks. + StringMap<std::string>::const_iterator begin() const { + return Successors.begin(); + } + StringMap<std::string>::const_iterator end() const { + return Successors.end(); + } + + // Return the label of the basic block reached on a transition on \p S. + StringRef getSuccessorLabel(StringRef S) const { + assert(Successors.count(S) == 1 && "Expected to find successor."); + return Successors.find(S)->getValue(); + } + +protected: + // Add a transition to \p Succ on \p Label + void addSuccessorLabel(StringRef Succ, StringRef Label) { + std::pair<std::string, std::string> SS{Succ.str(), Label.str()}; + Successors.insert(SS); + } + + StringMap<std::string> Successors; +}; + +// A change reporter that builds a website with links to pdf files showing +// dot control flow graphs with changed instructions shown in colour. +class DotCfgChangeReporter : public ChangeReporter<IRDataT<DCData>> { +public: + DotCfgChangeReporter(bool Verbose); + ~DotCfgChangeReporter() override; + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +protected: + // Initialize the HTML file and output the header. + bool initializeHTML(); + + // Called on the first IR processed. + void handleInitialIR(Any IR) override; + // Called before and after a pass to get the representation of the IR. + void generateIRRepresentation(Any IR, StringRef PassID, + IRDataT<DCData> &Output) override; + // Called when the pass is not iteresting. + void omitAfter(StringRef PassID, std::string &Name) override; + // Called when an interesting IR has changed. + void handleAfter(StringRef PassID, std::string &Name, + const IRDataT<DCData> &Before, const IRDataT<DCData> &After, + Any) override; + // Called when an interesting pass is invalidated. + void handleInvalidated(StringRef PassID) override; + // Called when the IR or pass is not interesting. + void handleFiltered(StringRef PassID, std::string &Name) override; + // Called when an ignored pass is encountered. + void handleIgnored(StringRef PassID, std::string &Name) override; + + // Generate the pdf file into \p Dir / \p PDFFileName using \p DotFile as + // input and return the html <a> tag with \Text as the content. + static std::string genHTML(StringRef Text, StringRef DotFile, + StringRef PDFFileName); + + void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, + StringRef Divider, bool InModule, unsigned Minor, + const FuncDataT<DCData> &Before, + const FuncDataT<DCData> &After); + + unsigned N = 0; + std::unique_ptr<raw_fd_ostream> HTML; +}; + +/// This class provides an interface to register all the standard pass +/// instrumentations and manages their state (if any). +class StandardInstrumentations { + PrintIRInstrumentation PrintIR; + PrintPassInstrumentation PrintPass; + TimePassesHandler TimePasses; + OptNoneInstrumentation OptNone; + OptBisectInstrumentation OptBisect; + PreservedCFGCheckerInstrumentation PreservedCFGChecker; + IRChangedPrinter PrintChangedIR; + PseudoProbeVerifier PseudoProbeVerification; + InLineChangePrinter PrintChangedDiff; + DotCfgChangeReporter WebsiteChangeReporter; + VerifyInstrumentation Verify; + + bool VerifyEach; + +public: + StandardInstrumentations(bool DebugLogging, bool VerifyEach = false, + PrintPassOptions PrintPassOpts = PrintPassOptions()); + + // Register all the standard instrumentation callbacks. If \p FAM is nullptr + // then PreservedCFGChecker is not enabled. + void registerCallbacks(PassInstrumentationCallbacks &PIC, + FunctionAnalysisManager *FAM = nullptr); + + TimePassesHandler &getTimePasses() { return TimePasses; } +}; + +extern template class ChangeReporter<std::string>; +extern template class TextChangeReporter<std::string>; + +extern template class BlockDataT<EmptyData>; +extern template class FuncDataT<EmptyData>; +extern template class IRDataT<EmptyData>; +extern template class ChangeReporter<IRDataT<EmptyData>>; +extern template class TextChangeReporter<IRDataT<EmptyData>>; +extern template class IRComparer<EmptyData>; + +} // namespace llvm + +#endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif |