Skip to content

Commit

Permalink
[MachineFunctionPass] Support -print-changed={,c}diff{,-quiet}
Browse files Browse the repository at this point in the history
Follow-up to D130434.
Move doSystemDiff to PrintPasses.cpp and call it in MachineFunctionPass.cpp.

Reviewed By: aeubanks

Differential Revision: https://reviews.llvm.org/D130833
  • Loading branch information
MaskRay committed Aug 1, 2022
1 parent 995ab92 commit 2b70beb
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 76 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/IR/PrintPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ bool forcePrintModuleIR();
// Returns true if we should print the function.
bool isFunctionInPrintList(StringRef FunctionName);

// Perform a system based diff between \p Before and \p After, using \p
// OldLineFormat, \p NewLineFormat, and \p UnchangedLineFormat to control the
// formatting of the output. Return an error message for any failures instead
// of the diff.
std::string doSystemDiff(StringRef Before, StringRef After,
StringRef OldLineFormat, StringRef NewLineFormat,
StringRef UnchangedLineFormat);

} // namespace llvm

#endif // LLVM_IR_PRINTPASSES_H
30 changes: 28 additions & 2 deletions llvm/lib/CodeGen/MachineFunctionPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,34 @@ bool MachineFunctionPass::runOnFunction(Function &F) {
if (const PassInfo *PI = Pass::lookupPassInfo(getPassID()))
Arg = PI->getPassArgument();
errs() << ("*** IR Dump After " + getPassName() + " (" + Arg + ") on " +
MF.getName() + " ***\n" + AfterStr);
} else if (PrintChanged == ChangePrinter::Verbose) {
MF.getName() + " ***\n");
switch (PrintChanged) {
case ChangePrinter::None:
llvm_unreachable("");
case ChangePrinter::Quiet:
case ChangePrinter::Verbose:
case ChangePrinter::DotCfgQuiet: // unimplemented
case ChangePrinter::DotCfgVerbose: // unimplemented
errs() << AfterStr;
break;
case ChangePrinter::DiffQuiet:
case ChangePrinter::DiffVerbose:
case ChangePrinter::ColourDiffQuiet:
case ChangePrinter::ColourDiffVerbose: {
bool Color = llvm::is_contained(
{ChangePrinter::ColourDiffQuiet, ChangePrinter::ColourDiffVerbose},
PrintChanged.getValue());
StringRef Removed = Color ? "\033[31m-%l\033[0m\n" : "-%l\n";
StringRef Added = Color ? "\033[32m+%l\033[0m\n" : "+%l\n";
StringRef NoChange = " %l\n";
errs() << doSystemDiff(BeforeStr, AfterStr, Removed, Added, NoChange);
break;
}
}
} else if (llvm::is_contained({ChangePrinter::Verbose,
ChangePrinter::DiffVerbose,
ChangePrinter::ColourDiffVerbose},
PrintChanged.getValue())) {
errs() << ("*** IR Dump After " + getPassName() + " on " + MF.getName() +
" omitted because no change ***\n");
}
Expand Down
71 changes: 71 additions & 0 deletions llvm/lib/IR/PrintPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#include "llvm/IR/PrintPasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Program.h"
#include <unordered_set>

using namespace llvm;
Expand Down Expand Up @@ -73,6 +76,11 @@ cl::opt<ChangePrinter> llvm::PrintChanged(
// Sentinel value for unspecified option.
clEnumValN(ChangePrinter::Verbose, "", "")));

// An option for specifying the diff used by print-changed=[diff | diff-quiet]
static cl::opt<std::string>
DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"),
cl::desc("system diff used by change reporters"));

