40#include <unordered_map>
41#include <unordered_set>
49#ifdef EXPENSIVE_CHECKS
61 cl::desc(
"Print before passes that change them"),
68 cl::desc(
"system dot used by change reporters"));
96 cl::desc(
"Generate dot files into specified directory for changed IRs"),
101 "print-on-crash-path",
102 cl::desc(
"Print the last form of the IR before crash to a file"),
107 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
111 "opt-bisect-print-ir-path",
116 cl::desc(
"Print pass names and their ordinals"));
120 cl::desc(
"Print IR at pass with this number as "
121 "reported by print-passes-names"));
134 cl::desc(
"exe called with module IR after each pass that "
139const Module *unwrapModule(
Any IR,
bool Force =
false) {
140 if (
const auto **M = any_cast<const Module *>(&
IR))
143 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
147 return (*F)->getParent();
150 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
154 return F.getParent();
157 assert(!Force &&
"Expected a module");
161 if (
const auto **L = any_cast<const Loop *>(&
IR)) {
162 const Function *
F = (*L)->getHeader()->getParent();
165 return F->getParent();
179 M->print(
OS,
nullptr);
181 for (
const auto &
F :
M->functions()) {
197 const Function *
F = L->getHeader()->getParent();
203std::string getIRName(
Any IR) {
204 if (any_cast<const Module *>(&
IR))
207 if (
const auto **
F = any_cast<const Function *>(&
IR))
208 return (*F)->getName().str();
210 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
211 return (*C)->getName();
213 if (
const auto **L = any_cast<const Loop *>(&
IR))
214 return (*L)->getName().str();
219bool moduleContainsFilterPrintFunc(
const Module &M) {
220 return any_of(M.functions(),
222 return isFunctionInPrintList(F.getName());
236 if (
const auto **M = any_cast<const Module *>(&
IR))
237 return moduleContainsFilterPrintFunc(**M);
239 if (
const auto **
F = any_cast<const Function *>(&
IR))
242 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
243 return sccContainsFilterPrintFunc(**
C);
245 if (
const auto **L = any_cast<const Loop *>(&
IR))
253 if (!shouldPrintIR(
IR))
257 auto *M = unwrapModule(
IR);
258 assert(M &&
"should have unwrapped module");
263 if (
const auto **M = any_cast<const Module *>(&
IR)) {
268 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
273 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
278 if (
const auto **L = any_cast<const Loop *>(&
IR)) {
288 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
289 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass"});
297 S.append(Clean.
str());
301 S.append(SR[0] ==
'<' ?
"<" :
">");
309 if (
const auto **M = any_cast<const Module *>(&
IR))
311 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
319bool isInterestingFunction(
const Function &
F) {
328 if (
const auto **
F = any_cast<const Function *>(&
IR))
329 return isInterestingFunction(**
F);
336 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
352 BeforeStack.emplace_back();
358 T &
Data = BeforeStack.back();
359 generateIRRepresentation(
IR, PassID,
Data);
365 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
367 std::string
Name = getIRName(
IR);
369 if (isIgnored(PassID)) {
371 handleIgnored(PassID,
Name);
374 handleFiltered(PassID,
Name);
377 T &Before = BeforeStack.back();
380 generateIRRepresentation(
IR, PassID, After);
383 if (Before == After) {
385 omitAfter(PassID,
Name);
387 handleAfter(PassID,
Name, Before, After,
IR);
389 BeforeStack.pop_back();
394 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
401 handleInvalidated(PassID);
402 BeforeStack.pop_back();
418 handleInvalidatedPass(
P);
429 auto *M = unwrapModule(
IR,
true);
430 assert(M &&
"Expected module to be unwrapped when forced.");
431 Out <<
"*** IR Dump At Start ***\n";
432 M->print(Out,
nullptr);
437 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
443 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
450 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
456 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
468 std::string &Output) {
470 unwrapAndPrint(
OS,
IR);
475 const std::string &Before,
476 const std::string &After,
Any) {
479 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
485 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
489 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" << After;
495 if (TestChanged !=
"")
505 dbgs() <<
"Unable to create temporary file.";
510 dbgs() <<
"Unable to find test-changed executable.";
514 StringRef Args[] = {TestChanged, FileName[0], PassID};
517 dbgs() <<
"Error executing test-changed executable.";
522 dbgs() <<
"Unable to remove temporary file.";
538 const std::string &Before,
539 const std::string &After,
Any) {
547 const auto &BFD = Before.
getData();
548 const auto &AFD = After.
getData();
549 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
550 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
551 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
552 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
554 auto HandlePotentiallyRemovedData = [&](std::string S) {
558 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
561 auto HandleNewData = [&](std::vector<const T *> &Q) {
563 for (
const T *NBI : Q)
564 HandlePair(
nullptr, NBI);
577 std::vector<const T *> NewDataQueue;
579 if (!BFD.count(*AI)) {
582 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
591 while (BI != BE && *BI != *AI) {
592 HandlePotentiallyRemovedData(*BI);
596 HandleNewData(NewDataQueue);
598 const T &AData = AFD.find(*AI)->getValue();
599 const T &BData = BFD.find(*AI)->getValue();
600 HandlePair(&BData, &AData);
608 HandlePotentiallyRemovedData(*BI);
612 HandleNewData(NewDataQueue);
618 std::function<
void(
bool InModule,
unsigned Minor,
621 if (!CompareModule) {
624 "Expected only one function.");
625 CompareFunc(
false, 0, Before.
getData().
begin()->getValue(),
634 assert((
B ||
A) &&
"Both functions cannot be missing.");
639 CompareFunc(
true, Minor++, *
B, *
A);
644 if (
const Module *M = getModuleForComparison(
IR)) {
647 generateFunctionData(
Data,
F);
651 const Function **FPtr = any_cast<const Function *>(&
IR);
652 const Function *
F = FPtr ? *FPtr :
nullptr;
654 const Loop **L = any_cast<const Loop *>(&
IR);
655 assert(L &&
"Unknown IR unit.");
656 F = (*L)->getHeader()->getParent();
658 assert(
F &&
"Unknown IR unit.");
659 generateFunctionData(
Data, *
F);
667 for (
const auto &
B :
F) {
668 std::string BBName =
B.getName().str();
669 if (BBName.empty()) {
676 Data.getOrder().emplace_back(
F.getName());
677 Data.getData().insert({
F.getName(), FD});
684 assert(ModuleDescStack.
empty() &&
"ModuleDescStack is not empty at exit");
687void PrintIRInstrumentation::pushModuleDesc(
StringRef PassID,
Any IR) {
692PrintIRInstrumentation::PrintModuleDesc
693PrintIRInstrumentation::popModuleDesc(
StringRef PassID) {
694 assert(!ModuleDescStack.
empty() &&
"empty ModuleDescStack");
695 PrintModuleDesc ModuleDesc = ModuleDescStack.
pop_back_val();
696 assert(std::get<2>(ModuleDesc).equals(PassID) &&
"malformed ModuleDescStack");
700void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
701 if (isIgnored(PassID))
708 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
709 shouldPrintAfterPass(PassID))
710 pushModuleDesc(PassID,
IR);
712 if (!shouldPrintIR(
IR))
717 if (shouldPrintPassNumbers())
718 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID <<
"\n";
720 if (!shouldPrintBeforePass(PassID))
723 dbgs() <<
"*** IR Dump Before " << PassID <<
" on " << getIRName(
IR)
725 unwrapAndPrint(
dbgs(),
IR);
728void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
729 if (isIgnored(PassID))
732 if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
733 !shouldPrintAtPassNumber())
739 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
740 assert(StoredPassID == PassID &&
"mismatched PassID");
742 if (!shouldPrintIR(
IR) || !shouldPrintAfterPass(PassID))
745 dbgs() <<
"*** IR Dump "
746 << (shouldPrintAtPassNumber()
749 <<
" on " << IRName <<
" ***\n";
750 unwrapAndPrint(
dbgs(),
IR);
753void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
754 if (isIgnored(PassID))
757 if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
758 !shouldPrintAtPassNumber())
764 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
765 assert(StoredPassID == PassID &&
"mismatched PassID");
768 if (!M || !shouldPrintAfterPass(PassID))
772 if (shouldPrintAtPassNumber())
773 Banner =
formatv(
"*** IR Dump At {0}-{1} on {2} (invalidated) ***",
774 CurrentPassNumber, PassID, IRName);
776 Banner =
formatv(
"*** IR Dump After {0} on {1} (invalidated) ***",
778 dbgs() << Banner <<
"\n";
782bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
790bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
801bool PrintIRInstrumentation::shouldPrintPassNumbers() {
805bool PrintIRInstrumentation::shouldPrintAtPassNumber() {
815 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
820 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
824 this->printAfterPass(
P,
IR);
828 this->printAfterPassInvalidated(
P);
840 const Function **FPtr = any_cast<const Function *>(&
IR);
841 const Function *
F = FPtr ? *FPtr :
nullptr;
843 if (
const auto **L = any_cast<const Loop *>(&
IR))
844 F = (*L)->getHeader()->getParent();
846 bool ShouldRun = !(
F &&
F->hasOptNone());
847 if (!ShouldRun && DebugLogging) {
848 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
849 <<
" due to optnone attribute\n";
863 this->HasWrittenIR =
true;
864 const Module *M = unwrapModule(
IR,
true);
865 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
870 M->print(
OS,
nullptr);
899 std::vector<StringRef> SpecialPasses;
901 SpecialPasses.emplace_back(
"PassManager");
902 SpecialPasses.emplace_back(
"PassAdaptor");
908 "Unexpectedly skipping special pass");
910 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
918 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
919 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
920 unsigned Count = (*F)->getInstructionCount();
921 OS <<
" (" << Count <<
" instruction";
925 }
else if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
926 int Count = (*C)->size();
927 OS <<
" (" << Count <<
" node";
953 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
960 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
964 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
970 bool TrackBBLifetime) {
973 for (
const auto &BB : *
F) {
975 BBGuards->try_emplace(intptr_t(&BB), &BB);
979 BBGuards->try_emplace(intptr_t(Succ), Succ);
986 out << BB->
getName() <<
"<" << BB <<
">";
991 out <<
"unnamed_removed<" << BB <<
">";
1001 unsigned FuncOrderBlockNum = 0;
1005 FuncOrderBlockNum++;
1007 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1015 out <<
"Some blocks were deleted\n";
1020 if (Before.
Graph.size() != After.
Graph.size())
1021 out <<
"Different number of non-leaf basic blocks: before="
1022 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1024 for (
auto &BB : Before.
Graph) {
1025 auto BA = After.
Graph.find(BB.first);
1026 if (BA == After.
Graph.end()) {
1027 out <<
"Non-leaf block ";
1029 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1033 for (
auto &BA : After.
Graph) {
1034 auto BB = Before.
Graph.find(BA.first);
1035 if (BB == Before.
Graph.end()) {
1036 out <<
"Non-leaf block ";
1038 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1042 if (BB->second == BA.second)
1045 out <<
"Different successors of block ";
1047 out <<
" (unordered):\n";
1048 out <<
"- before (" << BB->second.size() <<
"): ";
1049 for (
auto &SuccB : BB->second) {
1051 if (SuccB.second != 1)
1052 out <<
"(" << SuccB.second <<
"), ";
1057 out <<
"- after (" << BA.second.size() <<
"): ";
1058 for (
auto &SuccA : BA.second) {
1060 if (SuccA.second != 1)
1061 out <<
"(" << SuccA.second <<
"), ";
1141 if (
const auto **MaybeF = any_cast<const Function *>(&
IR)) {
1143 }
else if (
const auto **MaybeM = any_cast<const Module *>(&
IR)) {
1155 bool Registered =
false;
1158#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1159 assert(&PassStack.emplace_back(
P));
1164 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1179 if (
auto *MaybeM = any_cast<const Module *>(&
IR)) {
1187#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1188 assert(PassStack.pop_back_val() ==
P &&
1189 "Before and After callbacks must correspond");
1196#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1197 assert(PassStack.pop_back_val() ==
P &&
1198 "Before and After callbacks must correspond");
1206 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1210 if (
auto *HashBefore =
1214 "Function @{0} changed by {1} without invalidating analyses",
1220 const CFG &GraphBefore,
const CFG &GraphAfter) {
1221 if (GraphAfter == GraphBefore)
1225 <<
"Error: " <<
Pass
1226 <<
" does not invalidate CFG analyses but CFG changes detected in "
1228 << FuncName <<
":\n";
1233 if (
auto *GraphBefore =
1235 CheckCFG(
P,
F->getName(), *GraphBefore,
1238 if (
auto *MaybeM = any_cast<const Module *>(&
IR)) {
1240 if (
auto *HashBefore =
1244 "Module changed by {0} without invalidating analyses",
P));
1255 if (isIgnored(
P) ||
P ==
"VerifierPass")
1257 const Function **FPtr = any_cast<const Function *>(&
IR);
1258 const Function *
F = FPtr ? *FPtr :
nullptr;
1260 if (
const auto **L = any_cast<const Loop *>(&
IR))
1261 F = (*L)->getHeader()->getParent();
1266 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1271 const Module **MPtr = any_cast<const Module *>(&
IR);
1272 const Module *M = MPtr ? *MPtr :
nullptr;
1274 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
1275 M = (*C)->begin()->getFunction().getParent();
1280 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1302 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1306 [&](
bool InModule,
unsigned Minor,
1309 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1310 Minor, Before, After);
1321 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1328 const std::string Removed =
1329 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1330 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1331 const std::string NoChange =
" %l\n";
1332 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1354 this->runAfterPass();
1366void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1375class DotCfgDiffDisplayGraph;
1378class DisplayElement {
1381 StringRef getColour()
const {
return Colour; }
1384 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1390class DisplayEdge :
public DisplayElement {
1395 std::string getValue()
const {
return Value; }
1397 const DisplayNode &getDestinationNode()
const {
return Node; }
1401 const DisplayNode &
Node;
1405class DisplayNode :
public DisplayElement {
1413 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1414 ChildIterator children_begin()
const {
return Children.cbegin(); }
1415 ChildIterator children_end()
const {
return Children.cend(); }
1418 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1419 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1420 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1426 std::string getContent()
const {
return Content; }
1429 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1430 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1431 return *EdgeMap.find(&To)->second;
1436 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1437 return getEdge(Sink).getValue();
1440 void createEdgeMap();
1448 std::vector<DisplayEdge> Edges;
1450 std::vector<DisplayEdge *> EdgePtrs;
1451 std::unordered_set<DisplayNode *>
Children;
1452 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1455 bool AllEdgesCreated =
false;
1459class DotCfgDiffDisplayGraph {
1461 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1464 void generateDotFile(
StringRef DotFile);
1467 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1468 NodeIterator nodes_begin()
const {
1469 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1470 return NodePtrs.cbegin();
1472 NodeIterator nodes_end()
const {
1473 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1474 return NodePtrs.cend();
1479 void setEntryNode(
unsigned N) {
1481 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1482 NodeGenerationComplete =
true;
1483 for (
auto &
N : Nodes)
1484 NodePtrs.emplace_back(&
N);
1486 EntryNode = NodePtrs[
N];
1490 void createNode(std::string
C,
StringRef Colour) {
1491 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1492 Nodes.emplace_back(
C, Colour);
1495 DisplayNode &getNode(
unsigned N) {
1496 assert(
N < Nodes.size() &&
"Node is out of bounds");
1499 unsigned size()
const {
1500 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1501 return Nodes.size();
1505 std::string getGraphName()
const {
return GraphName; }
1510 return Node.getContent();
1514 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1515 return attribute(
Node.getColour());
1519 std::string getEdgeColorAttr(
const DisplayNode &
From,
1520 const DisplayNode &To)
const {
1521 return attribute(
From.getEdge(To).getColour());
1525 DisplayNode *getEntryNode()
const {
1526 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1532 std::string attribute(
StringRef Colour)
const {
1533 return "color=" + Colour.
str();
1536 bool NodeGenerationComplete =
false;
1537 const std::string GraphName;
1538 std::vector<DisplayNode> Nodes;
1539 std::vector<DisplayNode *> NodePtrs;
1540 DisplayNode *EntryNode =
nullptr;
1545 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1546 Edges.emplace_back(
Value.str(),
Node, Colour);
1550void DisplayNode::createEdgeMap() {
1553 AllEdgesCreated =
true;
1554 for (
auto &
E : Edges)
1555 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1558class DotCfgDiffNode;
1562class DotCfgDiffNode {
1564 DotCfgDiffNode() =
delete;
1570 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1571 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1576 unsigned getIndex()
const {
return N; }
1580 assert(
Data[0] &&
"Expected Data[0] to be set.");
1581 return Data[0]->getLabel();
1584 StringRef getColour()
const {
return Colour; }
1588 assert(!
Data[1] &&
"Expected only one block datum");
1596 "Unexpected edge count and color.");
1597 EdgesMap[
E] = {
Value.str(), Colour};
1603 StringRef getEdgeColour(
const unsigned S)
const {
1604 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1605 return EdgesMap.at(S).second;
1609 std::string getBodyContent()
const;
1611 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1612 std::map<const unsigned, unsigned> &NodeMap)
const;
1619 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1621 std::vector<unsigned> Edges;
1634 DotCfgDiff(
const DotCfgDiff &) =
delete;
1635 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1637 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1644 StringRef getEdgeSourceLabel(
const unsigned &Source,
1645 const unsigned &Sink)
const {
1647 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1648 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1649 return EdgeLabels.find(S)->getValue();
1653 unsigned size()
const {
return Nodes.size(); }
1655 const DotCfgDiffNode &getNode(
unsigned N)
const {
1656 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1662 std::string colourize(std::string S,
StringRef Colour)
const;
1665 unsigned Pos = Nodes.size();
1666 Nodes.emplace_back(*
this, Pos, BD,
C);
1667 NodePosition.insert({
Label, Pos});
1673 std::vector<DotCfgDiffNode> Nodes;
1675 const std::string GraphName;
1680std::string DotCfgDiffNode::getBodyContent()
const {
1682 assert(
Data[1] &&
"Expected Data[1] to be set.");
1685 for (
unsigned I = 0;
I < 2; ++
I) {
1686 SR[
I] =
Data[
I]->getBody();
1688 if (SR[
I][0] ==
'\n')
1691 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1695 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1697 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1699 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1700 std::string Diff =
Data[0]->getLabel().str();
1701 Diff +=
":\n<BR align=\"left\"/>" +
1702 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1703 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1708 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1711 std::string S =
R.sub(
"", Diff, &
Error);
1722 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1723 std::string Body = makeHTMLReady(
Data[0]->getBody());
1727 if (BS.
front() ==
'\n')
1732 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1734 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1737 while (BS1.
size()) {
1738 S.append(
"<BR align=\"left\"/>");
1740 S.append(
Line.str());
1743 S.append(
"<BR align=\"left\"/></FONT>");
1747std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1748 if (S.length() == 0)
1750 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1755 : GraphName(Title.str()) {
1768 Sink !=
E; ++Sink) {
1769 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1770 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1779 unsigned C = NodePosition.count(Label);
1784 assert(
C == 1 &&
"Unexpected multiple nodes.");
1785 Nodes[NodePosition[
Label]].setCommon(BD);
1790 Sink !=
E; ++Sink) {
1791 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1792 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1793 unsigned C = EdgesMap.
count(Key);
1803 for (
auto &
E : EdgesMap) {
1806 auto SP1 = S.
rsplit(
' ');
1807 auto &SourceSink = SP1.first;
1808 auto SP2 = SourceSink.split(
' ');
1813 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
1814 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
1815 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
1816 unsigned SinkNode = NodePosition[
Sink];
1820 if (EdgeLabels.count(SourceSink) == 0)
1821 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
1823 StringRef V = EdgeLabels.find(SourceSink)->getValue();
1824 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
1826 EdgeLabels[SourceSink] =
NV;
1828 SourceNode.addEdge(SinkNode,
Value, Colour);
1830 for (
auto &
I : Nodes)
1834DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
1836 assert(NodePosition.count(EntryNodeName) == 1 &&
1837 "Expected to find entry block in map.");
1838 unsigned Entry = NodePosition[EntryNodeName];
1839 assert(Entry < Nodes.size() &&
"Expected to find entry node");
1840 DotCfgDiffDisplayGraph
G(Title.
str());
1842 std::map<const unsigned, unsigned> NodeMap;
1844 int EntryIndex = -1;
1846 for (
auto &
I : Nodes) {
1847 if (
I.getIndex() == Entry)
1849 G.createNode(
I.getBodyContent(),
I.getColour());
1850 NodeMap.insert({
I.getIndex(),
Index++});
1852 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
1853 G.setEntryNode(EntryIndex);
1855 for (
auto &
I : NodeMap) {
1856 unsigned SourceNode =
I.first;
1857 unsigned DisplayNode =
I.second;
1858 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
1863void DotCfgDiffNode::createDisplayEdges(
1864 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
1865 std::map<const unsigned, unsigned> &NodeMap)
const {
1867 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
1869 for (
auto I : Edges) {
1870 unsigned SinkNodeIndex =
I;
1871 StringRef Colour = getEdgeColour(SinkNodeIndex);
1872 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
1874 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
1875 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
1876 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
1878 SourceDisplayNode.createEdgeMap();
1881void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
1882 for (
auto E : EdgesMap) {
1884 Edges.emplace_back(
E.first);
1900 return G->getEntryNode();
1903 return N->children_begin();
1907 return G->nodes_begin();
1910 return G->nodes_end();
1913 return N->edges_begin();
1917 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
1927 return DiffData->getGraphName();
1931 return "\tsize=\"190, 190\";\n";
1934 const DotCfgDiffDisplayGraph *DiffData) {
1935 return DiffData->getNodeLabel(*Node);
1938 const DotCfgDiffDisplayGraph *DiffData) {
1939 return DiffData->getNodeAttributes(*Node);
1942 DisplayNode::ChildIterator &To) {
1943 return From->getEdgeSourceLabel(**To);
1946 DisplayNode::ChildIterator &To,
1947 const DotCfgDiffDisplayGraph *DiffData) {
1948 return DiffData->getEdgeColorAttr(*
From, **To);
1956void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
1960 errs() <<
"Error: " <<
EC.message() <<
"\n";
1975 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
1976 if (Br->isUnconditional())
1982 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
1985 for (
auto &
C : Sw->cases()) {
1986 assert(
C.getCaseValue() &&
"Expected to find case value.");
2002 assert(
HTML &&
"Expected outstream to be set");
2007 Extender =
formatv(
"{0}_{1}",
N, Minor);
2016 std::string DotFile =
Twine(SV).
str();
2024 DotCfgDiff Diff(
Text, Before, After);
2027 if (EntryBlockName ==
"")
2029 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2031 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2032 DG.generateDotFile(DotFile);
2037 errs() <<
"Error: " << EC.message() <<
"\n";
2046 return "Unable to find dot executable.";
2051 return "Error executing system dot.";
2055 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2060 assert(
HTML &&
"Expected outstream to be set");
2061 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2062 <<
"Initial IR (by function)</button>\n"
2063 <<
"<div class=\"content\">\n"
2072 [&](
bool InModule,
unsigned Minor,
2076 Minor, Before, After);
2089 assert(
HTML &&
"Expected outstream to be set");
2091 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2092 N, makeHTMLReady(PassID),
Name);
2100 assert(
HTML &&
"Expected outstream to be set");
2103 [&](
bool InModule,
unsigned Minor,
2107 Minor, Before, After);
2109 *
HTML <<
" </p></div>\n";
2114 assert(
HTML &&
"Expected outstream to be set");
2116 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2122 assert(
HTML &&
"Expected outstream to be set");
2124 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2125 makeHTMLReady(PassID),
Name);
2131 assert(
HTML &&
"Expected outstream to be set");
2133 makeHTMLReady(PassID),
Name);
2140 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2146 *
HTML <<
"<!doctype html>"
2149 <<
"<style>.collapsible { "
2150 <<
"background-color: #777;"
2152 <<
" cursor: pointer;"
2153 <<
" padding: 18px;"
2156 <<
" text-align: left;"
2157 <<
" outline: none;"
2158 <<
" font-size: 15px;"
2159 <<
"} .active, .collapsible:hover {"
2160 <<
" background-color: #555;"
2162 <<
" padding: 0 18px;"
2163 <<
" display: none;"
2164 <<
" overflow: hidden;"
2165 <<
" background-color: #f1f1f1;"
2168 <<
"<title>passes.html</title>"
2178 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2180 <<
"for (i = 0; i < coll.length; i++) {"
2181 <<
"coll[i].addEventListener(\"click\", function() {"
2182 <<
" this.classList.toggle(\"active\");"
2183 <<
" var content = this.nextElementSibling;"
2184 <<
" if (content.style.display === \"block\"){"
2185 <<
" content.style.display = \"none\";"
2188 <<
" content.style.display= \"block\";"
2206 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2212 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2219 : PrintPass(DebugLogging, PrintPassOpts),
2220 OptNone(DebugLogging),
2245void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2252 "Did not expect to get here without option set.");
2261 "Did not expect to get here without option set.");
2262 CrashReporter =
nullptr;
2271 CrashReporter =
this;
2277 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2280 OS <<
" Filtered Out ***\n";
2283 OS <<
" Started ***\n";
2284 unwrapAndPrint(
OS,
IR);
This file provides Any, a non-template class modeled in the spirit of std::any.
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::optional< std::vector< StOtherPiece > > Other
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 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
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
Module.h This file contains the declarations for the Module class.
ppc ctr loops PowerPC CTR Loops Verify
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
This header defines various interfaces for pass management in LLVM.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 > 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::opt< bool > VerifyAnalysisInvalidation("verify-analysis-invalidation", cl::Hidden, cl::init(false))
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< unsigned > PrintAtPassNumber("print-at-pass-number", cl::init(0), cl::Hidden, cl::desc("Print IR at pass with this number as " "reported by print-passes-names"))
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
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)
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 <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
bool isEntryBlock() const
Return true if this is the entry block of the containing function.
const Function * getParent() const
Return the enclosing method, or null if none.
const T & getData() const
Conditional or Unconditional Branch instruction.
Represents analyses that only rely on functions' control flow.
void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName)
void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName)
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
void handleInvalidatedPass(StringRef PassID)
virtual ~ChangeReporter()
void addSuccessorLabel(StringRef Succ, StringRef Label)
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.
Lightweight error class with error context and mandatory checking.
std::string getEntryBlockName() const
~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
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)
static bool generateFunctionData(IRDataT< T > &Data, const Function &F)
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)
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This is an important class for using LLVM in a threaded context.
OptPassGate & getOptPassGate() const
Access the object which can disable optional passes and individual optimizations at compile time.
A node in the call graph.
An SCC of the call graph.
Represents a single loop in the control flow graph.
A Module instance is used to store all the information related to an LLVM module.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
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().
virtual bool shouldRunPass(const StringRef PassName, StringRef IRDescription)
IRDescription is a textual description of the IR unit the pass is running over.
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 registerAnalysesClearedCallback(CallableT C)
void registerBeforeAnalysisCallback(CallableT C)
void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront=false)
void registerAnalysisInvalidatedCallback(CallableT C)
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
void registerAfterAnalysisCallback(CallableT C, bool ToFront=false)
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerBeforeSkippedPassCallback(CallableT C)
void registerShouldRunOptionalPassCallback(CallableT C)
void registerAfterPassCallback(CallableT C, bool ToFront=false)
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.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
~PrintCrashIRInstrumentation()
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~PrintIRInstrumentation()
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)
StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - 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
size - Get the string size.
char front() const
front - 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.
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
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
TimeProfilingPassesHandler()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
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.
#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
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
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.
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
This is an optimization pass for GlobalISel generic memory operations.
Interval::succ_iterator succ_end(Interval *I)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code prepareTempFiles(SmallVector< int > &FD, ArrayRef< StringRef > SR, SmallVector< std::string > &FileName)
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.
bool forcePrintModuleIR()
std::vector< std::string > printAfterPasses()
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)
bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
bool shouldPrintBeforeAll()
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool shouldPrintAfterAll()
cl::opt< ChangePrinter > PrintChanged
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.
std::vector< std::string > printBeforePasses()
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
bool shouldPrintAfterSomePass()
void timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isFunctionInPrintList(StringRef FunctionName)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool isPassInPrintList(StringRef PassName)
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
void timeTraceProfilerEnd()
Manually end the last time section.
std::error_code cleanUpTempFiles(ArrayRef< std::string > FileName)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::array< uint32_t, 5 > ModuleHash
160 bits SHA1
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
uint64_t StructuralHash(const Function &F)
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
Result run(Function &F, FunctionAnalysisManager &FAM)
Run the analysis pass over a function and produce CFG.
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)
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
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 void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
CFG(const Function *F, bool TrackBBLifetime)
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
bool SkipAnalyses
Don't print information for analyses.
bool Verbose
Print adaptors and pass managers.
bool Indent
Indent based on hierarchy.