Revert "Add new hidden option -print-changed which only reports changes to IR"

This reverts commit 7bc9924cb2fbd9f3ae53577607822ace267a04e6 due to
failure caused by missing a space between trailing >>, required by some
versions of C++:wq.
This commit is contained in:
Jamie Schmeiser 2020-09-03 18:24:00 +00:00 committed by Anh Tuyen Tran
parent 63a262cd97
commit b707c16b9c
4 changed files with 2 additions and 424 deletions

View File

@ -25,7 +25,6 @@
namespace llvm {
class Function;
class Module;
/// Instrumentation to print IR before/after passes.
@ -74,98 +73,6 @@ private:
bool DebugLogging;
};
// Base class for classes that report changes to the IR.
// It presents an interface for such classes and provides callbacks
// 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.
// Callbacks 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 T> class ChangePrinter {
protected:
ChangePrinter(
std::function<void(Any IR)> HandleInitialIRFunc,
std::function<void(Any IR, StringRef PassID, T &Output)>
GenerateIRRepresentationFunc,
std::function<void(StringRef PassID, std::string &Name)> OmitAfterFunc,
std::function<void(StringRef PassID, std::string &Name, const T &Before,
const T &After, Any IR)>
HandleAfterFunc,
std::function<void(StringRef PassID)> HandleInvalidatedFunc,
std::function<void(StringRef PassID, std::string &Name)>
HandleFilteredFunc,
std::function<void(StringRef PassID, std::string &Name)>
HandleIgnoredFunc,
std::function<bool(const T &Before, const T &After)> SameFunc)
: HandleInitialIR(HandleInitialIRFunc),
GenerateIRRepresentation(GenerateIRRepresentationFunc),
OmitAfter(OmitAfterFunc), HandleAfter(HandleAfterFunc),
HandleInvalidated(HandleInvalidatedFunc),
HandleFiltered(HandleFilteredFunc), HandleIgnored(HandleIgnoredFunc),
Same(SameFunc), InitialIR(true) {}
public:
// Not virtual as classes are expected to be referenced as derived classes.
~ChangePrinter() {
assert(BeforeStack.empty() && "Problem with Change Printer stack.");
}
// 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);
private:
// callback on the first IR processed
std::function<void(Any IR)> HandleInitialIR;
// callback before and after a pass to get the representation of the IR
std::function<void(Any IR, StringRef PassID, T &Output)>
GenerateIRRepresentation;
// callback when the pass is not iteresting
std::function<void(StringRef PassID, std::string &Name)> OmitAfter;
// callback when interesting IR has changed
std::function<void(StringRef PassID, std::string &Name, const T &Before,
const T &After, Any)>
HandleAfter;
// callback when an interesting pass is invalidated
std::function<void(StringRef PassID)> HandleInvalidated;
// callback when the IR or pass is not interesting
std::function<void(StringRef PassID, std::string &Name)> HandleFiltered;
// callback when an ignored pass is encountered
std::function<void(StringRef PassID, std::string &Name)> HandleIgnored;
// callback to compare the before and after representations of the IR
std::function<bool(const T &Before, const T &After)> Same;
// stack of IRs before passes
std::vector<T> BeforeStack;
// Is this the first IR seen?
bool InitialIR;
};
// 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 IRChangePrinter : public ChangePrinter<std::string> {
public:
IRChangePrinter();
void registerCallbacks(PassInstrumentationCallbacks &PIC);
protected:
raw_ostream &Out;
};
/// This class provides an interface to register all the standard pass
/// instrumentations and manages their state (if any).
class StandardInstrumentations {
@ -173,7 +80,6 @@ class StandardInstrumentations {
PrintPassInstrumentation PrintPass;
TimePassesHandler TimePasses;
OptNoneInstrumentation OptNone;
IRChangePrinter PrintChangedIR;
public:
StandardInstrumentations(bool DebugLogging) : PrintPass(DebugLogging) {}

View File

@ -87,14 +87,14 @@ static cl::opt<bool> PrintAfterAll("print-after-all",
static cl::opt<bool>
PrintModuleScope("print-module-scope",
cl::desc("When printing IR for print-[before|after]{-all} "
"and change reporters always print a module IR"),
"always print a module IR"),
cl::init(false), cl::Hidden);
static cl::list<std::string>
PrintFuncsList("filter-print-funcs", cl::value_desc("function names"),
cl::desc("Only print IR for functions whose name "
"match this for all print-[before|after][-all] "
"and change reporter options"),
"options"),
cl::CommaSeparated, cl::Hidden);
/// This is a helper to determine whether to print IR before or

View File

@ -26,7 +26,6 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include <unordered_set>
#include <vector>
using namespace llvm;
@ -44,34 +43,6 @@ static cl::opt<bool>
cl::desc("Print all pass management debugging information. "
"`-debug-pass-manager` must also be specified"));
// A hidden option that prints out the IR after passes, similar to
// -print-after-all except that it only prints the IR after passes that
// change the IR. Those passes that do not make changes to the IR are
// reported as not making any changes. In addition, the initial IR is
// also reported. Other hidden options affect the output from this
// option. -filter-passes will limit the output to the named passes
// that actually change the IR and other passes are reported as filtered out.
// The specified passes will either be reported as making no changes (with
// no IR reported) or the changed IR will be reported. Also, the
// -filter-print-funcs and -print-module-scope options will do similar
// filtering based on function name, reporting changed IRs as functions(or
// modules if -print-module-scope is specified) for a particular function
// or indicating that the IR has been filtered out. The extra options
// can be combined, allowing only changed IRs for certain passes on certain
// functions to be reported in different formats, with the rest being
// reported as filtered out.
static cl::opt<bool> PrintChanged("print-changed",
cl::desc("Print changed IRs"),
cl::init(false), cl::Hidden);
// A hidden option that supports the -print-changed option. See
// the description for -print-changed for an explanation of the use
// of this option. Note that this option has no effect without -print-changed.
static cl::list<std::string>
PrintPassesList("filter-passes", cl::value_desc("pass names"),
cl::desc("Only consider IR changes for passes whose names "
"match for the print-changed option"),
cl::CommaSeparated, cl::Hidden);
namespace {
/// Extracting Module out of \p IR unit. Also fills a textual description
@ -218,197 +189,8 @@ void unwrapAndPrint(raw_ostream &OS, Any IR, StringRef Banner,
llvm_unreachable("Unknown wrapped IR type");
}
// Return true when this is a pass for which printing of changes is desired.
inline bool isIgnored(StringRef PassID) {
return PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<");
}
// Return true when this is a defined function for which printing
// of changes is desired.
inline bool isInterestingFunction(const Function &F) {
return llvm::isFunctionInPrintList(F.getName());
}
// Return true when this is a pass for which printing of changes is desired.
inline bool isInterestingPass(StringRef PassID) {
if (isIgnored(PassID))
return false;
static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(),
PrintPassesList.end());
return PrintPassNames.empty() || PrintPassNames.count(PassID.str());
}
// Return true when this is a pass on IR for which printing
// of changes is desired.
bool isInteresting(Any IR, StringRef PassID) {
if (!isInterestingPass(PassID))
return false;
if (any_isa<const Function *>(IR))
return isInterestingFunction(*any_cast<const Function *>(IR));
return true;
}
} // namespace
template <typename T>
void ChangePrinter<T>::saveIRBeforePass(Any IR, StringRef PassID) {
// Always need to place something on the stack because invalidated passes
// are not given the IR so it cannot be determined whether the pass was for
// something that was filtered out.
BeforeStack.emplace_back();
if (!isInteresting(IR, PassID))
return;
// Is this the initial IR?
if (InitialIR) {
InitialIR = false;
HandleInitialIR(IR);
}
// Save the IR representation on the stack.
auto &Data = BeforeStack.back();
GenerateIRRepresentation(IR, PassID, Data);
}
template <typename T>
void ChangePrinter<T>::handleIRAfterPass(Any IR, StringRef PassID) {
assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
std::string Name;
// unwrapModule has inconsistent handling of names for function IRs.
if (any_isa<const Function *>(IR)) {
const Function *F = any_cast<const Function *>(IR);
Name = formatv(" (function: {0})", F->getName()).str();
} else {
if (auto UM = unwrapModule(IR))
Name = UM->second;
}
if (Name == "")
Name = " (module)";
if (isIgnored(PassID))
HandleIgnored(PassID, Name);
else if (!isInteresting(IR, PassID))
HandleFiltered(PassID, Name);
else {
// Get the before rep from the stack
T &Before = BeforeStack.back();
// Create the after rep
T After;
GenerateIRRepresentation(IR, PassID, After);
// was there a change in IR?
if (Same(Before, After))
OmitAfter(PassID, Name);
else
HandleAfter(PassID, Name, Before, After, IR);
}
BeforeStack.pop_back();
}
template <typename T>
void ChangePrinter<T>::handleInvalidatedPass(StringRef PassID) {
assert(!BeforeStack.empty() && "Unexpected empty stack encountered.");
// Always flag it as invalidated as we cannot determine when
// a pass for a filtered function is invalidated since we do not
// get the IR in the callback. Also, the output is just alternate
// forms of the banner anyway.
HandleInvalidated(PassID);
BeforeStack.pop_back();
}
void handleInitialIR(Any IR, raw_ostream &Out) {
StringRef Banner("*** IR Dump At Start: ***");
unwrapAndPrint(Out, IR, Banner, true);
}
void generateOutput(Any IR, StringRef PassID, std::string &Output) {
raw_string_ostream OS(Output);
// use the after banner for all cases so it will match
SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID);
unwrapAndPrint(OS, IR, Banner, llvm::forcePrintModuleIR());
OS.str();
}
void omitAfter(StringRef PassID, std::string &Name, raw_ostream &Out) {
Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n",
PassID, Name);
}
void handleAfter(const StringRef After, std::string &Name, raw_ostream &Out) {
assert(After.find("*** IR Dump") == 0 && "Unexpected banner format.");
StringRef Banner = After.take_until([](char C) -> bool { return C == '\n'; });
Out << Banner;
// LazyCallGraph::SCC already has "(scc:..." in banner so only add
// in the name if it isn't already there.
if (Name.substr(0, 6).compare(" (scc:") != 0 && !llvm::forcePrintModuleIR())
Out << Name;
Out << After.substr(Banner.size());
}
void handleInvalidated(StringRef PassID, raw_ostream &Out) {
Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);
}
void handleFiltered(StringRef PassID, std::string &Name, raw_ostream &Out) {
SmallString<20> Banner =
formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name);
Out << Banner;
}
void handleIgnored(StringRef PassID, std::string &Name, raw_ostream &Out) {
Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name);
}
bool sameIR(const std::string &S1, const std::string &S2) {
return S1.compare(S2) == 0;
}
IRChangePrinter::IRChangePrinter()
: ChangePrinter<std::string>(
[this](Any IR) -> void { ::handleInitialIR(IR, Out); },
::generateOutput,
[this](StringRef PassID, std::string &Name) -> void {
::omitAfter(PassID, Name, Out);
},
[this](StringRef PassID, std::string &Name, const std::string &Before,
const std::string &After,
Any IR) -> void { ::handleAfter(After, Name, Out); },
[this](StringRef PassID) -> void {
::handleInvalidated(PassID, Out);
},
[this](StringRef PassID, std::string &Name) -> void {
::handleFiltered(PassID, Name, Out);
},
[this](StringRef PassID, std::string &Name) -> void {
::handleIgnored(PassID, Name, Out);
},
::sameIR),
Out(dbgs()) {}
void IRChangePrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) {
if (!PrintChanged)
return;
PIC.registerBeforePassCallback([this](StringRef P, Any IR) {
saveIRBeforePass(IR, P);
return true;
});
PIC.registerAfterPassCallback(
[this](StringRef P, Any IR, const PreservedAnalyses &) {
handleIRAfterPass(IR, P);
});
PIC.registerAfterPassInvalidatedCallback(
[this](StringRef P, const PreservedAnalyses &) {
handleInvalidatedPass(P);
});
}
PrintIRInstrumentation::~PrintIRInstrumentation() {
assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
}
@ -562,5 +344,4 @@ void StandardInstrumentations::registerCallbacks(
PrintPass.registerCallbacks(PIC);
TimePasses.registerCallbacks(PIC);
OptNone.registerCallbacks(PIC);
PrintChangedIR.registerCallbacks(PIC);
}

