1e8d8bef9SDimitry Andric //===- PrintPasses.cpp ----------------------------------------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #include "llvm/IR/PrintPasses.h" 10e8d8bef9SDimitry Andric #include "llvm/Support/CommandLine.h" 11e8d8bef9SDimitry Andric #include <unordered_set> 12e8d8bef9SDimitry Andric 13e8d8bef9SDimitry Andric using namespace llvm; 14e8d8bef9SDimitry Andric 15e8d8bef9SDimitry Andric // Print IR out before/after specified passes. 16e8d8bef9SDimitry Andric static cl::list<std::string> 17e8d8bef9SDimitry Andric PrintBefore("print-before", 18e8d8bef9SDimitry Andric llvm::cl::desc("Print IR before specified passes"), 19e8d8bef9SDimitry Andric cl::CommaSeparated, cl::Hidden); 20e8d8bef9SDimitry Andric 21e8d8bef9SDimitry Andric static cl::list<std::string> 22e8d8bef9SDimitry Andric PrintAfter("print-after", llvm::cl::desc("Print IR after specified passes"), 23e8d8bef9SDimitry Andric cl::CommaSeparated, cl::Hidden); 24e8d8bef9SDimitry Andric 25e8d8bef9SDimitry Andric static cl::opt<bool> PrintBeforeAll("print-before-all", 26e8d8bef9SDimitry Andric llvm::cl::desc("Print IR before each pass"), 27e8d8bef9SDimitry Andric cl::init(false), cl::Hidden); 28e8d8bef9SDimitry Andric static cl::opt<bool> PrintAfterAll("print-after-all", 29e8d8bef9SDimitry Andric llvm::cl::desc("Print IR after each pass"), 30e8d8bef9SDimitry Andric cl::init(false), cl::Hidden); 31e8d8bef9SDimitry Andric 32*972a253aSDimitry Andric // Print out the IR after passes, similar to -print-after-all except that it 33*972a253aSDimitry Andric // only prints the IR after passes that change the IR. Those passes that do not 34*972a253aSDimitry Andric // make changes to the IR are reported as not making any changes. In addition, 35*972a253aSDimitry Andric // the initial IR is also reported. Other hidden options affect the output from 36*972a253aSDimitry Andric // this option. -filter-passes will limit the output to the named passes that 37*972a253aSDimitry Andric // actually change the IR and other passes are reported as filtered out. The 38*972a253aSDimitry Andric // specified passes will either be reported as making no changes (with no IR 39*972a253aSDimitry Andric // reported) or the changed IR will be reported. Also, the -filter-print-funcs 40*972a253aSDimitry Andric // and -print-module-scope options will do similar filtering based on function 41*972a253aSDimitry Andric // name, reporting changed IRs as functions(or modules if -print-module-scope is 42*972a253aSDimitry Andric // specified) for a particular function or indicating that the IR has been 43*972a253aSDimitry Andric // filtered out. The extra options can be combined, allowing only changed IRs 44*972a253aSDimitry Andric // for certain passes on certain functions to be reported in different formats, 45*972a253aSDimitry Andric // with the rest being reported as filtered out. The -print-before-changed 46*972a253aSDimitry Andric // option will print the IR as it was before each pass that changed it. The 47*972a253aSDimitry Andric // optional value of quiet will only report when the IR changes, suppressing all 48*972a253aSDimitry Andric // other messages, including the initial IR. The values "diff" and "diff-quiet" 49*972a253aSDimitry Andric // will present the changes in a form similar to a patch, in either verbose or 50*972a253aSDimitry Andric // quiet mode, respectively. The lines that are removed and added are prefixed 51*972a253aSDimitry Andric // with '-' and '+', respectively. The -filter-print-funcs and -filter-passes 52*972a253aSDimitry Andric // can be used to filter the output. This reporter relies on the linux diff 53*972a253aSDimitry Andric // utility to do comparisons and insert the prefixes. For systems that do not 54*972a253aSDimitry Andric // have the necessary facilities, the error message will be shown in place of 55*972a253aSDimitry Andric // the expected output. 56*972a253aSDimitry Andric cl::opt<ChangePrinter> llvm::PrintChanged( 57*972a253aSDimitry Andric "print-changed", cl::desc("Print changed IRs"), cl::Hidden, 58*972a253aSDimitry Andric cl::ValueOptional, cl::init(ChangePrinter::None), 59*972a253aSDimitry Andric cl::values( 60*972a253aSDimitry Andric clEnumValN(ChangePrinter::Quiet, "quiet", "Run in quiet mode"), 61*972a253aSDimitry Andric clEnumValN(ChangePrinter::DiffVerbose, "diff", 62*972a253aSDimitry Andric "Display patch-like changes"), 63*972a253aSDimitry Andric clEnumValN(ChangePrinter::DiffQuiet, "diff-quiet", 64*972a253aSDimitry Andric "Display patch-like changes in quiet mode"), 65*972a253aSDimitry Andric clEnumValN(ChangePrinter::ColourDiffVerbose, "cdiff", 66*972a253aSDimitry Andric "Display patch-like changes with color"), 67*972a253aSDimitry Andric clEnumValN(ChangePrinter::ColourDiffQuiet, "cdiff-quiet", 68*972a253aSDimitry Andric "Display patch-like changes in quiet mode with color"), 69*972a253aSDimitry Andric clEnumValN(ChangePrinter::DotCfgVerbose, "dot-cfg", 70*972a253aSDimitry Andric "Create a website with graphical changes"), 71*972a253aSDimitry Andric clEnumValN(ChangePrinter::DotCfgQuiet, "dot-cfg-quiet", 72*972a253aSDimitry Andric "Create a website with graphical changes in quiet mode"), 73*972a253aSDimitry Andric // Sentinel value for unspecified option. 74*972a253aSDimitry Andric clEnumValN(ChangePrinter::Verbose, "", ""))); 75*972a253aSDimitry Andric 76e8d8bef9SDimitry Andric static cl::opt<bool> 77e8d8bef9SDimitry Andric PrintModuleScope("print-module-scope", 78e8d8bef9SDimitry Andric cl::desc("When printing IR for print-[before|after]{-all} " 79e8d8bef9SDimitry Andric "always print a module IR"), 80e8d8bef9SDimitry Andric cl::init(false), cl::Hidden); 81e8d8bef9SDimitry Andric 82e8d8bef9SDimitry Andric static cl::list<std::string> 83e8d8bef9SDimitry Andric PrintFuncsList("filter-print-funcs", cl::value_desc("function names"), 84e8d8bef9SDimitry Andric cl::desc("Only print IR for functions whose name " 85e8d8bef9SDimitry Andric "match this for all print-[before|after][-all] " 86e8d8bef9SDimitry Andric "options"), 87e8d8bef9SDimitry Andric cl::CommaSeparated, cl::Hidden); 88e8d8bef9SDimitry Andric 89e8d8bef9SDimitry Andric /// This is a helper to determine whether to print IR before or 90e8d8bef9SDimitry Andric /// after a pass. 91e8d8bef9SDimitry Andric 92e8d8bef9SDimitry Andric bool llvm::shouldPrintBeforeSomePass() { 93e8d8bef9SDimitry Andric return PrintBeforeAll || !PrintBefore.empty(); 94e8d8bef9SDimitry Andric } 95e8d8bef9SDimitry Andric 96e8d8bef9SDimitry Andric bool llvm::shouldPrintAfterSomePass() { 97e8d8bef9SDimitry Andric return PrintAfterAll || !PrintAfter.empty(); 98e8d8bef9SDimitry Andric } 99e8d8bef9SDimitry Andric 100e8d8bef9SDimitry Andric static bool shouldPrintBeforeOrAfterPass(StringRef PassID, 101e8d8bef9SDimitry Andric ArrayRef<std::string> PassesToPrint) { 102e8d8bef9SDimitry Andric return llvm::is_contained(PassesToPrint, PassID); 103e8d8bef9SDimitry Andric } 104e8d8bef9SDimitry Andric 105e8d8bef9SDimitry Andric bool llvm::shouldPrintBeforeAll() { return PrintBeforeAll; } 106e8d8bef9SDimitry Andric 107e8d8bef9SDimitry Andric bool llvm::shouldPrintAfterAll() { return PrintAfterAll; } 108e8d8bef9SDimitry Andric 109e8d8bef9SDimitry Andric bool llvm::shouldPrintBeforePass(StringRef PassID) { 110e8d8bef9SDimitry Andric return PrintBeforeAll || shouldPrintBeforeOrAfterPass(PassID, PrintBefore); 111e8d8bef9SDimitry Andric } 112e8d8bef9SDimitry Andric 113e8d8bef9SDimitry Andric bool llvm::shouldPrintAfterPass(StringRef PassID) { 114e8d8bef9SDimitry Andric return PrintAfterAll || shouldPrintBeforeOrAfterPass(PassID, PrintAfter); 115e8d8bef9SDimitry Andric } 116e8d8bef9SDimitry Andric 117e8d8bef9SDimitry Andric std::vector<std::string> llvm::printBeforePasses() { 118e8d8bef9SDimitry Andric return std::vector<std::string>(PrintBefore); 119e8d8bef9SDimitry Andric } 120e8d8bef9SDimitry Andric 121e8d8bef9SDimitry Andric std::vector<std::string> llvm::printAfterPasses() { 122e8d8bef9SDimitry Andric return std::vector<std::string>(PrintAfter); 123e8d8bef9SDimitry Andric } 124e8d8bef9SDimitry Andric 125e8d8bef9SDimitry Andric bool llvm::forcePrintModuleIR() { return PrintModuleScope; } 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric bool llvm::isFunctionInPrintList(StringRef FunctionName) { 128e8d8bef9SDimitry Andric static std::unordered_set<std::string> PrintFuncNames(PrintFuncsList.begin(), 129e8d8bef9SDimitry Andric PrintFuncsList.end()); 130e8d8bef9SDimitry Andric return PrintFuncNames.empty() || 131e8d8bef9SDimitry Andric PrintFuncNames.count(std::string(FunctionName)); 132e8d8bef9SDimitry Andric } 133