43#include <unordered_map>
44#include <unordered_set>
52#ifdef EXPENSIVE_CHECKS
64 cl::desc(
"Print before passes that change them"),
71 cl::desc(
"system dot used by change reporters"));
99 cl::desc(
"Generate dot files into specified directory for changed IRs"),
104 "print-on-crash-path",
105 cl::desc(
"Print the last form of the IR before crash to a file"),
110 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
114 "opt-bisect-print-ir-path",
119 cl::desc(
"Print pass names and their ordinals"));
123 cl::desc(
"Print IR before the passes with specified numbers as "
124 "reported by print-pass-numbers"));
128 cl::desc(
"Print IR after the passes with specified numbers as "
129 "reported by print-pass-numbers"));
133 cl::desc(
"If specified, IR printed using the "
134 "-print-[before|after]{-all} options will be dumped into "
135 "files in this directory rather than written to stderr"),
140 cl::desc(
"Dump dropped debug variables stats"),
145 return IRPtr ? *IRPtr :
nullptr;
159 cl::desc(
"exe called with module IR after each pass that "
164const Module *unwrapModule(
Any IR,
bool Force =
false) {
172 return F->getParent();
179 return F.getParent();
182 assert(!Force &&
"Expected a module");
187 const Function *
F =
L->getHeader()->getParent();
190 return F->getParent();
196 return MF->getFunction().getParent();
210 M->print(OS,
nullptr);
212 for (
const auto &
F : M->functions()) {
228 const Function *
F = L->getHeader()->getParent();
240std::string getIRName(
Any IR) {
245 return F->getName().str();
251 return "loop %" + L->getName().str() +
" in function " +
252 L->getHeader()->getParent()->getName().str();
260bool moduleContainsFilterPrintFunc(
const Module &M) {
261 return any_of(M.functions(),
263 return isFunctionInPrintList(F.getName());
276bool shouldPrintIR(
Any IR) {
278 return moduleContainsFilterPrintFunc(*M);
284 return sccContainsFilterPrintFunc(*
C);
297 if (!shouldPrintIR(
IR))
301 auto *M = unwrapModule(
IR);
302 assert(M &&
"should have unwrapped module");
337 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
338 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
339 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
340 "PrintMIRPreparePass",
"RequireAnalysisPass",
341 "InvalidateAnalysisPass"});
349 S.append(Clean.
str());
353 S.append(SR[0] ==
'<' ?
"<" :
">");
364 return C->begin()->getFunction().getParent();
368bool isInterestingFunction(
const Function &
F) {
378 return isInterestingFunction(*
F);
416 std::string Name = getIRName(
IR);
418 if (isIgnored(PassID)) {
432 if (Before == After) {
461 PIC.registerAfterPassCallback(
465 PIC.registerAfterPassInvalidatedCallback(
478 auto *M = unwrapModule(
IR,
true);
479 assert(M &&
"Expected module to be unwrapped when forced.");
480 Out <<
"*** IR Dump At Start ***\n";
481 M->print(
Out,
nullptr);
486 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
492 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
499 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
505 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
517 std::string &Output) {
519 unwrapAndPrint(OS,
IR);
524 const std::string &Before,
525 const std::string &After,
Any) {
528 Out <<
"*** IR Dump Before " << PassID <<
" on " << Name <<
" ***\n"
534 Out <<
"*** IR Deleted After " << PassID <<
" on " << Name <<
" ***\n";
538 Out <<
"*** IR Dump After " << PassID <<
" on " << Name <<
" ***\n" << After;
544 if (TestChanged !=
"")
554 dbgs() <<
"Unable to create temporary file.";
559 dbgs() <<
"Unable to find test-changed executable.";
563 StringRef Args[] = {TestChanged, FileName[0], PassID};
566 dbgs() <<
"Error executing test-changed executable.";
571 dbgs() <<
"Unable to remove temporary file.";
587 const std::string &Before,
588 const std::string &After,
Any) {
596 const auto &BFD = Before.
getData();
597 const auto &AFD = After.
getData();
598 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
599 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
600 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
601 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
603 auto HandlePotentiallyRemovedData = [&](std::string S) {
607 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
610 auto HandleNewData = [&](std::vector<const T *> &Q) {
612 for (
const T *NBI : Q)
613 HandlePair(
nullptr, NBI);
626 std::vector<const T *> NewDataQueue;
628 if (!BFD.count(*AI)) {
631 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
640 while (BI != BE && *BI != *AI) {
641 HandlePotentiallyRemovedData(*BI);
645 HandleNewData(NewDataQueue);
647 const T &AData = AFD.find(*AI)->getValue();
648 const T &BData = BFD.find(*AI)->getValue();
649 HandlePair(&BData, &AData);
657 HandlePotentiallyRemovedData(*BI);
661 HandleNewData(NewDataQueue);
667 std::function<
void(
bool InModule,
unsigned Minor,
670 if (!CompareModule) {
673 "Expected only one function.");
674 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
675 After.getData().begin()->getValue());
683 assert((
B ||
A) &&
"Both functions cannot be missing.");
688 CompareFunc(
true, Minor++, *
B, *
A);
693 if (
const Module *M = getModuleForComparison(
IR)) {
706 auto *
F = L->getHeader()->getParent();
728template <
typename FunctionT>
733 for (
const auto &
B :
F) {
734 std::string BBName =
B.getName().str();
735 if (BBName.empty()) {
742 Data.getOrder().emplace_back(
F.getName());
743 Data.getData().insert({
F.getName(), FD});
750 assert(PassRunDescriptorStack.empty() &&
751 "PassRunDescriptorStack is not empty at exit");
755 const Module *M = unwrapModule(
IR,
true);
756 assert(M &&
"should have unwrapped module");
758 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
761 ResultStream <<
"-module";
763 ResultStream <<
"-function-";
768 ResultStream <<
"-scc-";
772 ResultStream <<
"-loop-";
776 ResultStream <<
"-machine-function-";
792StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
793 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
795 return FileSuffixes[
static_cast<size_t>(
Type)];
798std::string PrintIRInstrumentation::fetchDumpFilename(
800 IRDumpFileSuffixType SuffixType) {
802 "The flag -ir-dump-directory must be passed to dump IR to files");
805 raw_svector_ostream FilenameStream(
Filename);
806 FilenameStream << PassNumber;
807 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
809 FilenameStream << getFileSuffix(SuffixType);
811 SmallString<128> ResultPath;
813 return std::string(ResultPath);
816void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
Any IR,
817 unsigned PassNumber) {
820 getIRName(
IR), PassID);
823PrintIRInstrumentation::PassRunDescriptor
824PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
825 assert(!PassRunDescriptorStack.empty() &&
"empty PassRunDescriptorStack");
826 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
827 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
835 if (!ParentPath.empty()) {
839 " to support -ir-dump-directory: " + EC.message());
846 " to support -ir-dump-directory: " + EC.message());
850void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
851 if (isIgnored(PassID))
858 if (shouldPrintAfterPass(PassID))
859 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
861 if (!shouldPrintIR(
IR))
866 if (shouldPrintPassNumbers())
867 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
868 <<
" on " << getIRName(
IR) <<
"\n";
870 if (shouldPrintAfterCurrentPassNumber())
871 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
873 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
876 auto WriteIRToStream = [&](raw_ostream &Stream) {
877 Stream <<
"; *** IR Dump Before ";
878 if (shouldPrintBeforeSomePassNumber())
879 Stream << CurrentPassNumber <<
"-";
880 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
881 unwrapAndPrint(Stream,
IR);
885 std::string DumpIRFilename =
887 IRDumpFileSuffixType::Before);
888 llvm::raw_fd_ostream DumpIRFileStream{
890 WriteIRToStream(DumpIRFileStream);
892 WriteIRToStream(
dbgs());
896void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
897 if (isIgnored(PassID))
900 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
903 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
904 popPassRunDescriptor(PassID);
905 assert(StoredPassID == PassID &&
"mismatched PassID");
907 if (!shouldPrintIR(
IR) ||
908 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
911 auto WriteIRToStream = [&](raw_ostream &Stream,
const StringRef IRName) {
912 Stream <<
"; *** IR Dump After ";
913 if (shouldPrintAfterSomePassNumber())
914 Stream << CurrentPassNumber <<
"-";
915 Stream << StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
916 unwrapAndPrint(Stream,
IR);
920 std::string DumpIRFilename =
922 IRDumpFileSuffixType::After);
923 llvm::raw_fd_ostream DumpIRFileStream{
926 WriteIRToStream(DumpIRFileStream, IRName);
928 WriteIRToStream(
dbgs(), IRName);
932void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
933 if (isIgnored(PassID))
936 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
939 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
940 popPassRunDescriptor(PassID);
941 assert(StoredPassID == PassID &&
"mismatched PassID");
945 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
948 auto WriteIRToStream = [&](raw_ostream &Stream,
const Module *
M,
949 const StringRef IRName) {
950 SmallString<20> Banner;
951 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
953 Stream << Banner <<
"\n";
958 std::string DumpIRFilename =
959 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
960 IRDumpFileSuffixType::Invalidated);
961 llvm::raw_fd_ostream DumpIRFileStream{
964 WriteIRToStream(DumpIRFileStream, M, IRName);
966 WriteIRToStream(
dbgs(), M, IRName);
970bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
974 StringRef
PassName = PIC->getPassNameForClassName(PassID);
978bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
982 StringRef
PassName = PIC->getPassNameForClassName(PassID);
986bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
987 return shouldPrintBeforeSomePassNumber() &&
991bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
992 return shouldPrintAfterSomePassNumber() &&
996bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1000bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1004bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1015 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1022 PIC.registerAfterPassCallback(
1024 this->printAfterPass(
P,
IR);
1026 PIC.registerAfterPassInvalidatedCallback(
1028 this->printAfterPassInvalidated(
P);
1035 PIC.registerShouldRunOptionalPassCallback(
1039bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
1040 bool ShouldRun =
true;
1042 ShouldRun = !
F->hasOptNone();
1044 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1048 if (!ShouldRun && DebugLogging) {
1049 errs() <<
"Skipping pass " << PassID <<
" on " << getIRName(
IR)
1050 <<
" due to optnone attribute\n";
1060 Context.getOptPassGate().shouldRunPass(
PassName, getIRName(
IR));
1064 this->HasWrittenIR =
true;
1065 const Module *M = unwrapModule(
IR,
true);
1066 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1071 M->print(OS,
nullptr);
1078 const OptPassGate &PassGate = Context.getOptPassGate();
1082 PIC.registerShouldRunOptionalPassCallback(
1104 std::vector<StringRef> SpecialPasses;
1105 if (!Opts.Verbose) {
1106 SpecialPasses.emplace_back(
"PassManager");
1107 SpecialPasses.emplace_back(
"PassAdaptor");
1110 PIC.registerBeforeSkippedPassCallback([
this, SpecialPasses](
StringRef PassID,
1113 "Unexpectedly skipping special pass");
1115 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1117 PIC.registerBeforeNonSkippedPassCallback([
this, SpecialPasses](
1123 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1125 unsigned Count =
F->getInstructionCount();
1126 OS <<
" (" <<
Count <<
" instruction";
1132 OS <<
" (" <<
Count <<
" node";
1140 PIC.registerAfterPassCallback(
1148 PIC.registerAfterPassInvalidatedCallback(
1156 if (!Opts.SkipAnalyses) {
1158 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1162 PIC.registerAfterAnalysisCallback(
1165 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1168 PIC.registerAnalysesClearedCallback([
this](
StringRef IRName) {
1169 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1175 bool TrackBBLifetime) {
1176 if (TrackBBLifetime)
1178 for (
const auto &BB : *
F) {
1180 BBGuards->try_emplace(intptr_t(&BB), &BB);
1184 BBGuards->try_emplace(intptr_t(Succ), Succ);
1191 out << BB->
getName() <<
"<" << BB <<
">";
1196 out <<
"unnamed_removed<" << BB <<
">";
1202 <<
"<" << BB <<
">";
1206 unsigned FuncOrderBlockNum = 0;
1210 FuncOrderBlockNum++;
1212 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1220 out <<
"Some blocks were deleted\n";
1225 if (Before.
Graph.size() != After.
Graph.size())
1226 out <<
"Different number of non-leaf basic blocks: before="
1227 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1229 for (
auto &BB : Before.
Graph) {
1230 auto BA = After.
Graph.find(BB.first);
1231 if (BA == After.
Graph.end()) {
1232 out <<
"Non-leaf block ";
1234 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1238 for (
auto &BA : After.
Graph) {
1239 auto BB = Before.
Graph.find(BA.first);
1240 if (BB == Before.
Graph.end()) {
1241 out <<
"Non-leaf block ";
1243 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1247 if (BB->second == BA.second)
1250 out <<
"Different successors of block ";
1252 out <<
" (unordered):\n";
1253 out <<
"- before (" << BB->second.size() <<
"): ";
1254 for (
auto &SuccB : BB->second) {
1256 if (SuccB.second != 1)
1257 out <<
"(" << SuccB.second <<
"), ";
1262 out <<
"- after (" << BA.second.size() <<
"): ";
1263 for (
auto &SuccA : BA.second) {
1265 if (SuccA.second != 1)
1266 out <<
"(" << SuccA.second <<
"), ";
1337 FunctionAnalysisManager::Invalidator &) {
1347 Functions.push_back(
const_cast<Function *
>(MaybeF));
1350 Functions.push_back(&
F);
1360 bool Registered =
false;
1361 PIC.registerBeforeNonSkippedPassCallback([
this, &
MAM, Registered](
1363#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1364 assert(&PassStack.emplace_back(
P));
1369 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1385 auto &M = *
const_cast<Module *
>(MPtr);
1390 PIC.registerAfterPassInvalidatedCallback(
1392#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1393 assert(PassStack.pop_back_val() ==
P &&
1394 "Before and After callbacks must correspond");
1401#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1402 assert(PassStack.pop_back_val() ==
P &&
1403 "Before and After callbacks must correspond");
1411 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1415 if (
auto *HashBefore =
1419 "Function @{0} changed by {1} without invalidating analyses",
1425 const CFG &GraphBefore,
const CFG &GraphAfter) {
1426 if (GraphAfter == GraphBefore)
1430 <<
"Error: " <<
Pass
1431 <<
" does not invalidate CFG analyses but CFG changes detected in "
1433 << FuncName <<
":\n";
1438 if (
auto *GraphBefore =
1440 CheckCFG(
P,
F->getName(), *GraphBefore,
1444 auto &M = *
const_cast<Module *
>(MPtr);
1445 if (
auto *HashBefore =
1449 "Module changed by {0} without invalidating analyses",
P));
1458 PIC.registerAfterPassCallback(
1460 if (isIgnored(
P) ||
P ==
"VerifierPass")
1465 F = L->getHeader()->getParent();
1470 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1474 "\"{0}\", compilation aborted!",
1480 M =
C->begin()->getFunction().getParent();
1485 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1489 "\"{0}\", compilation aborted!",
1495 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1496 std::string Banner =
1497 formatv(
"Broken machine function found after pass "
1498 "\"{0}\", compilation aborted!",
1528 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID, Name);
1532 [&](
bool InModule,
unsigned Minor,
1536 Minor, Before, After);
1547 Out <<
"\n*** IR for function " << Name <<
" ***\n";
1554 const std::string Removed =
1555 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1556 const std::string Added =
UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1557 const std::string NoChange =
" %l\n";
1576 PIC.registerBeforeNonSkippedPassCallback(
1578 PIC.registerAfterPassCallback(
1580 this->runAfterPass();
1583 PIC.registerAfterPassInvalidatedCallback(
1586 PIC.registerBeforeAnalysisCallback(
1588 PIC.registerAfterAnalysisCallback(
1592void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1601class DotCfgDiffDisplayGraph;
1604class DisplayElement {
1607 StringRef getColour()
const {
return Colour; }
1610 DisplayElement(StringRef Colour) : Colour(Colour) {}
1611 const StringRef Colour;
1616class DisplayEdge :
public DisplayElement {
1618 DisplayEdge(std::string
Value, DisplayNode &Node, StringRef Colour)
1623 const DisplayNode &getDestinationNode()
const {
return Node; }
1627 const DisplayNode &
Node;
1631class DisplayNode :
public DisplayElement {
1635 DisplayNode(std::string Content, StringRef Colour)
1636 : DisplayElement(Colour), Content(Content) {}
1639 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1640 ChildIterator children_begin()
const {
return Children.cbegin(); }
1641 ChildIterator children_end()
const {
return Children.cend(); }
1644 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1645 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1646 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1649 void createEdge(StringRef
Value, DisplayNode &Node, StringRef Colour);
1652 std::string getContent()
const {
return Content; }
1655 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1656 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1657 return *EdgeMap.find(&To)->second;
1662 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1663 return getEdge(Sink).getValue();
1666 void createEdgeMap();
1669 const std::string Content;
1674 std::vector<DisplayEdge> Edges;
1676 std::vector<DisplayEdge *> EdgePtrs;
1677 std::unordered_set<DisplayNode *>
Children;
1678 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1681 bool AllEdgesCreated =
false;
1685class DotCfgDiffDisplayGraph {
1687 DotCfgDiffDisplayGraph(std::string Name) : GraphName(
Name) {}
1690 void generateDotFile(StringRef DotFile);
1693 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1694 NodeIterator nodes_begin()
const {
1695 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1696 return NodePtrs.cbegin();
1698 NodeIterator nodes_end()
const {
1699 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1700 return NodePtrs.cend();
1705 void setEntryNode(
unsigned N) {
1707 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1708 NodeGenerationComplete =
true;
1709 for (
auto &
N : Nodes)
1710 NodePtrs.emplace_back(&
N);
1712 EntryNode = NodePtrs[
N];
1716 void createNode(std::string
C, StringRef Colour) {
1717 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1718 Nodes.emplace_back(
C, Colour);
1722 assert(
N < Nodes.size() &&
"Node is out of bounds");
1725 unsigned size()
const {
1726 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1727 return Nodes.size();
1731 std::string getGraphName()
const {
return GraphName; }
1735 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1736 return Node.getContent();
1740 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1741 return attribute(
Node.getColour());
1745 std::string getEdgeColorAttr(
const DisplayNode &From,
1746 const DisplayNode &To)
const {
1747 return attribute(From.getEdge(To).getColour());
1751 DisplayNode *getEntryNode()
const {
1752 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1758 std::string attribute(StringRef Colour)
const {
1759 return "color=" + Colour.
str();
1762 bool NodeGenerationComplete =
false;
1763 const std::string GraphName;
1764 std::vector<DisplayNode> Nodes;
1765 std::vector<DisplayNode *> NodePtrs;
1766 DisplayNode *EntryNode =
nullptr;
1769void DisplayNode::createEdge(StringRef
Value, DisplayNode &Node,
1771 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1772 Edges.emplace_back(
Value.str(), Node, Colour);
1776void DisplayNode::createEdgeMap() {
1779 AllEdgesCreated =
true;
1780 for (
auto &
E : Edges)
1781 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1784class DotCfgDiffNode;
1788class DotCfgDiffNode {
1790 DotCfgDiffNode() =
delete;
1794 DotCfgDiffNode(DotCfgDiff &
G,
unsigned N,
const BlockDataT<DCData> &BD,
1796 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1797 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1802 unsigned getIndex()
const {
return N; }
1805 StringRef getLabel()
const {
1806 assert(
Data[0] &&
"Expected Data[0] to be set.");
1807 return Data[0]->getLabel();
1810 StringRef getColour()
const {
return Colour; }
1813 void setCommon(
const BlockDataT<DCData> &
Other) {
1814 assert(!
Data[1] &&
"Expected only one block datum");
1819 void addEdge(
unsigned E, StringRef
Value, StringRef Colour) {
1822 "Unexpected edge count and color.");
1823 EdgesMap[
E] = {
Value.str(), Colour};
1829 StringRef getEdgeColour(
const unsigned S)
const {
1830 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1831 return EdgesMap.at(S).second;
1835 std::string getBodyContent()
const;
1837 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1838 std::map<const unsigned, unsigned> &NodeMap)
const;
1843 const BlockDataT<DCData> *
Data[2];
1845 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1847 std::vector<unsigned> Edges;
1857 DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1858 const FuncDataT<DCData> &After);
1860 DotCfgDiff(
const DotCfgDiff &) =
delete;
1861 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1863 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1864 StringRef EntryNodeName);
1870 StringRef getEdgeSourceLabel(
const unsigned &Source,
1871 const unsigned &Sink)
const {
1873 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1874 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1875 return EdgeLabels.find(S)->getValue();
1879 unsigned size()
const {
return Nodes.size(); }
1881 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1882 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1888 std::string colourize(std::string S, StringRef Colour)
const;
1890 void createNode(StringRef Label,
const BlockDataT<DCData> &BD, StringRef
C) {
1891 unsigned Pos = Nodes.size();
1892 Nodes.emplace_back(*
this, Pos, BD,
C);
1893 NodePosition.insert({
Label, Pos});
1899 std::vector<DotCfgDiffNode> Nodes;
1900 StringMap<unsigned> NodePosition;
1901 const std::string GraphName;
1903 StringMap<std::string> EdgeLabels;
1906std::string DotCfgDiffNode::getBodyContent()
const {
1908 assert(
Data[1] &&
"Expected Data[1] to be set.");
1911 for (
unsigned I = 0;
I < 2; ++
I) {
1912 SR[
I] =
Data[
I]->getBody();
1916 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1919 SmallString<80> OldLineFormat =
formatv(
1920 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1921 SmallString<80> NewLineFormat =
formatv(
1922 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1923 SmallString<80> UnchangedLineFormat =
formatv(
1924 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1925 std::string Diff =
Data[0]->getLabel().str();
1926 Diff +=
":\n<BR align=\"left\"/>" +
1927 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1928 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1933 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1936 std::string S =
R.sub(
"", Diff, &
Error);
1947 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1948 std::string Body = makeHTMLReady(
Data[0]->getBody());
1949 const StringRef BS = Body;
1952 if (BS.
front() ==
'\n')
1957 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1959 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1962 while (BS1.
size()) {
1963 S.append(
"<BR align=\"left\"/>");
1965 S.append(
Line.str());
1968 S.append(
"<BR align=\"left\"/></FONT>");
1972std::string DotCfgDiff::colourize(std::string S, StringRef Colour)
const {
1973 if (S.length() == 0)
1975 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1978DotCfgDiff::DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1979 const FuncDataT<DCData> &After)
1980 : GraphName(Title.str()) {
1981 StringMap<StringRef> EdgesMap;
1985 StringRef Label = B.getKey();
1986 const BlockDataT<DCData> &BD = B.getValue();
1987 createNode(Label, BD, BeforeColour);
1991 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1992 E = BD.getData().end();
1993 Sink != E; ++Sink) {
1994 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1995 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1996 EdgesMap.insert({Key, BeforeColour});
2002 StringRef Label = A.getKey();
2003 const BlockDataT<DCData> &BD = A.getValue();
2004 auto It = NodePosition.find(Label);
2005 if (It == NodePosition.end())
2007 createNode(Label, BD, AfterColour);
2009 Nodes[It->second].setCommon(BD);
2011 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
2012 E = BD.getData().end();
2013 Sink != E; ++Sink) {
2014 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
2015 BD.getData().getSuccessorLabel(Sink->getKey()).str();
2016 auto [It, Inserted] = EdgesMap.try_emplace(Key, AfterColour);
2018 It->second = CommonColour;
2023 for (
auto &
E : EdgesMap) {
2026 auto SP1 = S.
rsplit(
' ');
2027 auto &SourceSink = SP1.first;
2028 auto SP2 = SourceSink.split(
' ');
2033 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2034 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2035 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2036 unsigned SinkNode = NodePosition[
Sink];
2040 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2042 It->getValue() = colourize(
Value.str(), Colour);
2045 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2047 It->getValue() =
NV;
2049 SourceNode.addEdge(SinkNode,
Value, Colour);
2051 for (
auto &
I : Nodes)
2055DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2057 assert(NodePosition.count(EntryNodeName) == 1 &&
2058 "Expected to find entry block in map.");
2059 unsigned Entry = NodePosition[EntryNodeName];
2060 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2061 DotCfgDiffDisplayGraph
G(Title.
str());
2063 std::map<const unsigned, unsigned> NodeMap;
2065 int EntryIndex = -1;
2067 for (
auto &
I : Nodes) {
2068 if (
I.getIndex() == Entry)
2070 G.createNode(
I.getBodyContent(),
I.getColour());
2071 NodeMap.insert({
I.getIndex(),
Index++});
2073 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2074 G.setEntryNode(EntryIndex);
2076 for (
auto &
I : NodeMap) {
2077 unsigned SourceNode =
I.first;
2078 unsigned DisplayNode =
I.second;
2079 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2084void DotCfgDiffNode::createDisplayEdges(
2085 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2086 std::map<const unsigned, unsigned> &NodeMap)
const {
2088 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2090 for (
auto I : Edges) {
2091 unsigned SinkNodeIndex =
I;
2092 StringRef Colour = getEdgeColour(SinkNodeIndex);
2093 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2095 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2096 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2097 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2099 SourceDisplayNode.createEdgeMap();
2102void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2103 for (
auto E : EdgesMap) {
2105 Edges.emplace_back(
E.first);
2121 return G->getEntryNode();
2124 return N->children_begin();
2128 return G->nodes_begin();
2131 return G->nodes_end();
2134 return N->edges_begin();
2138 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2148 return DiffData->getGraphName();
2152 return "\tsize=\"190, 190\";\n";
2155 const DotCfgDiffDisplayGraph *DiffData) {
2156 return DiffData->getNodeLabel(*
Node);
2159 const DotCfgDiffDisplayGraph *DiffData) {
2160 return DiffData->getNodeAttributes(*
Node);
2163 DisplayNode::ChildIterator &To) {
2164 return From->getEdgeSourceLabel(**To);
2167 DisplayNode::ChildIterator &To,
2168 const DotCfgDiffDisplayGraph *DiffData) {
2169 return DiffData->getEdgeColorAttr(*From, **To);
2177void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
2179 raw_fd_ostream OutStream(DotFile, EC);
2181 errs() <<
"Error: " <<
EC.message() <<
"\n";
2202 for (
auto &
C : Sw->cases()) {
2203 assert(
C.getCaseValue() &&
"Expected to find case value.");
2224 assert(
HTML &&
"Expected outstream to be set");
2229 Extender =
formatv(
"{0}_{1}",
N, Minor);
2238 std::string DotFile =
Twine(SV).
str();
2246 DotCfgDiff Diff(
Text, Before, After);
2249 if (EntryBlockName ==
"")
2251 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2253 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2254 DG.generateDotFile(DotFile);
2259 errs() <<
"Error: " << EC.message() <<
"\n";
2268 return "Unable to find dot executable.";
2273 return "Error executing system dot.";
2277 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2282 assert(
HTML &&
"Expected outstream to be set");
2283 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2284 <<
"Initial IR (by function)</button>\n"
2285 <<
"<div class=\"content\">\n"
2294 [&](
bool InModule,
unsigned Minor,
2298 Minor, Before, After);
2311 assert(
HTML &&
"Expected outstream to be set");
2313 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2314 N, makeHTMLReady(PassID), Name);
2322 assert(
HTML &&
"Expected outstream to be set");
2325 [&](
bool InModule,
unsigned Minor,
2329 Minor, Before, After);
2331 *
HTML <<
" </p></div>\n";
2336 assert(
HTML &&
"Expected outstream to be set");
2338 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2344 assert(
HTML &&
"Expected outstream to be set");
2346 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2347 makeHTMLReady(PassID), Name);
2353 assert(
HTML &&
"Expected outstream to be set");
2355 makeHTMLReady(PassID), Name);
2362 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2368 *
HTML <<
"<!doctype html>"
2371 <<
"<style>.collapsible { "
2372 <<
"background-color: #777;"
2374 <<
" cursor: pointer;"
2375 <<
" padding: 18px;"
2378 <<
" text-align: left;"
2379 <<
" outline: none;"
2380 <<
" font-size: 15px;"
2381 <<
"} .active, .collapsible:hover {"
2382 <<
" background-color: #555;"
2384 <<
" padding: 0 18px;"
2385 <<
" display: none;"
2386 <<
" overflow: hidden;"
2387 <<
" background-color: #f1f1f1;"
2390 <<
"<title>passes.html</title>"
2400 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2402 <<
"for (i = 0; i < coll.length; i++) {"
2403 <<
"coll[i].addEventListener(\"click\", function() {"
2404 <<
" this.classList.toggle(\"active\");"
2405 <<
" var content = this.nextElementSibling;"
2406 <<
" if (content.style.display === \"block\"){"
2407 <<
" content.style.display = \"none\";"
2410 <<
" content.style.display= \"block\";"
2428 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2434 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2439 LLVMContext &Context,
bool DebugLogging,
bool VerifyEach,
2441 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2442 OptPassGate(Context),
2450 VerifyEach(VerifyEach) {}
2467void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2474 "Did not expect to get here without option set.");
2483 "Did not expect to get here without option set.");
2484 CrashReporter =
nullptr;
2493 CrashReporter =
this;
2495 PIC.registerBeforeNonSkippedPassCallback(
2499 OS <<
formatv(
"; *** Dump of {0}IR Before Last Pass {1}",
2502 OS <<
" Filtered Out ***\n";
2505 OS <<
" Started ***\n";
2506 unwrapAndPrint(OS,
IR);
2512 PrintIR.registerCallbacks(
PIC);
2513 PrintPass.registerCallbacks(
PIC);
2514 TimePasses.registerCallbacks(
PIC);
2515 OptNone.registerCallbacks(
PIC);
2516 OptPassGate.registerCallbacks(
PIC);
2517 PrintChangedIR.registerCallbacks(
PIC);
2518 PseudoProbeVerification.registerCallbacks(
PIC);
2520 Verify.registerCallbacks(
PIC,
MAM);
2521 PrintChangedDiff.registerCallbacks(
PIC);
2522 WebsiteChangeReporter.registerCallbacks(
PIC);
2523 ChangeTester.registerCallbacks(
PIC);
2524 PrintCrashIR.registerCallbacks(
PIC);
2525 DroppedStatsIR.registerCallbacks(
PIC);
2527 PreservedCFGChecker.registerCallbacks(
PIC, *
MAM);
2535 TimeProfilingPasses.registerCallbacks(
PIC);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file provides Any, a non-template class modeled in the spirit of std::any.
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
static constexpr Value * getValue(Ty &ValueOrUse)
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
Implements a lazy call graph analysis and related passes for the new pass manager.
Legalize the Machine IR a function s Machine IR
Machine Check Debug Module
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
static constexpr StringLiteral Filename
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
verify safepoint Safepoint IR Verifier
static cl::opt< std::string > BeforeColour("dot-cfg-before-color", cl::desc("Color for dot-cfg before elements"), cl::Hidden, cl::init("red"))
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"))
static cl::opt< bool > DroppedVarStats("dropped-variable-stats", cl::Hidden, cl::desc("Dump dropped debug variables stats"), cl::init(false))
static cl::opt< std::string > OptBisectPrintIRPath("opt-bisect-print-ir-path", cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden)
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
static cl::opt< std::string > DotCfgDir("dot-cfg-dir", cl::desc("Generate dot files into specified directory for changed IRs"), cl::Hidden, cl::init("./"))
static cl::list< unsigned > PrintBeforePassNumber("print-before-pass-number", cl::CommaSeparated, cl::Hidden, cl::desc("Print IR before the passes with specified numbers as " "reported by print-pass-numbers"))
static cl::opt< bool > VerifyAnalysisInvalidation("verify-analysis-invalidation", cl::Hidden, cl::init(false))
static std::string getIRFileDisplayName(Any IR)
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
static SmallVector< Function *, 1 > GetFunctions(Any IR)
static void printBBName(raw_ostream &out, const BasicBlock *BB)
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
static bool shouldGenerateData(const Function &F)
static cl::list< unsigned > PrintAfterPassNumber("print-after-pass-number", cl::CommaSeparated, cl::Hidden, cl::desc("Print IR after the passes with specified numbers as " "reported by print-pass-numbers"))
static int prepareDumpIRFileDescriptor(const StringRef DumpIRFilename)
static const IRUnitT * unwrapIR(Any IR)
static cl::opt< std::string > AfterColour("dot-cfg-after-color", cl::desc("Color for dot-cfg after elements"), cl::Hidden, cl::init("forestgreen"))
static cl::opt< bool > PrintOnCrash("print-on-crash", cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"), cl::Hidden)
static cl::opt< bool > PrintPassNumbers("print-pass-numbers", cl::init(false), cl::Hidden, cl::desc("Print pass names and their ordinals"))
static cl::opt< std::string > PrintOnCrashPath("print-on-crash-path", cl::desc("Print the last form of the IR before crash to a file"), cl::Hidden)
static void writeIRFileDisplayName(raw_ostream &ResultStream, Any IR)
This header defines a class that provides bookkeeping for all standard (i.e in-tree) pass instrumenta...
static const char PassName[]
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI bool isEntryBlock() const
Return true if this is the entry block of the containing function.
Represents analyses that only rely on functions' control flow.
void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName)
virtual void handleFiltered(StringRef PassID, std::string &Name)=0
virtual void handleAfter(StringRef PassID, std::string &Name, const IRUnitT &Before, const IRUnitT &After, Any)=0
virtual void handleIgnored(StringRef PassID, std::string &Name)=0
virtual void generateIRRepresentation(Any IR, StringRef PassID, IRUnitT &Output)=0
virtual void handleInitialIR(Any IR)=0
void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName)
virtual void handleInvalidated(StringRef PassID)=0
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
std::vector< IRUnitT > BeforeStack
virtual void omitAfter(StringRef PassID, std::string &Name)=0
void handleInvalidatedPass(StringRef PassID)
ChangeReporter(bool RunInVerboseMode)
virtual ~ChangeReporter()
Conditional Branch instruction.
void addSuccessorLabel(StringRef Succ, StringRef Label)
LLVM_ABI DCData(const BasicBlock &B)
std::unique_ptr< raw_fd_ostream > HTML
void handleInvalidated(StringRef PassID) override
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< DCData > &Output) override
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
void handleInitialIR(Any IR) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< DCData > &Before, const FuncDataT< DCData > &After)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
DotCfgChangeReporter(bool Verbose)
void handleIgnored(StringRef PassID, std::string &Name) override
~DotCfgChangeReporter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, Any) override
void handleFiltered(StringRef PassID, std::string &Name) override
void omitAfter(StringRef PassID, std::string &Name) override
Represents either an error or a value T.
std::string getEntryBlockName() const
bool hasOptNone() const
Do not optimize this function (-O0).
~IRChangedPrinter() override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
void omitAfter(StringRef PassID, std::string &Name) override
void handleInvalidated(StringRef PassID) override
void handleIR(const std::string &IR, StringRef PassID)
void handleInitialIR(Any IR) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleFiltered(StringRef PassID, std::string &Name) override
~IRChangedTester() override
const IRDataT< T > & Before
static bool generateFunctionData(IRDataT< T > &Data, const FunctionT &F)
const IRDataT< T > & After
static void analyzeIR(Any IR, IRDataT< T > &Data)
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~InLineChangePrinter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, Any) override
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< EmptyData > &Output) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
Represents a single loop in the control flow graph.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI bool shouldRun(StringRef PassName, Any IR)
Extensions to this class implement mechanisms to disable passes and individual optimizations at compi...
virtual bool isEnabled() const
isEnabled() should return true before calling shouldRunPass().
static void report(const OrderedChangedData &Before, const OrderedChangedData &After, function_ref< void(const T *, const T *)> HandlePair)
StringMap< T > & getData()
std::vector< std::string > & getOrder()
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerBeforeNonSkippedPassCallback(CallableT C)
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
LLVM_ABI void reportCrashIR()
LLVM_ABI ~PrintCrashIRInstrumentation()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI ~PrintIRInstrumentation()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)
LLVM_ABI StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef drop_until(function_ref< bool(char)> F) const
Return a StringRef equal to 'this', but with all characters not satisfying the given predicate droppe...
constexpr size_t size() const
Get the string size.
char front() const
Get the first character in the string.
StringRef take_until(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
void handleInitialIR(Any IR) override
void handleInvalidated(StringRef PassID) override
TextChangeReporter(bool Verbose)
void omitAfter(StringRef PassID, std::string &Name) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleFiltered(StringRef PassID, std::string &Name) override
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI TimeProfilingPassesHandler()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM)
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
LLVM_ABI std::error_code openFile(const Twine &Name, int &ResultFD, CreationDisposition Disp, FileAccess Access, OpenFlags Flags, unsigned Mode=0666)
Opens a file with the specified creation disposition, access mode, and flags and returns a file descr...
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
LLVM_ABI void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
LLVM_ABI void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
LLVM_ABI std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie, bool NeedsPOSIXUtilitySignalHandling=false)
Add a function to be called when an abort/kill signal is delivered to the process.
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.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI std::error_code prepareTempFiles(SmallVector< int > &FD, ArrayRef< StringRef > SR, SmallVector< std::string > &FileName)
T any_cast(const Any &Value)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI bool forcePrintModuleIR()
LLVM_ABI std::vector< std::string > printAfterPasses()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
Inline ArrayRef overloads of the xxhash entry points declared out-of-line in llvm/Support/xxhash....
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
LLVM_ABI bool shouldPrintBeforeAll()
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI bool shouldPrintAfterAll()
LLVM_ABI cl::opt< ChangePrinter > PrintChanged
LLVM_ABI TimeTraceProfiler * getTimeTraceProfilerInstance()
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI bool shouldPrintAfterSomePass()
LLVM_ABI void verifyMachineFunction(const std::string &Banner, const MachineFunction &MF)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool isFunctionInPrintList(StringRef FunctionName)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool isPassInPrintList(StringRef PassName)
FunctionAddr VTableAddr Count
LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
LLVM_ABI void timeTraceProfilerEnd()
Manually end the last time section.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
InnerAnalysisManagerProxy< MachineFunctionAnalysisManager, Module > MachineFunctionAnalysisManagerModuleProxy
LLVM_ABI void printLoop(const Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
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.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI stable_hash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI TimeTraceProfilerEntry * timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
Result run(Function &F, FunctionAnalysisManager &FAM)
Run the analysis pass over a function and produce CFG.
PreservedCFGCheckerInstrumentation::CFG Result
Provide the result type for this analysis pass.
Result run(Function &F, FunctionAnalysisManager &FAM)
Result run(Module &F, ModuleAnalysisManager &FAM)
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
static std::string getEdgeAttributes(const DisplayNode *From, DisplayNode::ChildIterator &To, const DotCfgDiffDisplayGraph *DiffData)
static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData)
static std::string getEdgeSourceLabel(const DisplayNode *From, DisplayNode::ChildIterator &To)
static std::string getNodeAttributes(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
static std::string getNodeLabel(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
static bool renderNodesUsingHTML()
static std::string getGraphProperties(const DotCfgDiffDisplayGraph *DiffData)
DOTGraphTraits(bool Simple=false)
DefaultDOTGraphTraits(bool simple=false)
static ChildEdgeIterator child_edge_end(NodeRef N)
static unsigned size(const DotCfgDiffDisplayGraph *G)
static NodeRef getEntryNode(const DotCfgDiffDisplayGraph *G)
DisplayNode::EdgeIterator ChildEdgeIterator
static ChildIteratorType child_begin(NodeRef N)
const DisplayEdge * EdgeRef
static ChildIteratorType child_end(NodeRef N)
const DisplayNode * NodeRef
static NodeRef edge_dest(EdgeRef E)
DotCfgDiffDisplayGraph::NodeIterator nodes_iterator
DisplayNode::ChildIterator ChildIteratorType
static nodes_iterator nodes_begin(const DotCfgDiffDisplayGraph *G)
static ChildEdgeIterator child_edge_begin(NodeRef N)
static nodes_iterator nodes_end(const DotCfgDiffDisplayGraph *G)
std::optional< DenseMap< intptr_t, BBGuard > > BBGuards
static LLVM_ABI void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
LLVM_ABI CFG(const Function *F, bool TrackBBLifetime)
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
bool Indent
Indent based on hierarchy.