LLVM 24.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
10#include "llvm/ADT/STLExtras.h"
13#include "llvm/ADT/StringSet.h"
14#include "llvm/ADT/Twine.h"
15#include "llvm/IR/BasicBlock.h"
17#include "llvm/IR/DebugLoc.h"
18#include "llvm/IR/Function.h"
19#include "llvm/IR/Instruction.h"
21#include "llvm/Support/Errc.h"
26#include "llvm/Support/Path.h"
29#include <vector>
30
31using namespace llvm;
32
33// Print IR out before/after specified passes.
35 PrintBefore("print-before",
36 llvm::cl::desc("Print IR before specified passes"),
38
40 PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"),
42
43static cl::opt<bool> PrintBeforeAll("print-before-all",
44 llvm::cl::desc("Print IR before each pass"),
45 cl::init(false), cl::Hidden);
46static cl::opt<bool> PrintAfterAll("print-after-all",
47 llvm::cl::desc("Print IR after each pass"),
48 cl::init(false), cl::Hidden);
49
50// Print out the IR after passes, similar to -print-after-all except that it
51// only prints the IR after passes that change the IR. Those passes that do not
52// make changes to the IR are reported as not making any changes. In addition,
53// the initial IR is also reported. Other hidden options affect the output from
54// this option. -filter-passes will limit the output to the named passes that
55// actually change the IR and other passes are reported as filtered out. The
56// specified passes will either be reported as making no changes (with no IR
57// reported) or the changed IR will be reported. Also, the -filter-print-funcs,
58// -filter-print-source-locs and -print-module-scope options will do similar
59// filtering based on function name or source location, reporting changed IRs as
60// functions(or modules if -print-module-scope is specified) for a particular
61// function or indicating that the IR has been filtered out. The extra options
62// can be combined, allowing only changed IRs for certain passes on certain
63// functions or source locations to be reported in different formats, with the
64// rest being reported as filtered out. The -print-before-changed
65// option will print the IR as it was before each pass that changed it. The
66// optional value of quiet will only report when the IR changes, suppressing all
67// other messages, including the initial IR. The values "diff" and "diff-quiet"
68// will present the changes in a form similar to a patch, in either verbose or
69// quiet mode, respectively. The lines that are removed and added are prefixed
70// with '-' and '+', respectively. The -filter-print-funcs,
71// -filter-print-source-locs and -filter-passes can be used to filter the
72// output. This reporter relies on the linux diff utility to do comparisons and
73// insert the prefixes. For systems that do not have the necessary facilities,
74// the error message will be shown in place of the expected output.
76 "print-changed", cl::desc("Print changed IRs"), cl::Hidden,
79 clEnumValN(ChangePrinter::Quiet, "quiet", "Run in quiet mode"),
81 "Display patch-like changes"),
83 "Display patch-like changes in quiet mode"),
85 "Display patch-like changes with color"),
87 "Display patch-like changes in quiet mode with color"),
89 "Create a website with graphical changes"),
91 "Create a website with graphical changes in quiet mode"),
92 // Sentinel value for unspecified option.
94
95// An option for specifying the diff used by print-changed=[diff | diff-quiet]
97 DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"),
98 cl::desc("system diff used by change reporters"));
99
100static cl::opt<bool>
101 PrintModuleScope("print-module-scope",
102 cl::desc("When printing IR for print-[before|after]{-all} "
103 "always print a module IR"),
104 cl::init(false), cl::Hidden);
105
107 "print-loop-func-scope",
108 cl::desc("When printing IR for print-[before|after]{-all} "
109 "for a loop pass, always print function IR"),
110 cl::init(false), cl::Hidden);
111
112// See the description for -print-changed for an explanation of the use
113// of this option.
115 "filter-passes", cl::value_desc("pass names"),
116 cl::desc("Only consider IR changes for passes whose names "
117 "match the specified value. No-op without -print-changed"),
119
121 PrintFuncsList("filter-print-funcs", cl::value_desc("function names"),
122 cl::desc("Only print IR for functions whose name "
123 "match this for all print-[before|after][-all] "
124 "options"),
126
128 "filter-print-source-locs", cl::value_desc("file:line[,line-line][,line]"),
129 cl::desc("Only print IR containing matching source locations"), cl::Hidden);
130
131/// This is a helper to determine whether to print IR before or
132/// after a pass.
133
135 return PrintBeforeAll || !PrintBefore.empty();
136}
137
139 return PrintAfterAll || !PrintAfter.empty();
140}
141
143 ArrayRef<std::string> PassesToPrint) {
144 return llvm::is_contained(PassesToPrint, PassID);
145}
146
148
150
154
158
159std::vector<std::string> llvm::printBeforePasses() {
160 return std::vector<std::string>(PrintBefore);
161}
162
163std::vector<std::string> llvm::printAfterPasses() {
164 return std::vector<std::string>(PrintAfter);
165}
166
168
170
172 static const StringSet<> Set(llvm::from_range, FilterPasses);
173 return Set.empty() || Set.contains(PassName);
174}
175
176bool llvm::isFilterPassesEmpty() { return FilterPasses.empty(); }
177
179 static const StringSet<> PrintFuncNames(llvm::from_range, PrintFuncsList);
180 return PrintFuncNames.empty() || PrintFuncNames.contains(FunctionName) ||
181 PrintFuncNames.contains("*");
182}
183
184namespace {
185
186struct PrintLineRange {
187 unsigned First;
188 unsigned Last;
189};
190
191struct PrintSourceLocFilter {
192 std::string File;
194};
195
196[[noreturn]] void reportBadSourceLocFilter(StringRef Filter) {
197 report_fatal_error(Twine("Invalid -filter-print-source-locs value '") +
198 Filter + "'. Expected file:line[,line-line][,line].");
199}
200
201std::string normalizeSlashes(StringRef Path) {
203}
204
205bool parseLineNumber(StringRef LineText, unsigned &Line) {
206 return !LineText.empty() && !LineText.getAsInteger(10, Line);
207}
208
209PrintLineRange parseLineRange(StringRef RangeText, StringRef FullFilter) {
210 auto [FirstText, LastText] = RangeText.split('-');
211
212 unsigned First;
213 if (!parseLineNumber(FirstText, First))
214 reportBadSourceLocFilter(FullFilter);
215
216 if (!RangeText.contains('-'))
217 return {First, First};
218
219 unsigned Last;
220 if (!parseLineNumber(LastText, Last) || Last < First)
221 reportBadSourceLocFilter(FullFilter);
222
223 return {First, Last};
224}
225
226std::vector<PrintSourceLocFilter> parseSourceLocFilters() {
227 std::vector<PrintSourceLocFilter> Result;
228 for (const std::string &RawFilter : PrintSourceLocs) {
229 StringRef Filter(RawFilter);
230 auto [File, LineList] = Filter.rsplit(':');
231 if (File.empty() || LineList.empty())
232 reportBadSourceLocFilter(Filter);
233
234 PrintSourceLocFilter Parsed;
235 Parsed.File = normalizeSlashes(File);
236 for (StringRef RangeText : llvm::split(LineList, ",")) {
237 Parsed.Lines.push_back(parseLineRange(RangeText, Filter));
238 }
239 Result.push_back(std::move(Parsed));
240 }
241 return Result;
242}
243
244ArrayRef<PrintSourceLocFilter> getSourceLocFilters() {
245 static const std::vector<PrintSourceLocFilter> Filters =
246 parseSourceLocFilters();
247 return Filters;
248}
249
250std::string makeDebugLocPath(StringRef Directory, StringRef Filename) {
251 std::string NormalizedFilename = normalizeSlashes(Filename);
252 if (Directory.empty() || sys::path::is_absolute(NormalizedFilename))
253 return NormalizedFilename;
254
255 std::string NormalizedDirectory = normalizeSlashes(Directory);
256 if (NormalizedDirectory.empty())
257 return NormalizedFilename;
258 if (NormalizedDirectory.back() == '/')
259 return NormalizedDirectory + NormalizedFilename;
260 return NormalizedDirectory + "/" + NormalizedFilename;
261}
262
263bool matchesFile(StringRef FilterFile, StringRef Directory,
265 std::string LocFile = normalizeSlashes(Filename);
266 std::string LocPath = makeDebugLocPath(Directory, Filename);
267
268 // Accept an exact filename or path, a basename, or a path suffix so the
269 // filter may omit leading directories.
270 if (FilterFile == LocFile || FilterFile == LocPath)
271 return true;
272
273 StringRef LocFileRef(LocFile);
274 StringRef LocPathRef(LocPath);
275 if (sys::path::filename(LocFileRef) == FilterFile)
276 return true;
277
278 std::string Suffix = (Twine("/") + FilterFile).str();
279 return LocFileRef.ends_with(Suffix) || LocPathRef.ends_with(Suffix);
280}
281
282bool matchesLine(ArrayRef<PrintLineRange> Ranges, unsigned Line) {
283 return any_of(Ranges, [Line](const PrintLineRange &Range) {
284 return Range.First <= Line && Line <= Range.Last;
285 });
286}
287
288bool matchesSourceLocFilter(const DebugLoc &Loc,
289 const PrintSourceLocFilter &Filter) {
290 auto *Scope = dyn_cast_or_null<DIScope>(Loc.getScope());
291 return Scope &&
292 matchesFile(Filter.File, Scope->getDirectory(),
293 Scope->getFilename()) &&
294 matchesLine(Filter.Lines, Loc.getLine());
295}
296
297} // namespace
298
300 ArrayRef<PrintSourceLocFilter> Filters = getSourceLocFilters();
301 if (Filters.empty())
302 return true;
303
304 for (DebugLoc CurLoc = Loc; CurLoc; CurLoc = CurLoc.getInlinedAt()) {
305 if (any_of(Filters, [&CurLoc](const PrintSourceLocFilter &Filter) {
306 return matchesSourceLocFilter(CurLoc, Filter);
307 }))
308 return true;
309 }
310 return false;
311}
312
313bool llvm::isSourceLocFilterEmpty() { return getSourceLocFilters().empty(); }
314
318
320 bool SourceLocFilterEmpty = isSourceLocFilterEmpty();
321 if (!isFunctionInPrintList(F.getName()))
322 return false;
323
324 if (SourceLocFilterEmpty)
325 return true;
326
327 for (const BasicBlock &BB : F)
328 for (const Instruction &I : BB)
329 if (isSourceLocInPrintList(I.getDebugLoc()))
330 return true;
331 return false;
332}
333
335 unsigned N) {
336 std::error_code RC;
337 for (unsigned I = 0; I < N; ++I) {
338 std::error_code EC = sys::fs::remove(FileName[I]);
339 if (EC)
340 RC = EC;
341 }
342 return RC;
343}
344
347 SmallVector<std::string> &FileName) {
348 assert(FD.size() >= SR.size() && FileName.size() == FD.size() &&
349 "Unexpected array sizes");
350 std::error_code EC;
351 unsigned I = 0;
352 for (; I < FD.size(); ++I) {
353 if (FD[I] == -1) {
355 EC = sys::fs::createTemporaryFile("tmpfile", "txt", FD[I], SV);
356 if (EC)
357 break;
358 FileName[I] = Twine(SV).str();
359 }
360 if (I < SR.size()) {
361 EC = sys::fs::openFileForWrite(FileName[I], FD[I]);
362 if (EC)
363 break;
364 raw_fd_ostream OutStream(FD[I], /*shouldClose=*/true);
365 if (FD[I] == -1) {
367 break;
368 }
369 OutStream << SR[I];
370 }
371 }
372 if (EC && I > 0)
373 // clean up created temporary files
374 cleanUpTempFilesImpl(FileName, I);
375 return EC;
376}
377
379 return cleanUpTempFilesImpl(FileName, FileName.size());
380}
381
382std::string llvm::doSystemDiff(StringRef Before, StringRef After,
383 StringRef OldLineFormat, StringRef NewLineFormat,
384 StringRef UnchangedLineFormat) {
385 auto BypassSandbox = sys::sandbox::scopedDisable();
386
387 // Store the 2 bodies into temporary files and call diff on them
388 // to get the body of the node.
389 static SmallVector<int> FD{-1, -1, -1};
390 SmallVector<StringRef> SR{Before, After};
391 static SmallVector<std::string> FileName{"", "", ""};
392 if (prepareTempFiles(FD, SR, FileName))
393 return "Unable to create temporary file.";
394
396 if (!DiffExe)
397 return "Unable to find diff executable.";
398
399 SmallString<128> OLF, NLF, ULF;
400 ("--old-line-format=" + OldLineFormat).toVector(OLF);
401 ("--new-line-format=" + NewLineFormat).toVector(NLF);
402 ("--unchanged-line-format=" + UnchangedLineFormat).toVector(ULF);
403
404 StringRef Args[] = {DiffBinary, "-w", "-d", OLF,
405 NLF, ULF, FileName[0], FileName[1]};
406 std::optional<StringRef> Redirects[] = {std::nullopt, StringRef(FileName[2]),
407 std::nullopt};
408 int Result = sys::ExecuteAndWait(*DiffExe, Args, std::nullopt, Redirects);
409 if (Result < 0)
410 return "Error executing system diff.";
411 std::string Diff;
412 auto B = MemoryBuffer::getFile(FileName[2]);
413 if (B && *B)
414 Diff = (*B)->getBuffer().str();
415 else
416 return "Unable to read result.";
417
418 if (cleanUpTempFiles(FileName))
419 return "Unable to remove temporary file.";
420
421 return Diff;
422}
423
426 StringRef IRName, bool IsInteresting,
427 bool ShouldReport) {
428 if (!ShouldReport && IsInteresting)
429 return;
430
431 if (IsInteresting && Before != After) {
432 if (After.empty() &&
433 llvm::is_contained({ChangePrinter::Quiet, ChangePrinter::Verbose,
434 ChangePrinter::DotCfgQuiet,
435 ChangePrinter::DotCfgVerbose},
436 PrintChanged.getValue())) {
437 errs() << ("*** IR Deleted After " + PassName + " (" + PassID + ") on " +
438 IRName + " ***\n");
439 return;
440 }
441
442 errs() << ("*** IR Dump After " + PassName + " (" + PassID + ") on " +
443 IRName + " ***\n");
444 switch (PrintChanged) {
449 case ChangePrinter::DotCfgQuiet: // unimplemented
450 case ChangePrinter::DotCfgVerbose: // unimplemented
451 errs() << After;
452 break;
457 bool Color = llvm::is_contained(
459 PrintChanged.getValue());
460 StringRef Removed = Color ? "\033[31m-%l\033[0m\n" : "-%l\n";
461 StringRef Added = Color ? "\033[32m+%l\033[0m\n" : "+%l\n";
462 StringRef NoChange = " %l\n";
463 errs() << doSystemDiff(Before, After, Removed, Added, NoChange);
464 break;
465 }
466 }
470 PrintChanged.getValue())) {
471 const char *Reason =
472 IsInteresting ? " omitted because no change" : " filtered out";
473 errs() << "*** IR Dump After " << PassName;
474 if (!PassID.empty())
475 errs() << " (" << PassID << ")";
476 errs() << " on " << IRName + Reason + " ***\n";
477 }
478}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
static bool shouldPrintBeforeOrAfterPass(StringRef PassID, ArrayRef< std::string > PassesToPrint)
static cl::opt< bool > PrintBeforeAll("print-before-all", llvm::cl::desc("Print IR before each pass"), cl::init(false), cl::Hidden)
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)
static cl::list< std::string > PrintBefore("print-before", llvm::cl::desc("Print IR before specified passes"), cl::CommaSeparated, cl::Hidden)
static cl::list< std::string > PrintSourceLocs("filter-print-source-locs", cl::value_desc("file:line[,line-line][,line]"), cl::desc("Only print IR containing matching source locations"), cl::Hidden)
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)
static cl::list< std::string > PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), cl::CommaSeparated, cl::Hidden)
static cl::opt< bool > LoopPrintFuncScope("print-loop-func-scope", cl::desc("When printing IR for print-[before|after]{-all} " "for a loop pass, always print function IR"), cl::init(false), cl::Hidden)
static cl::opt< bool > PrintAfterAll("print-after-all", llvm::cl::desc("Print IR after each pass"), cl::init(false), cl::Hidden)
static cl::opt< std::string > DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"), cl::desc("system diff used by change reporters"))
std::error_code cleanUpTempFilesImpl(ArrayRef< std::string > FileName, unsigned N)
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)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
StringSet - A set-like wrapper for the StringMap.
static const char PassName[]
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
LLVM Basic Block Representation.
Definition BasicBlock.h:62
A debug info location.
Definition DebugLoc.h:126
Represents either an error or a value T.
Definition ErrorOr.h:56
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool empty() const
Definition StringMap.h:103
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition StringRef.h:736
bool getAsInteger(unsigned Radix, T &Result) const
Parse the current string as an integer of the specified radix.
Definition StringRef.h:490
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
StringSet - A wrapper for StringMap that provides set-like functionality.
Definition StringSet.h:25
bool contains(StringRef key) const
Check if the set contains the given key.
Definition StringSet.h:60
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
A raw_ostream that writes to a file descriptor.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
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...
LLVM_ABI 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:936
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:594
LLVM_ABI std::string convert_to_slash(StringRef path, Style style=Style::native)
Replaces backslashes with slashes if Windows.
Definition Path.cpp:585
LLVM_ABI bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition Path.cpp:688
ScopedSetting scopedDisable()
Definition IOSandbox.h:36
LLVM_ABI ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
LLVM_ABI int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
Definition Program.cpp:32
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isSourceLocInPrintList(const DebugLoc &Loc)
LLVM_ABI std::error_code prepareTempFiles(SmallVector< int > &FD, ArrayRef< StringRef > SR, SmallVector< std::string > &FileName)
LLVM_ABI bool forcePrintModuleIR()
std::error_code make_error_code(BitcodeError E)
LLVM_ABI std::vector< std::string > printAfterPasses()
LLVM_ABI void reportChangedIR(StringRef Before, StringRef After, StringRef PassName, StringRef PassID, StringRef IRName, bool IsInteresting, bool ShouldReport)
constexpr from_range_t from_range
LLVM_ABI bool shouldPrintBeforeAll()
LLVM_ABI bool shouldPrintAfterAll()
LLVM_ABI cl::opt< ChangePrinter > PrintChanged
@ io_error
Definition Errc.h:58
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
LLVM_ABI std::vector< std::string > printBeforePasses()
LLVM_ABI bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
LLVM_ABI bool shouldPrintAfterSomePass()
LLVM_ABI bool isFunctionInPrintList(StringRef FunctionName)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
LLVM_ABI bool isPassInPrintList(StringRef PassName)
LLVM_ABI bool isSourceLocFilterEmpty()
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...
LLVM_ABI bool shouldPrintFunction(const Function &F)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI std::error_code cleanUpTempFiles(ArrayRef< std::string > FileName)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
LLVM_ABI std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
LLVM_ABI bool shouldPrintBeforePass(StringRef PassID)
LLVM_ABI bool shouldPrintAfterPass(StringRef PassID)
LLVM_ABI bool isFilterPassesEmpty()
LLVM_ABI bool shouldPrintAllFunctions()
LLVM_ABI bool forcePrintFuncIR()
#define N