View File

@ -1,109 +0,0 @@
; Simple checks of -print-changed functionality
;
; Note that (mostly) only the banners are checked.
;
; Simple functionality check.
; RUN: opt -S -print-changed -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK0
;
; Check that only the passes that change the IR are printed and that the
; others (including g) are filtered out.
; RUN: opt -S -print-changed -passes=instsimplify -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK1
;
; Check that the reporting of IRs respects -print-module-scope
; RUN: opt -S -print-changed -passes=instsimplify -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK2
;
; Check that the reporting of IRs respects -print-module-scope
; RUN: opt -S -print-changed -passes=instsimplify -filter-print-funcs=f -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK3
;
; Check that reporting of multiple functions happens
; RUN: opt -S -print-changed -passes=instsimplify -filter-print-funcs="f,g" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK4
;
; Check that the reporting of IRs respects -filter-passes
; RUN: opt -S -print-changed -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK5
;
; Check that the reporting of IRs respects -filter-passes with multiple passes
; RUN: opt -S -print-changed -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass,InstSimplifyPass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK6
;
; Check that the reporting of IRs respects both -filter-passes and -filter-print-funcs
; RUN: opt -S -print-changed -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass,InstSimplifyPass" -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK7
;
; Check that the reporting of IRs respects -filter-passes, -filter-print-funcs and -print-module-scope
; RUN: opt -S -print-changed -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass,InstSimplifyPass" -filter-print-funcs=f -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK8
;
; Check that repeated passes that change the IR are printed and that the
; others (including g) are filtered out. Note that the second time
; instsimplify is run on f, it does not change the IR
; RUN: opt -S -print-changed -passes="instsimplify,instsimplify" -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK9
define i32 @g() {
entry:
%a = add i32 2, 3
ret i32 %a
}
define i32 @f() {
entry:
%a = add i32 2, 3
ret i32 %a
}
; CHECK0: *** IR Dump At Start: ***
; CHECK0: ; ModuleID = '<stdin>'
; CHECK0: *** IR Dump After VerifierPass (module) omitted because no change ***
; CHECK0: *** IR Dump After InstSimplifyPass *** (function: g)
; CHECK0: *** IR Pass PassManager<llvm::Function> (function: g) ignored ***
; CHECK0: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK0: *** IR Pass PassManager<llvm::Function> (function: f) ignored ***
; CHECK0: *** IR Pass ModuleToFunctionPassAdaptor<llvm::PassManager<llvm::Function> > (module) ignored ***
; CHECK0: *** IR Dump After VerifierPass (module) omitted because no change ***
; CHECK0: *** IR Dump After PrintModulePass (module) omitted because no change ***
; CHECK1: *** IR Dump At Start: ***
; CHECK1: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK1: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK2: *** IR Dump At Start: ***
; CHECK2: *** IR Dump After InstSimplifyPass *** (function: g)
; CHECK2: ModuleID = '<stdin>'
; CHECK2: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK2: ModuleID = '<stdin>'
; CHECK3: *** IR Dump At Start: ***
; CHECK3: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK3: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK3: ModuleID = '<stdin>'
; CHECK4: *** IR Dump At Start: ***
; CHECK4: *** IR Dump After InstSimplifyPass *** (function: g)
; CHECK4: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK5: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK5: *** IR Dump At Start: *** (function: g)
; CHECK5: *** IR Dump After NoOpFunctionPass (function: g) omitted because no change ***
; CHECK5: *** IR Dump After InstSimplifyPass (function: f) filtered out ***
; CHECK5: *** IR Dump After NoOpFunctionPass (function: f) omitted because no change ***
; CHECK6: *** IR Dump At Start: *** (function: g)
; CHECK6: *** IR Dump After InstSimplifyPass *** (function: g)
; CHECK6: *** IR Dump After NoOpFunctionPass (function: g) omitted because no change ***
; CHECK6: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK6: *** IR Dump After NoOpFunctionPass (function: f) omitted because no change ***
; CHECK7: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK7: *** IR Dump After NoOpFunctionPass (function: g) filtered out ***
; CHECK7: *** IR Dump At Start: *** (function: f)
; CHECK7: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK7: *** IR Dump After NoOpFunctionPass (function: f) omitted because no change ***
; CHECK8: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK8: *** IR Dump After NoOpFunctionPass (function: g) filtered out ***
; CHECK8: *** IR Dump At Start: *** (function: f)
; CHECK8: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK8: ModuleID = '<stdin>'
; CHECK8: *** IR Dump After NoOpFunctionPass (function: f) omitted because no change ***
; CHECK9: *** IR Dump At Start: ***
; CHECK9: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK9: *** IR Dump After InstSimplifyPass (function: g) filtered out ***
; CHECK9: *** IR Dump After InstSimplifyPass *** (function: f)
; CHECK9: *** IR Dump After InstSimplifyPass (function: f) omitted because no change ***