diff options
Diffstat (limited to 'llvm/include/llvm/Passes/StandardInstrumentations.h')
-rw-r--r-- | llvm/include/llvm/Passes/StandardInstrumentations.h | 201 |
1 files changed, 178 insertions, 23 deletions
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h index 795a980878e2..2f573585e766 100644 --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -15,6 +15,7 @@ #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" @@ -22,6 +23,7 @@ #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> @@ -59,7 +61,6 @@ private: /// Stack of Module description, enough to print the module after a given /// pass. SmallVector<PrintModuleDesc, 2> ModuleDescStack; - bool StoreModuleDesc = false; }; class OptNoneInstrumentation { @@ -78,18 +79,41 @@ public: 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 DebugLogging) : DebugLogging(DebugLogging) {} + PrintPassInstrumentation(bool Enabled, PrintPassOptions Opts) + : Enabled(Enabled), Opts(Opts) {} void registerCallbacks(PassInstrumentationCallbacks &PIC); private: - bool DebugLogging; + bool Enabled; + PrintPassOptions Opts; + int Indent = 0; }; class PreservedCFGCheckerInstrumentation { -private: +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 @@ -99,40 +123,34 @@ private: // 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 { - 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(); } - }; - Optional<DenseMap<intptr_t, BBGuard>> BBGuards; DenseMap<const BasicBlock *, DenseMap<const BasicBlock *, unsigned>> Graph; - CFG(const Function *F, bool TrackBBLifetime = false); + CFG(const Function *F, bool TrackBBLifetime); bool operator==(const CFG &G) const { return !isPoisoned() && !G.isPoisoned() && Graph == G.Graph; } bool isPoisoned() const { - if (BBGuards) - for (auto &BB : *BBGuards) { - if (BB.second.isPoisoned()) - return true; - } - return false; + 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 &); }; - SmallVector<std::pair<StringRef, Optional<CFG>>, 8> GraphStackBefore; +#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS + SmallVector<StringRef, 8> PassStack; +#endif -public: static cl::opt<bool> VerifyPreservedCFG; - void registerCallbacks(PassInstrumentationCallbacks &PIC); + void registerCallbacks(PassInstrumentationCallbacks &PIC, + FunctionAnalysisManager &FAM); }; // Base class for classes that report changes to the IR. @@ -255,6 +273,134 @@ protected: bool same(const std::string &Before, const std::string &After) override; }; +// The following classes hold a representation of the IR for a change +// reporter that uses string comparisons of the basic blocks +// that are created using print (ie, similar to dump()). +// These classes respect the filtering of passes and functions using +// -filter-passes and -filter-print-funcs. +// +// 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. +class ChangedBlockData { +public: + ChangedBlockData(const BasicBlock &B); + + bool operator==(const ChangedBlockData &That) const { + return Body == That.Body; + } + bool operator!=(const ChangedBlockData &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; } + +protected: + std::string Label; + std::string Body; +}; + +template <typename IRData> 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<IRData> &getData() { return Data; } + const StringMap<IRData> &getData() const { return Data; } + + bool operator==(const OrderedChangedData<IRData> &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 IRData *, const IRData *)> HandlePair); + +protected: + std::vector<std::string> Order; + StringMap<IRData> Data; +}; + +// The data saved for comparing functions. +using ChangedFuncData = OrderedChangedData<ChangedBlockData>; + +// A map of names to the saved data. +using ChangedIRData = OrderedChangedData<ChangedFuncData>; + +// A class that compares two IRs and does a diff between them. The +// added lines are prefixed with a '+', the removed lines are prefixed +// with a '-' and unchanged lines are prefixed with a space (to have +// things line up). +class ChangedIRComparer { +public: + ChangedIRComparer(raw_ostream &OS, const ChangedIRData &Before, + const ChangedIRData &After, bool ColourMode) + : Before(Before), After(After), Out(OS), UseColour(ColourMode) {} + + // Compare the 2 IRs. + void compare(Any IR, StringRef Prefix, StringRef PassID, StringRef Name); + + // Analyze \p IR and build the IR representation in \p Data. + static void analyzeIR(Any IR, ChangedIRData &Data); + +protected: + // Return the module when that is the appropriate level of + // comparison for \p IR. + static const Module *getModuleForComparison(Any IR); + + // Generate the data for \p F into \p Data. + static bool generateFunctionData(ChangedIRData &Data, const Function &F); + + // 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 handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, + bool InModule, const ChangedFuncData &Before, + const ChangedFuncData &After); + + const ChangedIRData &Before; + const ChangedIRData &After; + raw_ostream &Out; + bool UseColour; +}; + +// 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<ChangedIRData> { +public: + InLineChangePrinter(bool VerboseMode, bool ColourMode) + : TextChangeReporter<ChangedIRData>(VerboseMode), UseColour(ColourMode) {} + ~InLineChangePrinter() override; + void registerCallbacks(PassInstrumentationCallbacks &PIC); + +protected: + // Create a representation of the IR. + virtual void generateIRRepresentation(Any IR, StringRef PassID, + ChangedIRData &Output) override; + + // Called when an interesting IR has changed. + virtual void handleAfter(StringRef PassID, std::string &Name, + const ChangedIRData &Before, + const ChangedIRData &After, Any) override; + // Called to compare the before and after representations of the IR. + virtual bool same(const ChangedIRData &Before, + const ChangedIRData &After) override; + + bool UseColour; +}; + class VerifyInstrumentation { bool DebugLogging; @@ -273,14 +419,20 @@ class StandardInstrumentations { OptBisectInstrumentation OptBisect; PreservedCFGCheckerInstrumentation PreservedCFGChecker; IRChangedPrinter PrintChangedIR; + PseudoProbeVerifier PseudoProbeVerification; + InLineChangePrinter PrintChangedDiff; VerifyInstrumentation Verify; bool VerifyEach; public: - StandardInstrumentations(bool DebugLogging, bool VerifyEach = false); + StandardInstrumentations(bool DebugLogging, bool VerifyEach = false, + PrintPassOptions PrintPassOpts = PrintPassOptions()); - void registerCallbacks(PassInstrumentationCallbacks &PIC); + // 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; } }; @@ -288,6 +440,9 @@ public: extern template class ChangeReporter<std::string>; extern template class TextChangeReporter<std::string>; +extern template class ChangeReporter<ChangedIRData>; +extern template class TextChangeReporter<ChangedIRData>; + } // namespace llvm #endif |