LLVM  16.0.0git
PrintPasses.cpp
Go to the documentation of this file.
1 //===- PrintPasses.cpp ----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/IR/PrintPasses.h"
13 #include "llvm/Support/Program.h"
14 #include <unordered_set>
15 
16 using namespace llvm;
17 
18 // Print IR out before/after specified passes.
20  PrintBefore("print-before",
21  llvm::cl::desc("Print IR before specified passes"),
23 
25  PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"),
27 
28 static cl::opt<bool> PrintBeforeAll("print-before-all",
29  llvm::cl::desc("Print IR before each pass"),
30  cl::init(false), cl::Hidden);
31 static cl::opt<bool> PrintAfterAll("print-after-all",
32  llvm::cl::desc("Print IR after each pass"),
33  cl::init(false), cl::Hidden);
34 
35 // Print out the IR after passes, similar to -print-after-all except that it
36 // only prints the IR after passes that change the IR. Those passes that do not
37 // make changes to the IR are reported as not making any changes. In addition,
38 // the initial IR is also reported. Other hidden options affect the output from
39 // this option. -filter-passes will limit the output to the named passes that
40 // actually change the IR and other passes are reported as filtered out. The
41 // specified passes will either be reported as making no changes (with no IR
42 // reported) or the changed IR will be reported. Also, the -filter-print-funcs
43 // and -print-module-scope options will do similar filtering based on function
44 // name, reporting changed IRs as functions(or modules if -print-module-scope is
45 // specified) for a particular function or indicating that the IR has been
46 // filtered out. The extra options can be combined, allowing only changed IRs
47 // for certain passes on certain functions to be reported in different formats,
48 // with the rest being reported as filtered out. The -print-before-changed
49 // option will print the IR as it was before each pass that changed it. The
50 // optional value of quiet will only report when the IR changes, suppressing all
51 // other messages, including the initial IR. The values "diff" and "diff-quiet"
52 // will present the changes in a form similar to a patch, in either verbose or
53 // quiet mode, respectively. The lines that are removed and added are prefixed
54 // with '-' and '+', respectively. The -filter-print-funcs and -filter-passes
55 // can be used to filter the output. This reporter relies on the linux diff
56 // utility to do comparisons and insert the prefixes. For systems that do not
57 // have the necessary facilities, the error message will be shown in place of
58 // the expected output.
60  "print-changed", cl::desc("Print changed IRs"), cl::Hidden,
62  cl::values(
63  clEnumValN(ChangePrinter::Quiet, "quiet", "Run in quiet mode"),
65  "Display patch-like changes"),
67  "Display patch-like changes in quiet mode"),
69  "Display patch-like changes with color"),
71  "Display patch-like changes in quiet mode with color"),
73  "Create a website with graphical changes"),
74  clEnumValN(ChangePrinter::DotCfgQuiet, "dot-cfg-quiet",
75  "Create a website with graphical changes in quiet mode"),
76  // Sentinel value for unspecified option.
78 
79 // An option for specifying the diff used by print-changed=[diff | diff-quiet]
81  DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"),
82  cl::desc("system diff used by change reporters"));
83 
84 static cl::opt<bool>
85  PrintModuleScope("print-module-scope",
86  cl::desc("When printing IR for print-[before|after]{-all} "
87  "always print a module IR"),
88  cl::init(false), cl::Hidden);
89 
90 // See the description for -print-changed for an explanation of the use
91 // of this option.
93  "filter-passes", cl::value_desc("pass names"),
94  cl::desc("Only consider IR changes for passes whose names "
95  "match the specified value. No-op without -print-changed"),
97 
99  PrintFuncsList("filter-print-funcs", cl::value_desc("function names"),
100  cl::desc("Only print IR for functions whose name "
101  "match this for all print-[before|after][-all] "
102  "options"),
104 
105 /// This is a helper to determine whether to print IR before or
106 /// after a pass.
107 
109  return PrintBeforeAll || !PrintBefore.empty();
110 }
111 
113  return PrintAfterAll || !PrintAfter.empty();
114 }
115 
117  ArrayRef<std::string> PassesToPrint) {
118  return llvm::is_contained(PassesToPrint, PassID);
119 }
120 
122 
124 
127 }
128 
131 }
132 
133 std::vector<std::string> llvm::printBeforePasses() {
134  return std::vector<std::string>(PrintBefore);
135 }
136 
137 std::vector<std::string> llvm::printAfterPasses() {
138  return std::vector<std::string>(PrintAfter);
139 }
140 
142 
144  static std::unordered_set<std::string> Set(FilterPasses.begin(),
145  FilterPasses.end());
146  return Set.empty() || Set.count(std::string(PassName));
147 }
148 
149 bool llvm::isFilterPassesEmpty() { return FilterPasses.empty(); }
150 
152  static std::unordered_set<std::string> PrintFuncNames(PrintFuncsList.begin(),
153  PrintFuncsList.end());
154  return PrintFuncNames.empty() ||
155  PrintFuncNames.count(std::string(FunctionName));
156 }
157 
158 std::string llvm::doSystemDiff(StringRef Before, StringRef After,
159  StringRef OldLineFormat, StringRef NewLineFormat,
160  StringRef UnchangedLineFormat) {
161  StringRef SR[2]{Before, After};
162  // Store the 2 bodies into temporary files and call diff on them
163  // to get the body of the node.
164  const unsigned NumFiles = 3;
165  static std::string FileName[NumFiles];
166  static int FD[NumFiles]{-1, -1, -1};
167  for (unsigned I = 0; I < NumFiles; ++I) {
168  if (FD[I] == -1) {
170  std::error_code EC =
171  sys::fs::createTemporaryFile("tmpdiff", "txt", FD[I], SV);
172  if (EC)
173  return "Unable to create temporary file.";
174  FileName[I] = Twine(SV).str();
175  }
176  // The third file is used as the result of the diff.
177  if (I == NumFiles - 1)
178  break;
179 
180  std::error_code EC = sys::fs::openFileForWrite(FileName[I], FD[I]);
181  if (EC)
182  return "Unable to open temporary file for writing.";
183 
184  raw_fd_ostream OutStream(FD[I], /*shouldClose=*/true);
185  if (FD[I] == -1)
186  return "Error opening file for writing.";
187  OutStream << SR[I];
188  }
189 
191  if (!DiffExe)
192  return "Unable to find diff executable.";
193 
194  SmallString<128> OLF, NLF, ULF;
195  ("--old-line-format=" + OldLineFormat).toVector(OLF);
196  ("--new-line-format=" + NewLineFormat).toVector(NLF);
197  ("--unchanged-line-format=" + UnchangedLineFormat).toVector(ULF);
198 
199  StringRef Args[] = {DiffBinary, "-w", "-d", OLF,
200  NLF, ULF, FileName[0], FileName[1]};
201  Optional<StringRef> Redirects[] = {None, StringRef(FileName[2]), None};
202  int Result = sys::ExecuteAndWait(*DiffExe, Args, None, Redirects);
203  if (Result < 0)
204  return "Error executing system diff.";
205  std::string Diff;
206  auto B = MemoryBuffer::getFile(FileName[2]);
207  if (B && *B)
208  Diff = (*B)->getBuffer().str();
209  else
210  return "Unable to read result.";
211 
212  // Clean up.
213  for (const std::string &I : FileName) {
214  std::error_code EC = sys::fs::remove(I);
215  if (EC)
216  return "Unable to remove temporary file.";
217  }
218  return Diff;
219 }
llvm::sys::findProgramByName
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
MemoryBuffer.h
llvm::sys::fs::openFileForWrite
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
Definition: FileSystem.h:1065
llvm::PrintChanged
cl::opt< ChangePrinter > PrintChanged
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FileSystem.h
llvm::ChangePrinter::Quiet
@ Quiet
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1182
llvm::cl::CommaSeparated
@ CommaSeparated
Definition: CommandLine.h:165
llvm::cl::ValueOptional
@ ValueOptional
Definition: CommandLine.h:132
llvm::ChangePrinter::ColourDiffVerbose
@ ColourDiffVerbose
llvm::cl::Hidden
@ Hidden
Definition: CommandLine.h:139
PrintAfter
static cl::list< std::string > PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), cl::CommaSeparated, cl::Hidden)
llvm::Optional
Definition: APInt.h:33
llvm::shouldPrintBeforeAll
bool shouldPrintBeforeAll()
Definition: PrintPasses.cpp:121
DiffBinary
static cl::opt< std::string > DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"), cl::desc("system diff used by change reporters"))
llvm::shouldPrintAfterSomePass
bool shouldPrintAfterSomePass()
Definition: PrintPasses.cpp:112
CommandLine.h
llvm::MemoryBuffer::getFile
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Definition: MemoryBuffer.cpp:239
PrintBefore
static cl::list< std::string > PrintBefore("print-before", llvm::cl::desc("Print IR before specified passes"), cl::CommaSeparated, cl::Hidden)
llvm::ChangePrinter::Verbose
@ Verbose
llvm::ChangePrinter::None
@ None
llvm::ChangePrinter::DiffQuiet
@ DiffQuiet
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
PrintModuleScope
static cl::opt< bool > PrintModuleScope("print-module-scope", cl::desc("When printing IR for print-[before|after]{-all} " "always print a module IR"), cl::init(false), cl::Hidden)
llvm::shouldPrintBeforeSomePass
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
Definition: PrintPasses.cpp:108
PrintPasses.h
llvm::None
const NoneType None
Definition: None.h:24
llvm::SmallString< 128 >
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
llvm::cl::opt< bool >
llvm::cl::values
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
Definition: CommandLine.h:692
llvm::shouldPrintAfterAll
bool shouldPrintAfterAll()
Definition: PrintPasses.cpp:123
llvm::ChangePrinter::DotCfgVerbose
@ DotCfgVerbose
PrintFuncsList
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] " "options"), cl::CommaSeparated, cl::Hidden)
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::ChangePrinter::DotCfgQuiet
@ DotCfgQuiet
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:439
llvm::is_contained
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1673
llvm::isFunctionInPrintList
bool isFunctionInPrintList(StringRef FunctionName)
Definition: PrintPasses.cpp:151
llvm::printBeforePasses
std::vector< std::string > printBeforePasses()
Definition: PrintPasses.cpp:133
llvm::printAfterPasses
std::vector< std::string > printAfterPasses()
Definition: PrintPasses.cpp:137
llvm::sys::fs::remove
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
llvm::sys::fs::createTemporaryFile
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
Definition: Path.cpp:863
llvm::ArrayRef< std::string >
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
clEnumValN
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
Definition: CommandLine.h:667
FilterPasses
static cl::list< std::string > FilterPasses("filter-passes", cl::value_desc("pass names"), cl::desc("Only consider IR changes for passes whose names " "match the specified value. No-op without -print-changed"), cl::CommaSeparated, cl::Hidden)
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:440
PrintBeforeAll
static cl::opt< bool > PrintBeforeAll("print-before-all", llvm::cl::desc("Print IR before each pass"), cl::init(false), cl::Hidden)
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
PrintAfterAll
static cl::opt< bool > PrintAfterAll("print-after-all", llvm::cl::desc("Print IR after each pass"), cl::init(false), cl::Hidden)
llvm::doSystemDiff
std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)
Definition: PrintPasses.cpp:158
llvm::isPassInPrintList
bool isPassInPrintList(StringRef PassName)
Definition: PrintPasses.cpp:143
llvm::shouldPrintAfterPass
bool shouldPrintAfterPass(StringRef PassID)
Definition: PrintPasses.cpp:129
llvm::cl::value_desc
Definition: CommandLine.h:421
llvm::shouldPrintBeforePass
bool shouldPrintBeforePass(StringRef PassID)
Definition: PrintPasses.cpp:125
llvm::ChangePrinter::ColourDiffQuiet
@ ColourDiffQuiet
Program.h
llvm::sys::ExecuteAndWait
int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, Optional< ArrayRef< StringRef >> Env=None, ArrayRef< Optional< StringRef >> Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, Optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
Definition: Program.cpp:31
llvm::ErrorOr
Represents either an error or a value T.
Definition: ErrorOr.h:56
shouldPrintBeforeOrAfterPass
static bool shouldPrintBeforeOrAfterPass(StringRef PassID, ArrayRef< std::string > PassesToPrint)
Definition: PrintPasses.cpp:116
llvm::forcePrintModuleIR
bool forcePrintModuleIR()
Definition: PrintPasses.cpp:141
llvm::ChangePrinter::DiffVerbose
@ DiffVerbose
llvm::isFilterPassesEmpty
bool isFilterPassesEmpty()
Definition: PrintPasses.cpp:149
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:394
llvm::cl::desc
Definition: CommandLine.h:412
PassName
static const char PassName[]
Definition: X86LowerAMXIntrinsics.cpp:671
llvm::cl::list
Definition: CommandLine.h:1608