[llvm] Add option to dump IR to files instead of stderr (PR #66412)
Nuri Amari via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 28 14:15:08 PDT 2023
https://github.com/NuriAmari updated https://github.com/llvm/llvm-project/pull/66412
>From 960f26534a2a00d3b2eccab6da3d322fd927863f Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Thu, 7 Sep 2023 12:34:15 -0700
Subject: [PATCH 01/10] Add option to dump IR to files intstead of stderr
This patch adds a flag to LLVM such that the output
generated by the `-print-(before|after|all)`
family of flags is written to files in a directory rather
than to stderr.
This new flag is `-ir-dump-directory` and is used to
specify where to write the files. No other flags are
added, it just modifies the behavior of the print flags.
---
llvm/include/llvm/IR/PrintPasses.h | 4 +
.../llvm/Passes/StandardInstrumentations.h | 20 ++-
llvm/lib/IR/PrintPasses.cpp | 9 +
llvm/lib/Passes/StandardInstrumentations.cpp | 167 +++++++++++++++---
llvm/test/Other/dump-before-after.ll | 57 ++++++
5 files changed, 231 insertions(+), 26 deletions(-)
create mode 100644 llvm/test/Other/dump-before-after.ll
diff --git a/llvm/include/llvm/IR/PrintPasses.h b/llvm/include/llvm/IR/PrintPasses.h
index 95b97e76c867cb2..c4baadfa3975531 100644
--- a/llvm/include/llvm/IR/PrintPasses.h
+++ b/llvm/include/llvm/IR/PrintPasses.h
@@ -55,6 +55,10 @@ bool forcePrintModuleIR();
bool isPassInPrintList(StringRef PassName);
bool isFilterPassesEmpty();
+// Returns a non-empty string if printing before/after passes is to be
+// dumped into files in the returned directory instead of written to stderr.
+std::string irDumpDirectory();
+
// Returns true if we should print the function.
bool isFunctionInPrintList(StringRef FunctionName);
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 331130c6b22d990..fd512635356e5dd 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -46,6 +46,16 @@ class PrintIRInstrumentation {
void registerCallbacks(PassInstrumentationCallbacks &PIC);
private:
+ enum SuffixType {
+ before,
+ after,
+ invalidated,
+ };
+
+ using PrintModuleDesc = std::tuple<const Module *, std::string /* IRName */,
+ StringRef /* StoredPassID */,
+ SmallString<128> /* DumpFilename */>;
+
void printBeforePass(StringRef PassID, Any IR);
void printAfterPass(StringRef PassID, Any IR);
void printAfterPassInvalidated(StringRef PassID);
@@ -55,11 +65,15 @@ class PrintIRInstrumentation {
bool shouldPrintPassNumbers();
bool shouldPrintAtPassNumber();
- using PrintModuleDesc = std::tuple<const Module *, std::string, StringRef>;
-
- void pushModuleDesc(StringRef PassID, Any IR);
+ void pushModuleDesc(StringRef PassID, Any IR,
+ SmallString<128> DumpIRFilename);
PrintModuleDesc popModuleDesc(StringRef PassID);
+ SmallString<128> fetchDumpFilename(StringRef PassId, Any IR);
+ StringRef getFileSuffix(SuffixType);
+
+ static constexpr std::array FileSuffixes = {"-before.ll", "-after.ll",
+ "-invalidated.ll"};
PassInstrumentationCallbacks *PIC;
/// Stack of Module description, enough to print the module after a given
/// pass.
diff --git a/llvm/lib/IR/PrintPasses.cpp b/llvm/lib/IR/PrintPasses.cpp
index e2ef20bb81ba7d7..406af4a0a5e004e 100644
--- a/llvm/lib/IR/PrintPasses.cpp
+++ b/llvm/lib/IR/PrintPasses.cpp
@@ -103,6 +103,13 @@ static cl::list<std::string>
"options"),
cl::CommaSeparated, cl::Hidden);
+static cl::opt<std::string> IRDumpDirectory(
+ "ir-dump-directory",
+ llvm::cl::desc("If specified, IR printed using the "
+ "-print-[before|after]{-all} options will be dumped into "
+ "files in this directory rather than written to stderr"),
+ cl::init(""), cl::Hidden, cl::value_desc("filename"));
+
/// This is a helper to determine whether to print IR before or
/// after a pass.
@@ -139,6 +146,8 @@ std::vector<std::string> llvm::printAfterPasses() {
return std::vector<std::string>(PrintAfter);
}
+std::string llvm::irDumpDirectory() { return IRDumpDirectory; }
+
bool llvm::forcePrintModuleIR() { return PrintModuleScope; }
bool llvm::isPassInPrintList(StringRef PassName) {
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 6244c0a5a949ba1..64bf306438d99d2 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -14,6 +14,7 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/ADT/Any.h"
+#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
@@ -33,6 +34,7 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
@@ -684,9 +686,64 @@ PrintIRInstrumentation::~PrintIRInstrumentation() {
assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
}
-void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) {
+static SmallString<32> getIRDisplayName(Any IR) {
+
+ auto hashName = [](StringRef name) {
+ const size_t hashValue = hash_value(name);
+ return std::to_string(hashValue);
+ };
+
+ SmallString<32> Result;
+ const Module *M = unwrapModule(IR);
+ std::string ModuleName = hashName(M->getName());
+ SmallString<32> IRName;
+ if (any_cast<const Module *>(&IR)) {
+ IRName += "-module";
+ } else if (const Function **F = any_cast<const Function *>(&IR)) {
+ IRName += "-function-";
+ IRName += hashName((*F)->getName());
+ } else if (const LazyCallGraph::SCC **C =
+ any_cast<const LazyCallGraph::SCC *>(&IR)) {
+ IRName += "-scc-";
+ IRName += hashName((*C)->getName());
+ } else if (const Loop **L = any_cast<const Loop *>(&IR)) {
+ IRName += "-loop-";
+ IRName += hashName((*L)->getName());
+ } else {
+ llvm_unreachable("Unknown wrapped IR type");
+ }
+
+ Result += ModuleName;
+ Result += IRName;
+ return Result;
+}
+
+SmallString<128> PrintIRInstrumentation::fetchDumpFilename(StringRef PassID,
+ Any IR) {
+ const std::string &RootDirectory = irDumpDirectory();
+ assert(!RootDirectory.empty() &&
+ "The flag -ir-dump-directory must be passed to dump IR to files");
+ SmallString<128> ResultPath;
+ ResultPath += RootDirectory;
+ SmallString<16> Filename;
+ Filename += std::to_string(CurrentPassNumber);
+ Filename += "-";
+ Filename += getIRDisplayName(IR);
+ Filename += "-";
+ Filename += PassID;
+ sys::path::append(ResultPath, Filename);
+ return ResultPath;
+}
+
+StringRef
+PrintIRInstrumentation::getFileSuffix(PrintIRInstrumentation::SuffixType Type) {
+ return FileSuffixes[Type];
+}
+
+void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR,
+ SmallString<128> DumpIRFilename) {
const Module *M = unwrapModule(IR);
- ModuleDescStack.emplace_back(M, getIRName(IR), PassID);
+ ModuleDescStack.emplace_back(M, getIRName(IR), PassID, DumpIRFilename);
}
PrintIRInstrumentation::PrintModuleDesc
@@ -697,17 +754,42 @@ PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
return ModuleDesc;
}
+// Callers are responsible for closing the returned file descriptor
+static int prepareDumpIRFileDescriptor(StringRef DumpIRFilename) {
+ std::error_code EC;
+ auto ParentPath = llvm::sys::path::parent_path(DumpIRFilename);
+ if (!ParentPath.empty()) {
+ std::error_code EC = llvm::sys::fs::create_directories(ParentPath);
+ if (EC)
+ report_fatal_error(Twine("Failed to create directory ") + ParentPath +
+ " to support -ir-dump-directory: " + EC.message());
+ }
+ int Result = 0;
+ EC =
+ sys::fs::openFile(DumpIRFilename, Result, sys::fs::CD_OpenAlways,
+ sys::fs::FA_Write | sys::fs::FA_Read, sys::fs::OF_None);
+ if (EC)
+ report_fatal_error(Twine("Failed to open ") + DumpIRFilename +
+ " to support -ir-dump-directory: " + EC.message());
+ return Result;
+}
+
void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
if (isIgnored(PassID))
return;
+ SmallString<128> DumpIRFilename;
+ if (!irDumpDirectory().empty() &&
+ (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID)))
+ DumpIRFilename = fetchDumpFilename(PassID, IR);
+
// Saving Module for AfterPassInvalidated operations.
// Note: here we rely on a fact that we do not change modules while
// traversing the pipeline, so the latest captured module is good
// for all print operations that has not happen yet.
if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
shouldPrintAfterPass(PassID))
- pushModuleDesc(PassID, IR);
+ pushModuleDesc(PassID, IR, DumpIRFilename);
if (!shouldPrintIR(IR))
return;
@@ -720,9 +802,20 @@ void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
if (!shouldPrintBeforePass(PassID))
return;
- dbgs() << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
- << " ***\n";
- unwrapAndPrint(dbgs(), IR);
+ auto WriteIRToStream = [&](raw_ostream &Stream) {
+ Stream << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
+ << " ***\n";
+ unwrapAndPrint(Stream, IR);
+ };
+
+ if (!DumpIRFilename.empty()) {
+ DumpIRFilename += getFileSuffix(SuffixType::before);
+ llvm::raw_fd_ostream DumpIRFileStream{
+ prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
+ WriteIRToStream(DumpIRFileStream);
+ } else {
+ WriteIRToStream(dbgs());
+ }
}
void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
@@ -736,18 +829,32 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
const Module *M;
std::string IRName;
StringRef StoredPassID;
- std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
+ SmallString<128> DumpIRFilename;
+ std::tie(M, IRName, StoredPassID, DumpIRFilename) = popModuleDesc(PassID);
assert(StoredPassID == PassID && "mismatched PassID");
if (!shouldPrintIR(IR) || !shouldPrintAfterPass(PassID))
return;
- dbgs() << "*** IR Dump "
- << (shouldPrintAtPassNumber()
- ? StringRef(formatv("At {0}-{1}", CurrentPassNumber, PassID))
- : StringRef(formatv("After {0}", PassID)))
- << " on " << IRName << " ***\n";
- unwrapAndPrint(dbgs(), IR);
+ auto WriteIRToStream = [&](raw_ostream &Stream) {
+ Stream << "*** IR Dump "
+ << (shouldPrintAtPassNumber()
+ ? StringRef(formatv("At {0}-{1}", CurrentPassNumber, PassID))
+ : StringRef(formatv("After {0}", PassID)))
+ << " on " << IRName << " ***\n";
+ unwrapAndPrint(Stream, IR);
+ };
+
+ if (!irDumpDirectory().empty()) {
+ assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "
+ "should be set in printBeforePass");
+ DumpIRFilename += getFileSuffix(SuffixType::after);
+ llvm::raw_fd_ostream DumpIRFileStream{
+ prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
+ WriteIRToStream(DumpIRFileStream);
+ } else {
+ WriteIRToStream(dbgs());
+ }
}
void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
@@ -761,22 +868,36 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
const Module *M;
std::string IRName;
StringRef StoredPassID;
- std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
+ SmallString<128> DumpIRFilename;
+ std::tie(M, IRName, StoredPassID, DumpIRFilename) = popModuleDesc(PassID);
assert(StoredPassID == PassID && "mismatched PassID");
// Additional filtering (e.g. -filter-print-func) can lead to module
// printing being skipped.
if (!M || !shouldPrintAfterPass(PassID))
return;
- SmallString<20> Banner;
- if (shouldPrintAtPassNumber())
- Banner = formatv("*** IR Dump At {0}-{1} on {2} (invalidated) ***",
- CurrentPassNumber, PassID, IRName);
- else
- Banner = formatv("*** IR Dump After {0} on {1} (invalidated) ***",
- PassID, IRName);
- dbgs() << Banner << "\n";
- printIR(dbgs(), M);
+ auto WriteIRToStream = [&](raw_ostream &Stream) {
+ SmallString<20> Banner;
+ if (shouldPrintAtPassNumber())
+ Banner = formatv("*** IR Dump At {0}-{1} on {2} (invalidated) ***",
+ CurrentPassNumber, PassID, IRName);
+ else
+ Banner = formatv("*** IR Dump After {0} on {1} (invalidated) ***", PassID,
+ IRName);
+ Stream << Banner << "\n";
+ printIR(Stream, M);
+ };
+
+ if (!irDumpDirectory().empty()) {
+ assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "
+ "should be set in printBeforePass");
+ DumpIRFilename += getFileSuffix(SuffixType::invalidated);
+ llvm::raw_fd_ostream DumpIRFileStream{
+ prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
+ WriteIRToStream(DumpIRFileStream);
+ } else {
+ WriteIRToStream(dbgs());
+ }
}
bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
new file mode 100644
index 000000000000000..1f0d01022551123
--- /dev/null
+++ b/llvm/test/Other/dump-before-after.ll
@@ -0,0 +1,57 @@
+; RUN: mkdir -p %t/logs
+; RUN: rm -rf %t/logs
+
+; Basic dump before and after a single module pass
+
+; RUN: opt %s -disable-output -passes='no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
+; RUN: find %t/logs -type f -print | sort | FileCheck %s --check-prefix=SINGLE-PASS
+; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
+; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; RUN: rm -rf %t/logs
+
+
+; Dump before and after multiple runs of the same module pass
+; The integers preceeding log files represent relative pass execution order,
+; but they are not necessarily continuous. That is passes which are run
+; but not printed, still increment the count -- leading to gaps in the printed
+; integers.
+
+; RUN: opt %s -disable-output -passes='no-op-module,no-op-module,no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
+; RUN: find %t/logs -type f -print | sort | FileCheck %s --check-prefix=MULTIPLE-PASSES
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; RUN: rm -rf %t/logs
+
+; Dump before and after multiple passes, of various levels of granularity
+
+; RUN: opt %s -disable-output -passes='no-op-module,cgscc(no-op-cgscc),function(no-op-function),function(loop(no-op-loop))' -ir-dump-directory %t/logs -print-after=no-op-module,no-op-cgscc,no-op-function,no-op-loop -print-before=no-op-module,no-op-cgscc,no-op-function,no-op-loop
+; RUN: find %t/logs -type f -print | sort | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[0-9]+]]-NoOpCGSCCPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH]]-NoOpCGSCCPass-before.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH:[0-9]+]]-NoOpCGSCCPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH]]-NoOpCGSCCPass-before.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH:[0-9]+]]-NoOpFunctionPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH]]-NoOpFunctionPass-before.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH:[0-9]+]]-NoOpFunctionPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH]]-NoOpFunctionPass-before.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH:[0-9]+]]-NoOpLoopPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH]]-NoOpLoopPass-before.ll
+
+; RUN: rm -rf %t/logs
+
+define void @foo() {
+ ret void
+}
+
+define void @bar() {
+entry:
+ br label %my-loop
+my-loop:
+ br label %my-loop
+}
>From a697d25ae6b97cfee607f1b304342b3c47cdfcc0 Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Thu, 7 Sep 2023 12:34:15 -0700
Subject: [PATCH 02/10] Address PR Comments
- Use raw_svector_stream to build paths
- Rename PassID -> PassName in fetchDumpFileName
- Use stable_hash_combine_string instead of hash_value
- Use `-sort -n` in test to sort by prefix integer intead of
alphabetically
- Return a StringRef instead of a std::string for irDumpDirectory
---
llvm/include/llvm/IR/PrintPasses.h | 2 +-
llvm/lib/IR/PrintPasses.cpp | 4 +-
llvm/lib/Passes/StandardInstrumentations.cpp | 48 ++++++++------------
llvm/test/Other/dump-before-after.ll | 12 ++---
4 files changed, 29 insertions(+), 37 deletions(-)
diff --git a/llvm/include/llvm/IR/PrintPasses.h b/llvm/include/llvm/IR/PrintPasses.h
index c4baadfa3975531..f173194f6bc0c14 100644
--- a/llvm/include/llvm/IR/PrintPasses.h
+++ b/llvm/include/llvm/IR/PrintPasses.h
@@ -57,7 +57,7 @@ bool isFilterPassesEmpty();
// Returns a non-empty string if printing before/after passes is to be
// dumped into files in the returned directory instead of written to stderr.
-std::string irDumpDirectory();
+StringRef irDumpDirectory();
// Returns true if we should print the function.
bool isFunctionInPrintList(StringRef FunctionName);
diff --git a/llvm/lib/IR/PrintPasses.cpp b/llvm/lib/IR/PrintPasses.cpp
index 406af4a0a5e004e..c80aa03fcd10dc6 100644
--- a/llvm/lib/IR/PrintPasses.cpp
+++ b/llvm/lib/IR/PrintPasses.cpp
@@ -108,7 +108,7 @@ static cl::opt<std::string> IRDumpDirectory(
llvm::cl::desc("If specified, IR printed using the "
"-print-[before|after]{-all} options will be dumped into "
"files in this directory rather than written to stderr"),
- cl::init(""), cl::Hidden, cl::value_desc("filename"));
+ cl::Hidden, cl::value_desc("filename"));
/// This is a helper to determine whether to print IR before or
/// after a pass.
@@ -146,7 +146,7 @@ std::vector<std::string> llvm::printAfterPasses() {
return std::vector<std::string>(PrintAfter);
}
-std::string llvm::irDumpDirectory() { return IRDumpDirectory; }
+StringRef llvm::irDumpDirectory() { return IRDumpDirectory; }
bool llvm::forcePrintModuleIR() { return PrintModuleScope; }
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 64bf306438d99d2..3147a775dd61d8c 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -14,11 +14,11 @@
#include "llvm/Passes/StandardInstrumentations.h"
#include "llvm/ADT/Any.h"
-#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/StableHashing.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
@@ -686,51 +686,43 @@ PrintIRInstrumentation::~PrintIRInstrumentation() {
assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
}
-static SmallString<32> getIRDisplayName(Any IR) {
-
- auto hashName = [](StringRef name) {
- const size_t hashValue = hash_value(name);
- return std::to_string(hashValue);
- };
-
+static SmallString<32> getIRFileDisplayName(Any IR) {
SmallString<32> Result;
+ raw_svector_ostream ResultStream(Result);
const Module *M = unwrapModule(IR);
- std::string ModuleName = hashName(M->getName());
- SmallString<32> IRName;
+ ResultStream << stable_hash_combine_string(M->getName());
if (any_cast<const Module *>(&IR)) {
- IRName += "-module";
+ ResultStream << "-module";
} else if (const Function **F = any_cast<const Function *>(&IR)) {
- IRName += "-function-";
- IRName += hashName((*F)->getName());
+ ResultStream << "-function-";
+ ResultStream << stable_hash_combine_string((*F)->getName());
} else if (const LazyCallGraph::SCC **C =
any_cast<const LazyCallGraph::SCC *>(&IR)) {
- IRName += "-scc-";
- IRName += hashName((*C)->getName());
+ ResultStream << "-scc-";
+ ResultStream << stable_hash_combine_string((*C)->getName());
} else if (const Loop **L = any_cast<const Loop *>(&IR)) {
- IRName += "-loop-";
- IRName += hashName((*L)->getName());
+ ResultStream << "-loop-";
+ ResultStream << stable_hash_combine_string((*L)->getName());
} else {
llvm_unreachable("Unknown wrapped IR type");
}
-
- Result += ModuleName;
- Result += IRName;
return Result;
}
-SmallString<128> PrintIRInstrumentation::fetchDumpFilename(StringRef PassID,
+SmallString<128> PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,
Any IR) {
- const std::string &RootDirectory = irDumpDirectory();
+ const StringRef RootDirectory = irDumpDirectory();
assert(!RootDirectory.empty() &&
"The flag -ir-dump-directory must be passed to dump IR to files");
SmallString<128> ResultPath;
ResultPath += RootDirectory;
- SmallString<16> Filename;
- Filename += std::to_string(CurrentPassNumber);
- Filename += "-";
- Filename += getIRDisplayName(IR);
- Filename += "-";
- Filename += PassID;
+ SmallString<64> Filename;
+ raw_svector_ostream FilenameStream(Filename);
+ FilenameStream << CurrentPassNumber;
+ FilenameStream << "-";
+ FilenameStream << getIRFileDisplayName(IR);
+ FilenameStream << "-";
+ FilenameStream << PassName;
sys::path::append(ResultPath, Filename);
return ResultPath;
}
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
index 1f0d01022551123..5c95e869bbd06a5 100644
--- a/llvm/test/Other/dump-before-after.ll
+++ b/llvm/test/Other/dump-before-after.ll
@@ -4,12 +4,11 @@
; Basic dump before and after a single module pass
; RUN: opt %s -disable-output -passes='no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
-; RUN: find %t/logs -type f -print | sort | FileCheck %s --check-prefix=SINGLE-PASS
+; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=SINGLE-PASS
; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; RUN: rm -rf %t/logs
-
; Dump before and after multiple runs of the same module pass
; The integers preceeding log files represent relative pass execution order,
; but they are not necessarily continuous. That is passes which are run
@@ -17,7 +16,7 @@
; integers.
; RUN: opt %s -disable-output -passes='no-op-module,no-op-module,no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
-; RUN: find %t/logs -type f -print | sort | FileCheck %s --check-prefix=MULTIPLE-PASSES
+; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-PASSES
; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
@@ -28,8 +27,8 @@
; Dump before and after multiple passes, of various levels of granularity
-; RUN: opt %s -disable-output -passes='no-op-module,cgscc(no-op-cgscc),function(no-op-function),function(loop(no-op-loop))' -ir-dump-directory %t/logs -print-after=no-op-module,no-op-cgscc,no-op-function,no-op-loop -print-before=no-op-module,no-op-cgscc,no-op-function,no-op-loop
-; RUN: find %t/logs -type f -print | sort | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
+; RUN: opt %s -disable-output -passes='no-op-module,cgscc(no-op-cgscc),function(no-op-function),function(loop(no-op-loop)),no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module,no-op-cgscc,no-op-function,no-op-loop -print-before=no-op-module,no-op-cgscc,no-op-function,no-op-loop
+; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[0-9]+]]-NoOpCGSCCPass-after.ll
@@ -42,7 +41,8 @@
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH]]-NoOpFunctionPass-before.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH:[0-9]+]]-NoOpLoopPass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH]]-NoOpLoopPass-before.ll
-
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; RUN: rm -rf %t/logs
define void @foo() {
>From c9af58abe734ab8e5563e1b7646cb12ae7efd083 Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Tue, 26 Sep 2023 09:43:56 -0700
Subject: [PATCH 03/10] Address PR Comments #2
- Remove mkdir -p run comment from LIT test
- Open dump file with write permissions only, not write and read
- Make suffix type enum an enum class
- Prepend a semi colon to the dump file header to make it valid IR
ingestible by opt
---
.../llvm/Passes/StandardInstrumentations.h | 8 +++----
llvm/lib/Passes/StandardInstrumentations.cpp | 23 +++++++++----------
llvm/test/Other/dump-before-after.ll | 1 -
3 files changed, 15 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index fd512635356e5dd..550c93b6cb327ec 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -46,10 +46,10 @@ class PrintIRInstrumentation {
void registerCallbacks(PassInstrumentationCallbacks &PIC);
private:
- enum SuffixType {
- before,
- after,
- invalidated,
+ enum class SuffixType {
+ Before,
+ After,
+ Invalidated,
};
using PrintModuleDesc = std::tuple<const Module *, std::string /* IRName */,
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 3147a775dd61d8c..d946ed3a0c8a3df 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -729,7 +729,7 @@ SmallString<128> PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,
StringRef
PrintIRInstrumentation::getFileSuffix(PrintIRInstrumentation::SuffixType Type) {
- return FileSuffixes[Type];
+ return FileSuffixes[static_cast<size_t>(Type)];
}
void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR,
@@ -757,9 +757,8 @@ static int prepareDumpIRFileDescriptor(StringRef DumpIRFilename) {
" to support -ir-dump-directory: " + EC.message());
}
int Result = 0;
- EC =
- sys::fs::openFile(DumpIRFilename, Result, sys::fs::CD_OpenAlways,
- sys::fs::FA_Write | sys::fs::FA_Read, sys::fs::OF_None);
+ EC = sys::fs::openFile(DumpIRFilename, Result, sys::fs::CD_OpenAlways,
+ sys::fs::FA_Write, sys::fs::OF_None);
if (EC)
report_fatal_error(Twine("Failed to open ") + DumpIRFilename +
" to support -ir-dump-directory: " + EC.message());
@@ -795,13 +794,13 @@ void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
return;
auto WriteIRToStream = [&](raw_ostream &Stream) {
- Stream << "*** IR Dump Before " << PassID << " on " << getIRName(IR)
+ Stream << "; *** IR Dump Before " << PassID << " on " << getIRName(IR)
<< " ***\n";
unwrapAndPrint(Stream, IR);
};
if (!DumpIRFilename.empty()) {
- DumpIRFilename += getFileSuffix(SuffixType::before);
+ DumpIRFilename += getFileSuffix(SuffixType::Before);
llvm::raw_fd_ostream DumpIRFileStream{
prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
WriteIRToStream(DumpIRFileStream);
@@ -829,7 +828,7 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
return;
auto WriteIRToStream = [&](raw_ostream &Stream) {
- Stream << "*** IR Dump "
+ Stream << "; *** IR Dump "
<< (shouldPrintAtPassNumber()
? StringRef(formatv("At {0}-{1}", CurrentPassNumber, PassID))
: StringRef(formatv("After {0}", PassID)))
@@ -840,7 +839,7 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
if (!irDumpDirectory().empty()) {
assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "
"should be set in printBeforePass");
- DumpIRFilename += getFileSuffix(SuffixType::after);
+ DumpIRFilename += getFileSuffix(SuffixType::After);
llvm::raw_fd_ostream DumpIRFileStream{
prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
WriteIRToStream(DumpIRFileStream);
@@ -871,11 +870,11 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
auto WriteIRToStream = [&](raw_ostream &Stream) {
SmallString<20> Banner;
if (shouldPrintAtPassNumber())
- Banner = formatv("*** IR Dump At {0}-{1} on {2} (invalidated) ***",
+ Banner = formatv("; *** IR Dump At {0}-{1} on {2} (invalidated) ***",
CurrentPassNumber, PassID, IRName);
else
- Banner = formatv("*** IR Dump After {0} on {1} (invalidated) ***", PassID,
- IRName);
+ Banner = formatv("; *** IR Dump After {0} on {1} (invalidated) ***",
+ PassID, IRName);
Stream << Banner << "\n";
printIR(Stream, M);
};
@@ -883,7 +882,7 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
if (!irDumpDirectory().empty()) {
assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "
"should be set in printBeforePass");
- DumpIRFilename += getFileSuffix(SuffixType::invalidated);
+ DumpIRFilename += getFileSuffix(SuffixType::Invalidated);
llvm::raw_fd_ostream DumpIRFileStream{
prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
WriteIRToStream(DumpIRFileStream);
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
index 5c95e869bbd06a5..73b820a9893ee24 100644
--- a/llvm/test/Other/dump-before-after.ll
+++ b/llvm/test/Other/dump-before-after.ll
@@ -1,4 +1,3 @@
-; RUN: mkdir -p %t/logs
; RUN: rm -rf %t/logs
; Basic dump before and after a single module pass
>From a5bd20a028f2212e5fbccb3dc16247d6e25dbafd Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Tue, 26 Sep 2023 14:28:29 -0700
Subject: [PATCH 04/10] Address PR Feedback #3
- Use a struct instead of a tuple for
the pass run state stack
- Format filename name hash as fixed
length hexidemical value
---
.../llvm/Passes/StandardInstrumentations.h | 19 ++++++++--
llvm/lib/Passes/StandardInstrumentations.cpp | 37 ++++++++-----------
llvm/test/Other/dump-before-after.ll | 18 ++++-----
3 files changed, 40 insertions(+), 34 deletions(-)
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 550c93b6cb327ec..4b5af9d4b5ff90a 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -52,6 +52,17 @@ class PrintIRInstrumentation {
Invalidated,
};
+ struct PassRunDescriptor {
+ const Module *M;
+ SmallString<128> DumpIRFilename;
+ const SmallString<128> IRName;
+ const StringRef PassID;
+
+ PassRunDescriptor(const Module *M, SmallString<128> DumpIRFilename,
+ SmallString<128> IRName, const StringRef PassID)
+ : M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName} {}
+ };
+
using PrintModuleDesc = std::tuple<const Module *, std::string /* IRName */,
StringRef /* StoredPassID */,
SmallString<128> /* DumpFilename */>;
@@ -65,9 +76,9 @@ class PrintIRInstrumentation {
bool shouldPrintPassNumbers();
bool shouldPrintAtPassNumber();
- void pushModuleDesc(StringRef PassID, Any IR,
- SmallString<128> DumpIRFilename);
- PrintModuleDesc popModuleDesc(StringRef PassID);
+ void pushPassRunDescriptor(StringRef PassID, Any IR,
+ SmallString<128> &DumpIRFilename);
+ PassRunDescriptor popPassRunDescriptor(StringRef PassID);
SmallString<128> fetchDumpFilename(StringRef PassId, Any IR);
StringRef getFileSuffix(SuffixType);
@@ -77,7 +88,7 @@ class PrintIRInstrumentation {
PassInstrumentationCallbacks *PIC;
/// Stack of Module description, enough to print the module after a given
/// pass.
- SmallVector<PrintModuleDesc, 2> ModuleDescStack;
+ SmallVector<PassRunDescriptor, 2> PassRunDescriptorStack;
/// Used for print-at-pass-number
unsigned CurrentPassNumber = 0;
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index d946ed3a0c8a3df..fc5a4c0df70fe8d 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -690,7 +690,9 @@ static SmallString<32> getIRFileDisplayName(Any IR) {
SmallString<32> Result;
raw_svector_ostream ResultStream(Result);
const Module *M = unwrapModule(IR);
- ResultStream << stable_hash_combine_string(M->getName());
+ stable_hash NameHash = stable_hash_combine_string(M->getName());
+ unsigned int MaxHashWidth = sizeof(stable_hash) * 8 / 4;
+ write_hex(ResultStream, NameHash, HexPrintStyle::Lower, MaxHashWidth);
if (any_cast<const Module *>(&IR)) {
ResultStream << "-module";
} else if (const Function **F = any_cast<const Function *>(&IR)) {
@@ -732,22 +734,23 @@ PrintIRInstrumentation::getFileSuffix(PrintIRInstrumentation::SuffixType Type) {
return FileSuffixes[static_cast<size_t>(Type)];
}
-void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR,
- SmallString<128> DumpIRFilename) {
+void PrintIRInstrumentation::pushPassRunDescriptor(
+ StringRef PassID, Any IR, SmallString<128> &DumpIRFilename) {
const Module *M = unwrapModule(IR);
- ModuleDescStack.emplace_back(M, getIRName(IR), PassID, DumpIRFilename);
+ PassRunDescriptorStack.emplace_back(M, DumpIRFilename,
+ SmallString<128>(getIRName(IR)), PassID);
}
-PrintIRInstrumentation::PrintModuleDesc
-PrintIRInstrumentation::popModuleDesc(StringRef PassID) {
+PrintIRInstrumentation::PassRunDescriptor
+PrintIRInstrumentation::popPassRunDescriptor(StringRef PassID) {
assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
- PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val();
- assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack");
- return ModuleDesc;
+ PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
+ assert(Descriptor.PassID.equals(PassID) && "malformed ModuleDescStack");
+ return Descriptor;
}
// Callers are responsible for closing the returned file descriptor
-static int prepareDumpIRFileDescriptor(StringRef DumpIRFilename) {
+static int prepareDumpIRFileDescriptor(const StringRef DumpIRFilename) {
std::error_code EC;
auto ParentPath = llvm::sys::path::parent_path(DumpIRFilename);
if (!ParentPath.empty()) {
@@ -780,7 +783,7 @@ void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
// for all print operations that has not happen yet.
if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
shouldPrintAfterPass(PassID))
- pushModuleDesc(PassID, IR, DumpIRFilename);
+ pushPassRunDescriptor(PassID, IR, DumpIRFilename);
if (!shouldPrintIR(IR))
return;
@@ -817,11 +820,7 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
!shouldPrintAtPassNumber())
return;
- const Module *M;
- std::string IRName;
- StringRef StoredPassID;
- SmallString<128> DumpIRFilename;
- std::tie(M, IRName, StoredPassID, DumpIRFilename) = popModuleDesc(PassID);
+ auto [M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
assert(StoredPassID == PassID && "mismatched PassID");
if (!shouldPrintIR(IR) || !shouldPrintAfterPass(PassID))
@@ -856,11 +855,7 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
!shouldPrintAtPassNumber())
return;
- const Module *M;
- std::string IRName;
- StringRef StoredPassID;
- SmallString<128> DumpIRFilename;
- std::tie(M, IRName, StoredPassID, DumpIRFilename) = popModuleDesc(PassID);
+ auto [M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
assert(StoredPassID == PassID && "mismatched PassID");
// Additional filtering (e.g. -filter-print-func) can lead to module
// printing being skipped.
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
index 73b820a9893ee24..32a8ab8e7705dca 100644
--- a/llvm/test/Other/dump-before-after.ll
+++ b/llvm/test/Other/dump-before-after.ll
@@ -4,7 +4,7 @@
; RUN: opt %s -disable-output -passes='no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=SINGLE-PASS
-; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
+; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; RUN: rm -rf %t/logs
@@ -16,7 +16,7 @@
; RUN: opt %s -disable-output -passes='no-op-module,no-op-module,no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-PASSES
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
@@ -27,18 +27,18 @@
; Dump before and after multiple passes, of various levels of granularity
; RUN: opt %s -disable-output -passes='no-op-module,cgscc(no-op-cgscc),function(no-op-function),function(loop(no-op-loop)),no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module,no-op-cgscc,no-op-function,no-op-loop -print-before=no-op-module,no-op-cgscc,no-op-function,no-op-loop
-; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[0-9]+]]-module-NoOpModulePass-after.ll
+; RUN: find %t/logs -type f -printf '%P\n' | tee ~/log.txt | sort -n | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[0-9]+]]-NoOpCGSCCPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH]]-NoOpCGSCCPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH:[0-9]+]]-NoOpCGSCCPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH]]-NoOpCGSCCPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH:[0-9]+]]-NoOpFunctionPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH:[a-z0-9]+]]-NoOpFunctionPass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH]]-NoOpFunctionPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH:[0-9]+]]-NoOpFunctionPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH:[a-z0-9]+]]-NoOpFunctionPass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH]]-NoOpFunctionPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH:[0-9]+]]-NoOpLoopPass-after.ll
+; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH:[a-z0-9]+]]-NoOpLoopPass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH]]-NoOpLoopPass-before.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
>From d4c7a1feae26775fafb0379488f29988cff58539 Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Wed, 27 Sep 2023 08:49:09 -0700
Subject: [PATCH 05/10] Cleanup 'Address PR Feedback #3' commit
- Remove erroneously included tee invocation in test
- Remove now unused typedef (replaced by struct)
- Adjust comment to refer to pass run descriptor instead
of module descriptor
---
llvm/include/llvm/Passes/StandardInstrumentations.h | 6 +-----
llvm/test/Other/dump-before-after.ll | 2 +-
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 4b5af9d4b5ff90a..b1fb891d5349b3b 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -63,10 +63,6 @@ class PrintIRInstrumentation {
: M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName} {}
};
- using PrintModuleDesc = std::tuple<const Module *, std::string /* IRName */,
- StringRef /* StoredPassID */,
- SmallString<128> /* DumpFilename */>;
-
void printBeforePass(StringRef PassID, Any IR);
void printAfterPass(StringRef PassID, Any IR);
void printAfterPassInvalidated(StringRef PassID);
@@ -86,7 +82,7 @@ class PrintIRInstrumentation {
static constexpr std::array FileSuffixes = {"-before.ll", "-after.ll",
"-invalidated.ll"};
PassInstrumentationCallbacks *PIC;
- /// Stack of Module description, enough to print the module after a given
+ /// Stack of Pass Run descriptions, enough to print the IR unit after a given
/// pass.
SmallVector<PassRunDescriptor, 2> PassRunDescriptorStack;
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
index 32a8ab8e7705dca..4d3ea41c9e0dfbf 100644
--- a/llvm/test/Other/dump-before-after.ll
+++ b/llvm/test/Other/dump-before-after.ll
@@ -27,7 +27,7 @@
; Dump before and after multiple passes, of various levels of granularity
; RUN: opt %s -disable-output -passes='no-op-module,cgscc(no-op-cgscc),function(no-op-function),function(loop(no-op-loop)),no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module,no-op-cgscc,no-op-function,no-op-loop -print-before=no-op-module,no-op-cgscc,no-op-function,no-op-loop
-; RUN: find %t/logs -type f -printf '%P\n' | tee ~/log.txt | sort -n | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
+; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
>From 9f18d14c7b488dd53e066f0112eab377ba0296b3 Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Wed, 27 Sep 2023 09:08:14 -0700
Subject: [PATCH 06/10] Fix build
- Rename reference to the now renamed ModuleDescStack
- Appease warnings about structural binding captures being a C++20
extension and pass them to the lambda explicitly instead
---
llvm/lib/Passes/StandardInstrumentations.cpp | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index fc5a4c0df70fe8d..0f20b3fcafe941b 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -683,7 +683,8 @@ bool IRComparer<T>::generateFunctionData(IRDataT<T> &Data, const Function &F) {
}
PrintIRInstrumentation::~PrintIRInstrumentation() {
- assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit");
+ assert(PassRunDescriptorStack.empty() &&
+ "ModuleDescStack is not empty at exit");
}
static SmallString<32> getIRFileDisplayName(Any IR) {
@@ -826,7 +827,7 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
if (!shouldPrintIR(IR) || !shouldPrintAfterPass(PassID))
return;
- auto WriteIRToStream = [&](raw_ostream &Stream) {
+ auto WriteIRToStream = [&](raw_ostream &Stream, const StringRef IRName) {
Stream << "; *** IR Dump "
<< (shouldPrintAtPassNumber()
? StringRef(formatv("At {0}-{1}", CurrentPassNumber, PassID))
@@ -841,9 +842,9 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
DumpIRFilename += getFileSuffix(SuffixType::After);
llvm::raw_fd_ostream DumpIRFileStream{
prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
- WriteIRToStream(DumpIRFileStream);
+ WriteIRToStream(DumpIRFileStream, IRName);
} else {
- WriteIRToStream(dbgs());
+ WriteIRToStream(dbgs(), IRName);
}
}
@@ -862,7 +863,8 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
if (!M || !shouldPrintAfterPass(PassID))
return;
- auto WriteIRToStream = [&](raw_ostream &Stream) {
+ auto WriteIRToStream = [&](raw_ostream &Stream, const Module *M,
+ const StringRef IRName) {
SmallString<20> Banner;
if (shouldPrintAtPassNumber())
Banner = formatv("; *** IR Dump At {0}-{1} on {2} (invalidated) ***",
@@ -880,9 +882,9 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
DumpIRFilename += getFileSuffix(SuffixType::Invalidated);
llvm::raw_fd_ostream DumpIRFileStream{
prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
- WriteIRToStream(DumpIRFileStream);
+ WriteIRToStream(DumpIRFileStream, M, IRName);
} else {
- WriteIRToStream(dbgs());
+ WriteIRToStream(dbgs(), M, IRName);
}
}
>From 06c0438c1683c1fbb86e07b3ee3021d5fdb2b3b6 Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Wed, 27 Sep 2023 09:52:40 -0700
Subject: [PATCH 07/10] Rename more references to ModuleDescStack
---
llvm/lib/Passes/StandardInstrumentations.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 0f20b3fcafe941b..eb2ab2795efdcef 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -684,7 +684,7 @@ bool IRComparer<T>::generateFunctionData(IRDataT<T> &Data, const Function &F) {
PrintIRInstrumentation::~PrintIRInstrumentation() {
assert(PassRunDescriptorStack.empty() &&
- "ModuleDescStack is not empty at exit");
+ "PassRunDescriptorStack is not empty at exit");
}
static SmallString<32> getIRFileDisplayName(Any IR) {
@@ -744,9 +744,10 @@ void PrintIRInstrumentation::pushPassRunDescriptor(
PrintIRInstrumentation::PassRunDescriptor
PrintIRInstrumentation::popPassRunDescriptor(StringRef PassID) {
- assert(!ModuleDescStack.empty() && "empty ModuleDescStack");
+ assert(!PassRunDescriptorStack.empty() && "empty PassRunDescriptorStack");
PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
- assert(Descriptor.PassID.equals(PassID) && "malformed ModuleDescStack");
+ assert(Descriptor.PassID.equals(PassID) &&
+ "malformed PassRunDescriptorStack");
return Descriptor;
}
>From 180292136df2edbc0bd0db4f0cb71c3281bba98a Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Wed, 27 Sep 2023 11:57:39 -0700
Subject: [PATCH 08/10] Correct PassRunDescriptor Constructor
I failed to initalize one of the fields in the
struct causing an assert to later fail in the a
Clang test.
---
llvm/include/llvm/Passes/StandardInstrumentations.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index b1fb891d5349b3b..054ea6031534112 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -60,7 +60,8 @@ class PrintIRInstrumentation {
PassRunDescriptor(const Module *M, SmallString<128> DumpIRFilename,
SmallString<128> IRName, const StringRef PassID)
- : M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName} {}
+ : M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName}, PassID(PassID) {
+ }
};
void printBeforePass(StringRef PassID, Any IR);
>From 4fbb393b3fe3d69254ca34ce5fec74453ffac81d Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Thu, 28 Sep 2023 11:04:46 -0700
Subject: [PATCH 09/10] Address PR Feedback #4
- Move ir-dump-directory and related getter into
StandardInstrumentations.cpp
- Switch to std::string to store DumpIRFilename where convenient
- Make all members of PassRunDescriptor const
- Accordingly make a copy of DumpIRFilename to append the suffix
- Move Suffix related declarations out of PrintIRInstrumentation class
into StandardInstrumentations.cpp
- Remove unnecessary `llvm::` qualifier
- Replace find usage in test with ls
- Add a test for printing a pass after it is invalidated
- Hash function / scc / loop names in the same manner we hash module
names
- Assert dump file numbers in tests instead of relying on sort
---
llvm/include/llvm/IR/PrintPasses.h | 4 --
.../llvm/Passes/StandardInstrumentations.h | 22 ++----
llvm/lib/IR/PrintPasses.cpp | 9 ---
llvm/lib/Passes/StandardInstrumentations.cpp | 64 +++++++++++------
.../Other/dump-before-after-invalidated.ll | 24 +++++++
llvm/test/Other/dump-before-after.ll | 68 ++++++++++++-------
6 files changed, 116 insertions(+), 75 deletions(-)
create mode 100644 llvm/test/Other/dump-before-after-invalidated.ll
diff --git a/llvm/include/llvm/IR/PrintPasses.h b/llvm/include/llvm/IR/PrintPasses.h
index f173194f6bc0c14..95b97e76c867cb2 100644
--- a/llvm/include/llvm/IR/PrintPasses.h
+++ b/llvm/include/llvm/IR/PrintPasses.h
@@ -55,10 +55,6 @@ bool forcePrintModuleIR();
bool isPassInPrintList(StringRef PassName);
bool isFilterPassesEmpty();
-// Returns a non-empty string if printing before/after passes is to be
-// dumped into files in the returned directory instead of written to stderr.
-StringRef irDumpDirectory();
-
// Returns true if we should print the function.
bool isFunctionInPrintList(StringRef FunctionName);
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 054ea6031534112..2ec36cad244fd2c 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -46,20 +46,14 @@ class PrintIRInstrumentation {
void registerCallbacks(PassInstrumentationCallbacks &PIC);
private:
- enum class SuffixType {
- Before,
- After,
- Invalidated,
- };
-
struct PassRunDescriptor {
const Module *M;
- SmallString<128> DumpIRFilename;
- const SmallString<128> IRName;
+ const std::string DumpIRFilename;
+ const std::string IRName;
const StringRef PassID;
- PassRunDescriptor(const Module *M, SmallString<128> DumpIRFilename,
- SmallString<128> IRName, const StringRef PassID)
+ PassRunDescriptor(const Module *M, std::string DumpIRFilename,
+ std::string IRName, const StringRef PassID)
: M{M}, DumpIRFilename{DumpIRFilename}, IRName{IRName}, PassID(PassID) {
}
};
@@ -74,14 +68,10 @@ class PrintIRInstrumentation {
bool shouldPrintAtPassNumber();
void pushPassRunDescriptor(StringRef PassID, Any IR,
- SmallString<128> &DumpIRFilename);
+ std::string &DumpIRFilename);
PassRunDescriptor popPassRunDescriptor(StringRef PassID);
+ std::string fetchDumpFilename(StringRef PassId, Any IR);
- SmallString<128> fetchDumpFilename(StringRef PassId, Any IR);
- StringRef getFileSuffix(SuffixType);
-
- static constexpr std::array FileSuffixes = {"-before.ll", "-after.ll",
- "-invalidated.ll"};
PassInstrumentationCallbacks *PIC;
/// Stack of Pass Run descriptions, enough to print the IR unit after a given
/// pass.
diff --git a/llvm/lib/IR/PrintPasses.cpp b/llvm/lib/IR/PrintPasses.cpp
index c80aa03fcd10dc6..e2ef20bb81ba7d7 100644
--- a/llvm/lib/IR/PrintPasses.cpp
+++ b/llvm/lib/IR/PrintPasses.cpp
@@ -103,13 +103,6 @@ static cl::list<std::string>
"options"),
cl::CommaSeparated, cl::Hidden);
-static cl::opt<std::string> IRDumpDirectory(
- "ir-dump-directory",
- llvm::cl::desc("If specified, IR printed using the "
- "-print-[before|after]{-all} options will be dumped into "
- "files in this directory rather than written to stderr"),
- cl::Hidden, cl::value_desc("filename"));
-
/// This is a helper to determine whether to print IR before or
/// after a pass.
@@ -146,8 +139,6 @@ std::vector<std::string> llvm::printAfterPasses() {
return std::vector<std::string>(PrintAfter);
}
-StringRef llvm::irDumpDirectory() { return IRDumpDirectory; }
-
bool llvm::forcePrintModuleIR() { return PrintModuleScope; }
bool llvm::isPassInPrintList(StringRef PassName) {
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index eb2ab2795efdcef..a0d0bf68ab42596 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -122,6 +122,13 @@ static cl::opt<unsigned>
cl::desc("Print IR at pass with this number as "
"reported by print-passes-names"));
+static cl::opt<std::string> IRDumpDirectory(
+ "ir-dump-directory",
+ cl::desc("If specified, IR printed using the "
+ "-print-[before|after]{-all} options will be dumped into "
+ "files in this directory rather than written to stderr"),
+ cl::Hidden, cl::value_desc("filename"));
+
namespace {
// An option for specifying an executable that will be called with the IR
@@ -698,23 +705,27 @@ static SmallString<32> getIRFileDisplayName(Any IR) {
ResultStream << "-module";
} else if (const Function **F = any_cast<const Function *>(&IR)) {
ResultStream << "-function-";
- ResultStream << stable_hash_combine_string((*F)->getName());
+ stable_hash FunctionNameHash = stable_hash_combine_string((*F)->getName());
+ write_hex(ResultStream, FunctionNameHash, HexPrintStyle::Lower,
+ MaxHashWidth);
} else if (const LazyCallGraph::SCC **C =
any_cast<const LazyCallGraph::SCC *>(&IR)) {
ResultStream << "-scc-";
- ResultStream << stable_hash_combine_string((*C)->getName());
+ stable_hash SCCNameHash = stable_hash_combine_string((*C)->getName());
+ write_hex(ResultStream, SCCNameHash, HexPrintStyle::Lower, MaxHashWidth);
} else if (const Loop **L = any_cast<const Loop *>(&IR)) {
ResultStream << "-loop-";
- ResultStream << stable_hash_combine_string((*L)->getName());
+ stable_hash LoopNameHash = stable_hash_combine_string((*L)->getName());
+ write_hex(ResultStream, LoopNameHash, HexPrintStyle::Lower, MaxHashWidth);
} else {
llvm_unreachable("Unknown wrapped IR type");
}
return Result;
}
-SmallString<128> PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,
- Any IR) {
- const StringRef RootDirectory = irDumpDirectory();
+std::string PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,
+ Any IR) {
+ const StringRef RootDirectory = IRDumpDirectory;
assert(!RootDirectory.empty() &&
"The flag -ir-dump-directory must be passed to dump IR to files");
SmallString<128> ResultPath;
@@ -727,19 +738,26 @@ SmallString<128> PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,
FilenameStream << "-";
FilenameStream << PassName;
sys::path::append(ResultPath, Filename);
- return ResultPath;
+ return std::string(ResultPath);
}
-StringRef
-PrintIRInstrumentation::getFileSuffix(PrintIRInstrumentation::SuffixType Type) {
+enum class IRDumpFileSuffixType {
+ Before,
+ After,
+ Invalidated,
+};
+
+static StringRef getFileSuffix(IRDumpFileSuffixType Type) {
+ static constexpr std::array FileSuffixes = {"-before.ll", "-after.ll",
+ "-invalidated.ll"};
return FileSuffixes[static_cast<size_t>(Type)];
}
void PrintIRInstrumentation::pushPassRunDescriptor(
- StringRef PassID, Any IR, SmallString<128> &DumpIRFilename) {
+ StringRef PassID, Any IR, std::string &DumpIRFilename) {
const Module *M = unwrapModule(IR);
- PassRunDescriptorStack.emplace_back(M, DumpIRFilename,
- SmallString<128>(getIRName(IR)), PassID);
+ PassRunDescriptorStack.emplace_back(
+ PassRunDescriptor(M, DumpIRFilename, getIRName(IR), PassID));
}
PrintIRInstrumentation::PassRunDescriptor
@@ -774,8 +792,8 @@ void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
if (isIgnored(PassID))
return;
- SmallString<128> DumpIRFilename;
- if (!irDumpDirectory().empty() &&
+ std::string DumpIRFilename;
+ if (!IRDumpDirectory.empty() &&
(shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID)))
DumpIRFilename = fetchDumpFilename(PassID, IR);
@@ -805,7 +823,7 @@ void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {
};
if (!DumpIRFilename.empty()) {
- DumpIRFilename += getFileSuffix(SuffixType::Before);
+ DumpIRFilename += getFileSuffix(IRDumpFileSuffixType::Before);
llvm::raw_fd_ostream DumpIRFileStream{
prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
WriteIRToStream(DumpIRFileStream);
@@ -837,12 +855,14 @@ void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {
unwrapAndPrint(Stream, IR);
};
- if (!irDumpDirectory().empty()) {
+ if (!IRDumpDirectory.empty()) {
assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "
"should be set in printBeforePass");
- DumpIRFilename += getFileSuffix(SuffixType::After);
+ const std::string DumpIRFilenameWithSuffix =
+ DumpIRFilename + getFileSuffix(IRDumpFileSuffixType::After).str();
llvm::raw_fd_ostream DumpIRFileStream{
- prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
+ prepareDumpIRFileDescriptor(DumpIRFilenameWithSuffix),
+ /* shouldClose */ true};
WriteIRToStream(DumpIRFileStream, IRName);
} else {
WriteIRToStream(dbgs(), IRName);
@@ -877,12 +897,14 @@ void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {
printIR(Stream, M);
};
- if (!irDumpDirectory().empty()) {
+ if (!IRDumpDirectory.empty()) {
assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "
"should be set in printBeforePass");
- DumpIRFilename += getFileSuffix(SuffixType::Invalidated);
+ const std::string DumpIRFilenameWithSuffix =
+ DumpIRFilename + getFileSuffix(IRDumpFileSuffixType::Invalidated).str();
llvm::raw_fd_ostream DumpIRFileStream{
- prepareDumpIRFileDescriptor(DumpIRFilename), /* shouldClose */ true};
+ prepareDumpIRFileDescriptor(DumpIRFilenameWithSuffix),
+ /* shouldClose */ true};
WriteIRToStream(DumpIRFileStream, M, IRName);
} else {
WriteIRToStream(dbgs(), M, IRName);
diff --git a/llvm/test/Other/dump-before-after-invalidated.ll b/llvm/test/Other/dump-before-after-invalidated.ll
new file mode 100644
index 000000000000000..00b1a599b67f828
--- /dev/null
+++ b/llvm/test/Other/dump-before-after-invalidated.ll
@@ -0,0 +1,24 @@
+; RUN: rm -rf %t/logs
+; RUN: opt %s -disable-output -passes=loop-deletion -ir-dump-directory %t/logs -print-after=loop-deletion
+
+; RUN: ls %t/logs | FileCheck %s
+; CHECK: 2-{{[a-z0-9]+}}-loop-{{[a-z0-9]+}}-LoopDeletionPass-invalidated.ll
+
+; RUN: ls %t/logs | count 1
+; RUN: cat %t/logs/* | FileCheck %s --check-prefix=CHECK-CONTENTS
+
+; CHECK-CONTENTS: ; *** IR Dump After LoopDeletionPass on bb1 (invalidated) ***
+; CHECK-CONTENTS: define void @foo() {
+; CHECK-CONTENTS: br label %bb2
+; CHECK-CONTENTS: bb2: ; preds = %0
+; CHECK-CONTENTS: ret void
+; CHECK-CONTENTS: }
+
+
+define void @foo() {
+ br label %bb1
+bb1:
+ br i1 false, label %bb1, label %bb2
+bb2:
+ ret void
+}
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
index 4d3ea41c9e0dfbf..37489a80742b21b 100644
--- a/llvm/test/Other/dump-before-after.ll
+++ b/llvm/test/Other/dump-before-after.ll
@@ -3,9 +3,25 @@
; Basic dump before and after a single module pass
; RUN: opt %s -disable-output -passes='no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
-; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=SINGLE-PASS
-; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
-; SINGLE-PASS: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; RUN: ls %t/logs | FileCheck %s --check-prefix=SINGLE-PASS
+; RUN: ls %t/logs | count 2
+; SINGLE-PASS-DAG: 0-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
+; SINGLE-PASS-DAG: 0-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; RUN: cat %t/logs/*after.ll | FileCheck %s --check-prefix=SINGLE-PASS-CONTENTS
+
+; SINGLE-PASS-CONTENTS: ; *** IR Dump After NoOpModulePass on [module] ***
+; SINGLE-PASS-CONTENTS: ; ModuleID = '/home/nuriamari/git/llvm-project/llvm/test/Other/dump-before-after.ll'
+; SINGLE-PASS-CONTENTS: source_filename = "/home/nuriamari/git/llvm-project/llvm/test/Other/dump-before-after.ll"
+; SINGLE-PASS-CONTENTS: define void @foo() {
+; SINGLE-PASS-CONTENTS: ret void
+; SINGLE-PASS-CONTENTS: }
+; SINGLE-PASS-CONTENTS: define void @bar() {
+; SINGLE-PASS-CONTENTS: entry:
+; SINGLE-PASS-CONTENTS: br label %my-loop
+; SINGLE-PASS-CONTENTS: my-loop: ; preds = %my-loop, %entry
+; SINGLE-PASS-CONTENTS: br label %my-loop
+; SINGLE-PASS-CONTENTS: }
+
; RUN: rm -rf %t/logs
; Dump before and after multiple runs of the same module pass
@@ -15,33 +31,35 @@
; integers.
; RUN: opt %s -disable-output -passes='no-op-module,no-op-module,no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module -print-before=no-op-module
-; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-PASSES
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
-; MULTIPLE-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; RUN: ls %t/logs | FileCheck %s --check-prefix=MULTIPLE-PASSES
+; RUN: ls %t/logs | count 6
+; MULTIPLE-PASSES-DAG: 0-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES-DAG: 0-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; MULTIPLE-PASSES-DAG: 1-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES-DAG: 1-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; MULTIPLE-PASSES-DAG: 2-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
+; MULTIPLE-PASSES-DAG: 2-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; RUN: rm -rf %t/logs
; Dump before and after multiple passes, of various levels of granularity
; RUN: opt %s -disable-output -passes='no-op-module,cgscc(no-op-cgscc),function(no-op-function),function(loop(no-op-loop)),no-op-module' -ir-dump-directory %t/logs -print-after=no-op-module,no-op-cgscc,no-op-function,no-op-loop -print-before=no-op-module,no-op-cgscc,no-op-function,no-op-loop
-; RUN: find %t/logs -type f -printf '%P\n' | sort -n | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH]]-NoOpCGSCCPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH]]-NoOpCGSCCPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH:[a-z0-9]+]]-NoOpFunctionPass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH]]-NoOpFunctionPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH:[a-z0-9]+]]-NoOpFunctionPass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH]]-NoOpFunctionPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH:[a-z0-9]+]]-NoOpLoopPass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH]]-NoOpLoopPass-before.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
-; MULTIPLE-GRANULAR-PASSES: {{[0-9]+}}-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; RUN: ls %t/logs | FileCheck %s --check-prefix=MULTIPLE-GRANULAR-PASSES
+; RUN: ls %t/logs | count 14
+; MULTIPLE-GRANULAR-PASSES-DAG: 0-[[MODULE_NAME_HASH:[a-z0-9]+]]-module-NoOpModulePass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 0-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 1-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 1-[[MODULE_NAME_HASH]]-scc-[[SCC_FOO_HASH]]-NoOpCGSCCPass-before.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 2-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH:[a-z0-9]+]]-NoOpCGSCCPass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 2-[[MODULE_NAME_HASH]]-scc-[[SCC_BAR_HASH]]-NoOpCGSCCPass-before.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 3-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH:[a-z0-9]+]]-NoOpFunctionPass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 3-[[MODULE_NAME_HASH]]-function-[[FUNCTION_FOO_HASH]]-NoOpFunctionPass-before.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 4-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH:[a-z0-9]+]]-NoOpFunctionPass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 4-[[MODULE_NAME_HASH]]-function-[[FUNCTION_BAR_HASH]]-NoOpFunctionPass-before.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 9-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH:[a-z0-9]+]]-NoOpLoopPass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 9-[[MODULE_NAME_HASH]]-loop-[[LOOP_NAME_HASH]]-NoOpLoopPass-before.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 10-[[MODULE_NAME_HASH]]-module-NoOpModulePass-after.ll
+; MULTIPLE-GRANULAR-PASSES-DAG: 10-[[MODULE_NAME_HASH]]-module-NoOpModulePass-before.ll
; RUN: rm -rf %t/logs
define void @foo() {
>From 19b0fba9e26eb2d056915f383b582f71ab8896da Mon Sep 17 00:00:00 2001
From: Nuri Amari <nuriamari at fb.com>
Date: Thu, 28 Sep 2023 14:14:06 -0700
Subject: [PATCH 10/10] Fix dump-before-after.ll test
Accidentally included a machine specific path in the test.
Remove those check lines.
---
llvm/test/Other/dump-before-after.ll | 2 --
1 file changed, 2 deletions(-)
diff --git a/llvm/test/Other/dump-before-after.ll b/llvm/test/Other/dump-before-after.ll
index 37489a80742b21b..2934a77071a75f7 100644
--- a/llvm/test/Other/dump-before-after.ll
+++ b/llvm/test/Other/dump-before-after.ll
@@ -10,8 +10,6 @@
; RUN: cat %t/logs/*after.ll | FileCheck %s --check-prefix=SINGLE-PASS-CONTENTS
; SINGLE-PASS-CONTENTS: ; *** IR Dump After NoOpModulePass on [module] ***
-; SINGLE-PASS-CONTENTS: ; ModuleID = '/home/nuriamari/git/llvm-project/llvm/test/Other/dump-before-after.ll'
-; SINGLE-PASS-CONTENTS: source_filename = "/home/nuriamari/git/llvm-project/llvm/test/Other/dump-before-after.ll"
; SINGLE-PASS-CONTENTS: define void @foo() {
; SINGLE-PASS-CONTENTS: ret void
; SINGLE-PASS-CONTENTS: }
More information about the llvm-commits
mailing list