aboutsummaryrefslogtreecommitdiff
path: root/llvm/include/llvm/Passes/StandardInstrumentations.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/include/llvm/Passes/StandardInstrumentations.h')
-rw-r--r--llvm/include/llvm/Passes/StandardInstrumentations.h201
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