static cl::opt<bool>
PrintModuleScope("print-module-scope",
cl::desc("When printing IR for print-[before|after]{-all} "
Expand Down Expand Up @@ -130,3 +138,66 @@ bool llvm::isFunctionInPrintList(StringRef FunctionName) {
return PrintFuncNames.empty() ||
PrintFuncNames.count(std::string(FunctionName));
}

std::string llvm::doSystemDiff(StringRef Before, StringRef After,
StringRef OldLineFormat, StringRef NewLineFormat,
StringRef UnchangedLineFormat) {
StringRef SR[2]{Before, After};
// Store the 2 bodies into temporary files and call diff on them
// to get the body of the node.
const unsigned NumFiles = 3;
static std::string FileName[NumFiles];
static int FD[NumFiles]{-1, -1, -1};
for (unsigned I = 0; I < NumFiles; ++I) {
if (FD[I] == -1) {
SmallVector<char, 200> SV;
std::error_code EC =
sys::fs::createTemporaryFile("tmpdiff", "txt", FD[I], SV);
if (EC)
return "Unable to create temporary file.";
FileName[I] = Twine(SV).str();
}
// The third file is used as the result of the diff.
if (I == NumFiles - 1)
break;

std::error_code EC = sys::fs::openFileForWrite(FileName[I], FD[I]);
if (EC)
return "Unable to open temporary file for writing.";

raw_fd_ostream OutStream(FD[I], /*shouldClose=*/true);
if (FD[I] == -1)
return "Error opening file for writing.";
OutStream << SR[I];
}

static ErrorOr<std::string> DiffExe = sys::findProgramByName(DiffBinary);
if (!DiffExe)
return "Unable to find diff executable.";

SmallString<128> OLF, NLF, ULF;
("--old-line-format=" + OldLineFormat).toVector(OLF);
("--new-line-format=" + NewLineFormat).toVector(NLF);
("--unchanged-line-format=" + UnchangedLineFormat).toVector(ULF);

StringRef Args[] = {DiffBinary, "-w", "-d", OLF,
NLF, ULF, FileName[0], FileName[1]};
Optional<StringRef> Redirects[] = {None, StringRef(FileName[2]), None};
int Result = sys::ExecuteAndWait(*DiffExe, Args, None, Redirects);
if (Result < 0)
return "Error executing system diff.";
std::string Diff;
auto B = MemoryBuffer::getFile(FileName[2]);
if (B && *B)
Diff = (*B)->getBuffer().str();
else
return "Unable to read result.";

// Clean up.
for (const std::string &I : FileName) {
std::error_code EC = sys::fs::remove(I);
if (EC)
return "Unable to remove temporary file.";
}
return Diff;
}
72 changes: 0 additions & 72 deletions llvm/lib/Passes/StandardInstrumentations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ static cl::opt<bool>
cl::desc("Print before passes that change them"),
cl::init(false), cl::Hidden);

// An option for specifying the diff used by print-changed=[diff | diff-quiet]
static cl::opt<std::string>
DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"),
cl::desc("system diff used by change reporters"));

// An option for specifying the dot used by
// print-changed=[dot-cfg | dot-cfg-quiet]
static cl::opt<std::string>
Expand Down Expand Up @@ -116,73 +111,6 @@ static cl::opt<bool>

namespace {

// Perform a system based diff between \p Before and \p After, using
// \p OldLineFormat, \p NewLineFormat, and \p UnchangedLineFormat
// to control the formatting of the output. Return an error message
// for any failures instead of the diff.
std::string doSystemDiff(StringRef Before, StringRef After,
StringRef OldLineFormat, StringRef NewLineFormat,
StringRef UnchangedLineFormat) {
StringRef SR[2]{Before, After};
// Store the 2 bodies into temporary files and call diff on them
// to get the body of the node.
const unsigned NumFiles = 3;
static std::string FileName[NumFiles];
static int FD[NumFiles]{-1, -1, -1};
for (unsigned I = 0; I < NumFiles; ++I) {
if (FD[I] == -1) {
SmallVector<char, 200> SV;
std::error_code EC =
sys::fs::createTemporaryFile("tmpdiff", "txt", FD[I], SV);
if (EC)
return "Unable to create temporary file.";
FileName[I] = Twine(SV).str();
}
// The third file is used as the result of the diff.
if (I == NumFiles - 1)
break;

std::error_code EC = sys::fs::openFileForWrite(FileName[I], FD[I]);
if (EC)
return "Unable to open temporary file for writing.";

raw_fd_ostream OutStream(FD[I], /*shouldClose=*/true);
if (FD[I] == -1)
return "Error opening file for writing.";
OutStream << SR[I];
}

static ErrorOr<std::string> DiffExe = sys::findProgramByName(DiffBinary);
if (!DiffExe)
return "Unable to find diff executable.";

SmallString<128> OLF = formatv("--old-line-format={0}", OldLineFormat);
SmallString<128> NLF = formatv("--new-line-format={0}", NewLineFormat);
SmallString<128> ULF =
formatv("--unchanged-line-format={0}", UnchangedLineFormat);

StringRef Args[] = {DiffBinary, "-w", "-d", OLF,
NLF, ULF, FileName[0], FileName[1]};
Optional<StringRef> Redirects[] = {None, StringRef(FileName[2]), None};
int Result = sys::ExecuteAndWait(*DiffExe, Args, None, Redirects);
if (Result < 0)
return "Error executing system diff.";
std::string Diff;
auto B = MemoryBuffer::getFile(FileName[2]);
if (B && *B)
Diff = (*B)->getBuffer().str();
else
return "Unable to read result.";

// Clean up.
for (const std::string &I : FileName) {
std::error_code EC = sys::fs::remove(I);
if (EC)
return "Unable to remove temporary file.";
}
return Diff;
}

/// Extract Module out of \p IR unit. May return nullptr if \p IR does not match
/// certain global filters. Will never return nullptr if \p Force is true.
const Module *unwrapModule(Any IR, bool Force = false) {
Expand Down
33 changes: 33 additions & 0 deletions llvm/test/Other/ChangePrinters/print-changed-diff-machine.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
; REQUIRES: aarch64-registered-target
; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=diff %s 2>&1 | FileCheck %s --check-prefixes=DIFF,VERBOSE
; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=diff-quiet %s 2>&1 | FileCheck %s --check-prefixes=DIFF,QUIET
; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=cdiff %s 2>&1 | FileCheck %s --check-prefixes=CDIFF,VERBOSE
; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=cdiff-quiet %s 2>&1 | FileCheck %s --check-prefixes=CDIFF,QUIET

; VERBOSE: *** IR Dump After AArch64O0PreLegalizerCombiner on foo omitted because no change ***
; QUIET-NOT: *** {{.*}} omitted because no change ***

; DIFF: *** IR Dump After Legalizer (legalizer) on foo ***
; DIFF-NEXT: -# Machine code for function foo: IsSSA, TracksLiveness
; DIFF-NEXT: +# Machine code for function foo: IsSSA, TracksLiveness, Legalized
; DIFF-NEXT: Function Live Ins: $w0

; CDIFF: *** IR Dump After Legalizer (legalizer) on foo ***
; CDIFF-NEXT: {{.\[31m-}}# Machine code for function foo: IsSSA, TracksLiveness{{.\[0m}}
; CDIFF-NEXT: {{.\[32m\+}}# Machine code for function foo: IsSSA, TracksLiveness, Legalized{{.\[0m}}

@var = global i32 0

define void @foo(i32 %a) {
entry:
%b = add i32 %a, 1
store i32 %b, ptr @var
ret void
}

define void @bar(i32 %a) {
entry:
%b = add i32 %a, 2
store i32 %b, ptr @var
ret void
}
4 changes: 2 additions & 2 deletions llvm/test/Other/print-changed-machine.ll
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
; QUIET-NOT: ***
; QUIET: *** IR Dump After Legalizer (legalizer) on foo ***

;; Other modes are unimplemented. Currently they behave like 'quiet'.
; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=diff %s 2>&1 | FileCheck %s --check-prefix=QUIET
;; dot-cfg/dot-cfg-quiet are unimplemented. Currently they behave like 'quiet'.
; RUN: llc -filetype=null -mtriple=aarch64 -O0 -print-changed=dot-cfg %s 2>&1 | FileCheck %s --check-prefix=QUIET

@var = global i32 0

Expand Down

0 comments on commit 2b70beb

Please sign in to comment.