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"),
102 cl::desc(
"Print the last form of the IR before crash"),
106 "opt-bisect-print-ir-path",
120 cl::desc(
"exe called with module IR after each pass that "
125const Module *unwrapModule(
Any IR,
bool Force =
false) {
126 if (
const auto **M = any_cast<const Module *>(&
IR))
129 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
133 return (*F)->getParent();
136 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
140 return F.getParent();
143 assert(!Force &&
"Expected a module");
147 if (
const auto **L = any_cast<const Loop *>(&
IR)) {
148 const Function *
F = (*L)->getHeader()->getParent();
151 return F->getParent();
165 M->print(
OS,
nullptr);
167 for (
const auto &
F :
M->functions()) {
189std::string getIRName(
Any IR) {
190 if (any_cast<const Module *>(&
IR))
193 if (
const auto **
F = any_cast<const Function *>(&
IR))
194 return (*F)->getName().str();
196 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
197 return (*C)->getName();
199 if (
const auto **L = any_cast<const Loop *>(&
IR))
200 return (*L)->getName().str();
205bool moduleContainsFilterPrintFunc(
const Module &M) {
206 return any_of(M.functions(),
208 return isFunctionInPrintList(F.getName());
221bool shouldPrintIR(
Any IR) {
222 if (
const auto **M = any_cast<const Module *>(&
IR))
223 return moduleContainsFilterPrintFunc(**M);
225 if (
const auto **
F = any_cast<const Function *>(&
IR))
228 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
229 return sccContainsFilterPrintFunc(**
C);
231 if (
const auto **L = any_cast<const Loop *>(&
IR))
239 if (!shouldPrintIR(
IR))
243 auto *M = unwrapModule(
IR);
244 assert(M &&
"should have unwrapped module");
249 if (
const auto **M = any_cast<const Module *>(&
IR)) {
254 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
259 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
264 if (
const auto **L = any_cast<const Loop *>(&
IR)) {
274 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
275 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass"});
283 S.append(Clean.
str());
287 S.append(SR[0] ==
'<' ?
"<" :
">");
295 if (
const auto **M = any_cast<const Module *>(&
IR))
297 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
305bool isInterestingFunction(
const Function &
F) {
314 if (
const auto **
F = any_cast<const Function *>(&
IR))
315 return isInterestingFunction(**
F);
322 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
338 BeforeStack.emplace_back();
344 T &
Data = BeforeStack.back();
345 generateIRRepresentation(
IR, PassID,
Data);
351 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
353 std::string
Name = getIRName(
IR);
355 if (isIgnored(PassID)) {
357 handleIgnored(PassID,
Name);
360 handleFiltered(PassID,
Name);
363 T &Before = BeforeStack.back();
366 generateIRRepresentation(
IR, PassID, After);
369 if (Before == After) {
371 omitAfter(PassID,
Name);
373 handleAfter(PassID,
Name, Before, After,
IR);
375 BeforeStack.pop_back();
380 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
387 handleInvalidated(PassID);
388 BeforeStack.pop_back();
404 handleInvalidatedPass(
P);
415 auto *M = unwrapModule(
IR,
true);
416 assert(M &&
"Expected module to be unwrapped when forced.");
417 Out <<
"*** IR Dump At Start ***\n";
418 M->print(Out,
nullptr);
423 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
429 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
436 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
442 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
454 std::string &Output) {
456 unwrapAndPrint(
OS,
IR);
461 const std::string &Before,
462 const std::string &After,
Any) {
465 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
471 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
475 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" << After;
481 if (TestChanged !=
"")
491 dbgs() <<
"Unable to create temporary file.";
496 dbgs() <<
"Unable to find test-changed executable.";
500 StringRef Args[] = {TestChanged, FileName[0], PassID};
503 dbgs() <<
"Error executing test-changed executable.";
508 dbgs() <<
"Unable to remove temporary file.";
524 const std::string &Before,
525 const std::string &After,
Any) {
533 const auto &BFD = Before.
getData();
534 const auto &AFD = After.
getData();
535 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
536 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
537 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
538 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
540 auto HandlePotentiallyRemovedData = [&](std::string S) {
544 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
547 auto HandleNewData = [&](std::vector<const T *> &Q) {
549 for (
const T *NBI : Q)
550 HandlePair(
nullptr, NBI);
563 std::vector<const T *> NewDataQueue;
565 if (!BFD.count(*AI)) {
568 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
577 while (BI != BE && *BI != *AI) {
578 HandlePotentiallyRemovedData(*BI);
582 HandleNewData(NewDataQueue);
584 const T &AData = AFD.find(*AI)->getValue();
585 const T &BData = BFD.find(*AI)->getValue();
586 HandlePair(&BData, &AData);
594 HandlePotentiallyRemovedData(*BI);
598 HandleNewData(NewDataQueue);
604 std::function<
void(
bool InModule,
unsigned Minor,
607 if (!CompareModule) {
610 "Expected only one function.");
611 CompareFunc(
false, 0, Before.
getData().
begin()->getValue(),
620 assert((
B ||
A) &&
"Both functions cannot be missing.");
625 CompareFunc(
true, Minor++, *
B, *
A);
630 if (
const Module *M = getModuleForComparison(
IR)) {
633 generateFunctionData(
Data,
F);
637 const Function **FPtr = any_cast<const Function *>(&
IR);
638 const Function *
F = FPtr ? *FPtr :
nullptr;
640 const Loop **L = any_cast<const Loop *>(&
IR);
641 assert(L &&
"Unknown IR unit.");
642 F = (*L)->getHeader()->getParent();
644 assert(
F &&
"Unknown IR unit.");
645 generateFunctionData(
Data, *
F);
653 for (
const auto &
B :
F) {
654 std::string BBName =
B.getName().str();
655 if (BBName.empty()) {
662 Data.getOrder().emplace_back(
F.getName());
663 Data.getData().insert({
F.getName(), FD});
670 assert(ModuleDescStack.
empty() &&
"ModuleDescStack is not empty at exit");
673void PrintIRInstrumentation::pushModuleDesc(
StringRef PassID,
Any IR) {
678PrintIRInstrumentation::PrintModuleDesc
679PrintIRInstrumentation::popModuleDesc(
StringRef PassID) {
680 assert(!ModuleDescStack.
empty() &&
"empty ModuleDescStack");
681 PrintModuleDesc ModuleDesc = ModuleDescStack.
pop_back_val();
682 assert(std::get<2>(ModuleDesc).equals(PassID) &&
"malformed ModuleDescStack");
686void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
687 if (isIgnored(PassID))
694 if (shouldPrintAfterPass(PassID))
695 pushModuleDesc(PassID,
IR);
697 if (!shouldPrintBeforePass(PassID))
700 if (!shouldPrintIR(
IR))
703 dbgs() <<
"*** IR Dump Before " << PassID <<
" on " << getIRName(
IR)
705 unwrapAndPrint(
dbgs(),
IR);
708void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
709 if (isIgnored(PassID))
712 if (!shouldPrintAfterPass(PassID))
718 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
719 assert(StoredPassID == PassID &&
"mismatched PassID");
721 if (!shouldPrintIR(
IR))
724 dbgs() <<
"*** IR Dump After " << PassID <<
" on " << IRName <<
" ***\n";
725 unwrapAndPrint(
dbgs(),
IR);
728void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
730 if (!shouldPrintAfterPass(
PassName))
733 if (isIgnored(PassID))
739 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
740 assert(StoredPassID == PassID &&
"mismatched PassID");
747 formatv(
"*** IR Dump After {0} on {1} (invalidated) ***", PassID, IRName);
748 dbgs() << Banner <<
"\n";
752bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
760bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
781 this->printAfterPass(
P,
IR);
785 this->printAfterPassInvalidated(
P);
797 const Function **FPtr = any_cast<const Function *>(&
IR);
798 const Function *
F = FPtr ? *FPtr :
nullptr;
800 if (
const auto **L = any_cast<const Loop *>(&
IR))
801 F = (*L)->getHeader()->getParent();
803 bool ShouldRun = !(
F &&
F->hasOptNone());
804 if (!ShouldRun && DebugLogging) {
805 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
806 <<
" due to optnone attribute\n";
820 this->HasWrittenIR =
true;
821 const Module *M = unwrapModule(
IR,
true);
822 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
827 M->print(
OS,
nullptr);
856 std::vector<StringRef> SpecialPasses;
858 SpecialPasses.emplace_back(
"PassManager");
859 SpecialPasses.emplace_back(
"PassAdaptor");
865 "Unexpectedly skipping special pass");
867 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
875 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
876 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
877 unsigned Count = (*F)->getInstructionCount();
878 OS <<
" (" << Count <<
" instruction";
882 }
else if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
883 int Count = (*C)->size();
884 OS <<
" (" << Count <<
" node";
910 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
917 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
921 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
927 bool TrackBBLifetime) {
930 for (
const auto &BB : *
F) {
932 BBGuards->try_emplace(intptr_t(&BB), &BB);
936 BBGuards->try_emplace(intptr_t(Succ), Succ);
943 out << BB->
getName() <<
"<" << BB <<
">";
948 out <<
"unnamed_removed<" << BB <<
">";
958 unsigned FuncOrderBlockNum = 0;
964 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
972 out <<
"Some blocks were deleted\n";
977 if (Before.
Graph.size() != After.
Graph.size())
978 out <<
"Different number of non-leaf basic blocks: before="
979 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
981 for (
auto &BB : Before.
Graph) {
982 auto BA = After.
Graph.find(BB.first);
983 if (BA == After.
Graph.end()) {
984 out <<
"Non-leaf block ";
986 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
990 for (
auto &BA : After.
Graph) {
991 auto BB = Before.
Graph.find(BA.first);
992 if (BB == Before.
Graph.end()) {
993 out <<
"Non-leaf block ";
995 out <<
" is added (" << BA.second.size() <<
" successors)\n";
999 if (BB->second == BA.second)
1002 out <<
"Different successors of block ";
1004 out <<
" (unordered):\n";
1005 out <<
"- before (" << BB->second.size() <<
"): ";
1006 for (
auto &SuccB : BB->second) {
1008 if (SuccB.second != 1)
1009 out <<
"(" << SuccB.second <<
"), ";
1014 out <<
"- after (" << BA.second.size() <<
"): ";
1015 for (
auto &SuccA : BA.second) {
1017 if (SuccA.second != 1)
1018 out <<
"(" << SuccA.second <<
"), ";
1098 if (
const auto **MaybeF = any_cast<const Function *>(&
IR)) {
1100 }
else if (
const auto **MaybeM = any_cast<const Module *>(&
IR)) {
1112 bool Registered =
false;
1115#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1116 assert(&PassStack.emplace_back(
P));
1121 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1136 if (
auto *MaybeM = any_cast<const Module *>(&
IR)) {
1144#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1145 assert(PassStack.pop_back_val() ==
P &&
1146 "Before and After callbacks must correspond");
1153#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1154 assert(PassStack.pop_back_val() ==
P &&
1155 "Before and After callbacks must correspond");
1163 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1167 if (
auto *HashBefore =
1171 "Function @{0} changed by {1} without invalidating analyses",
1177 const CFG &GraphBefore,
const CFG &GraphAfter) {
1178 if (GraphAfter == GraphBefore)
1182 <<
"Error: " <<
Pass
1183 <<
" does not invalidate CFG analyses but CFG changes detected in "
1185 << FuncName <<
":\n";
1190 if (
auto *GraphBefore =
1192 CheckCFG(
P,
F->getName(), *GraphBefore,
1195 if (
auto *MaybeM = any_cast<const Module *>(&
IR)) {
1197 if (
auto *HashBefore =
1201 "Module changed by {0} without invalidating analyses",
P));
1212 if (isIgnored(
P) ||
P ==
"VerifierPass")
1214 const Function **FPtr = any_cast<const Function *>(&
IR);
1215 const Function *
F = FPtr ? *FPtr :
nullptr;
1217 if (
const auto **L = any_cast<const Loop *>(&
IR))
1218 F = (*L)->getHeader()->getParent();
1223 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1228 const Module **MPtr = any_cast<const Module *>(&
IR);
1229 const Module *M = MPtr ? *MPtr :
nullptr;
1231 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
1232 M = (*C)->begin()->getFunction().getParent();
1237 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1259 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1263 [&](
bool InModule,
unsigned Minor,
1266 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1267 Minor, Before, After);
1278 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1285 const std::string Removed =
1286 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1287 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1288 const std::string NoChange =
" %l\n";
1289 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1311 this->runAfterPass();
1323void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1332class DotCfgDiffDisplayGraph;
1335class DisplayElement {
1338 StringRef getColour()
const {
return Colour; }
1341 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1347class DisplayEdge :
public DisplayElement {
1352 std::string getValue()
const {
return Value; }
1354 const DisplayNode &getDestinationNode()
const {
return Node; }
1358 const DisplayNode &
Node;
1362class DisplayNode :
public DisplayElement {
1370 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1371 ChildIterator children_begin()
const {
return Children.cbegin(); }
1372 ChildIterator children_end()
const {
return Children.cend(); }
1375 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1376 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1377 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1383 std::string getContent()
const {
return Content; }
1386 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1387 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1388 return *EdgeMap.find(&To)->second;
1393 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1394 return getEdge(Sink).getValue();
1397 void createEdgeMap();
1405 std::vector<DisplayEdge> Edges;
1407 std::vector<DisplayEdge *> EdgePtrs;
1408 std::unordered_set<DisplayNode *>
Children;
1409 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1412 bool AllEdgesCreated =
false;
1416class DotCfgDiffDisplayGraph {
1418 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1421 void generateDotFile(
StringRef DotFile);
1424 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1425 NodeIterator nodes_begin()
const {
1426 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1427 return NodePtrs.cbegin();
1429 NodeIterator nodes_end()
const {
1430 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1431 return NodePtrs.cend();
1436 void setEntryNode(
unsigned N) {
1438 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1439 NodeGenerationComplete =
true;
1440 for (
auto &
N : Nodes)
1441 NodePtrs.emplace_back(&
N);
1443 EntryNode = NodePtrs[
N];
1447 void createNode(std::string
C,
StringRef Colour) {
1448 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1449 Nodes.emplace_back(
C, Colour);
1452 DisplayNode &getNode(
unsigned N) {
1453 assert(
N < Nodes.size() &&
"Node is out of bounds");
1456 unsigned size()
const {
1457 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1458 return Nodes.size();
1462 std::string getGraphName()
const {
return GraphName; }
1467 return Node.getContent();
1471 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1472 return attribute(
Node.getColour());
1476 std::string getEdgeColorAttr(
const DisplayNode &
From,
1477 const DisplayNode &To)
const {
1478 return attribute(
From.getEdge(To).getColour());
1482 DisplayNode *getEntryNode()
const {
1483 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1489 std::string attribute(
StringRef Colour)
const {
1490 return "color=" + Colour.
str();
1493 bool NodeGenerationComplete =
false;
1494 const std::string GraphName;
1495 std::vector<DisplayNode> Nodes;
1496 std::vector<DisplayNode *> NodePtrs;
1497 DisplayNode *EntryNode =
nullptr;
1502 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1503 Edges.emplace_back(
Value.str(),
Node, Colour);
1507void DisplayNode::createEdgeMap() {
1510 AllEdgesCreated =
true;
1511 for (
auto &
E : Edges)
1512 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1515class DotCfgDiffNode;
1519class DotCfgDiffNode {
1521 DotCfgDiffNode() =
delete;
1527 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1528 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1533 unsigned getIndex()
const {
return N; }
1537 assert(
Data[0] &&
"Expected Data[0] to be set.");
1538 return Data[0]->getLabel();
1541 StringRef getColour()
const {
return Colour; }
1545 assert(!
Data[1] &&
"Expected only one block datum");
1553 "Unexpected edge count and color.");
1554 EdgesMap[
E] = {
Value.str(), Colour};
1560 StringRef getEdgeColour(
const unsigned S)
const {
1561 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1562 return EdgesMap.at(S).second;
1566 std::string getBodyContent()
const;
1568 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1569 std::map<const unsigned, unsigned> &NodeMap)
const;
1576 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1578 std::vector<unsigned> Edges;
1591 DotCfgDiff(
const DotCfgDiff &) =
delete;
1592 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1594 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1601 StringRef getEdgeSourceLabel(
const unsigned &Source,
1602 const unsigned &Sink)
const {
1604 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1605 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1606 return EdgeLabels.find(S)->getValue();
1610 unsigned size()
const {
return Nodes.size(); }
1612 const DotCfgDiffNode &getNode(
unsigned N)
const {
1613 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1619 std::string colourize(std::string S,
StringRef Colour)
const;
1622 unsigned Pos = Nodes.size();
1623 Nodes.emplace_back(*
this, Pos, BD,
C);
1624 NodePosition.insert({
Label, Pos});
1630 std::vector<DotCfgDiffNode> Nodes;
1632 const std::string GraphName;
1637std::string DotCfgDiffNode::getBodyContent()
const {
1639 assert(
Data[1] &&
"Expected Data[1] to be set.");
1642 for (
unsigned I = 0;
I < 2; ++
I) {
1643 SR[
I] =
Data[
I]->getBody();
1645 if (SR[
I][0] ==
'\n')
1648 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1652 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1654 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1656 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1657 std::string Diff =
Data[0]->getLabel().str();
1658 Diff +=
":\n<BR align=\"left\"/>" +
1659 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1660 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1665 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1668 std::string S =
R.sub(
"", Diff, &
Error);
1679 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1680 std::string Body = makeHTMLReady(
Data[0]->getBody());
1684 if (BS.
front() ==
'\n')
1689 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1691 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1694 while (BS1.
size()) {
1695 S.append(
"<BR align=\"left\"/>");
1697 S.append(
Line.str());
1700 S.append(
"<BR align=\"left\"/></FONT>");
1704std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1705 if (S.length() == 0)
1707 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1712 : GraphName(Title.str()) {
1725 Sink !=
E; ++Sink) {
1726 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1727 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1736 unsigned C = NodePosition.count(Label);
1741 assert(
C == 1 &&
"Unexpected multiple nodes.");
1742 Nodes[NodePosition[
Label]].setCommon(BD);
1747 Sink !=
E; ++Sink) {
1748 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1749 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1750 unsigned C = EdgesMap.
count(Key);
1760 for (
auto &
E : EdgesMap) {
1763 auto SP1 = S.
rsplit(
' ');
1764 auto &SourceSink = SP1.first;
1765 auto SP2 = SourceSink.split(
' ');
1770 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
1771 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
1772 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
1773 unsigned SinkNode = NodePosition[
Sink];
1777 if (EdgeLabels.count(SourceSink) == 0)
1778 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
1780 StringRef V = EdgeLabels.find(SourceSink)->getValue();
1781 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
1783 EdgeLabels[SourceSink] =
NV;
1785 SourceNode.addEdge(SinkNode,
Value, Colour);
1787 for (
auto &
I : Nodes)
1791DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
1793 assert(NodePosition.count(EntryNodeName) == 1 &&
1794 "Expected to find entry block in map.");
1795 unsigned Entry = NodePosition[EntryNodeName];
1796 assert(Entry < Nodes.size() &&
"Expected to find entry node");
1797 DotCfgDiffDisplayGraph
G(Title.
str());
1799 std::map<const unsigned, unsigned> NodeMap;
1801 int EntryIndex = -1;
1803 for (
auto &
I : Nodes) {
1804 if (
I.getIndex() == Entry)
1806 G.createNode(
I.getBodyContent(),
I.getColour());
1807 NodeMap.insert({
I.getIndex(),
Index++});
1809 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
1810 G.setEntryNode(EntryIndex);
1812 for (
auto &
I : NodeMap) {
1813 unsigned SourceNode =
I.first;
1814 unsigned DisplayNode =
I.second;
1815 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
1820void DotCfgDiffNode::createDisplayEdges(
1821 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
1822 std::map<const unsigned, unsigned> &NodeMap)
const {
1824 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
1826 for (
auto I : Edges) {
1827 unsigned SinkNodeIndex =
I;
1828 StringRef Colour = getEdgeColour(SinkNodeIndex);
1829 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
1831 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
1832 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
1833 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
1835 SourceDisplayNode.createEdgeMap();
1838void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
1839 for (
auto E : EdgesMap) {
1841 Edges.emplace_back(
E.first);
1857 return G->getEntryNode();
1860 return N->children_begin();
1864 return G->nodes_begin();
1867 return G->nodes_end();
1870 return N->edges_begin();
1874 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
1884 return DiffData->getGraphName();
1888 return "\tsize=\"190, 190\";\n";
1891 const DotCfgDiffDisplayGraph *DiffData) {
1892 return DiffData->getNodeLabel(*Node);
1895 const DotCfgDiffDisplayGraph *DiffData) {
1896 return DiffData->getNodeAttributes(*Node);
1899 DisplayNode::ChildIterator &To) {
1900 return From->getEdgeSourceLabel(**To);
1903 DisplayNode::ChildIterator &To,
1904 const DotCfgDiffDisplayGraph *DiffData) {
1905 return DiffData->getEdgeColorAttr(*
From, **To);
1913void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
1917 errs() <<
"Error: " <<
EC.message() <<
"\n";
1932 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
1933 if (Br->isUnconditional())
1939 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
1942 for (
auto &
C : Sw->cases()) {
1943 assert(
C.getCaseValue() &&
"Expected to find case value.");
1959 assert(
HTML &&
"Expected outstream to be set");
1964 Extender =
formatv(
"{0}_{1}",
N, Minor);
1973 std::string DotFile =
Twine(SV).
str();
1981 DotCfgDiff Diff(
Text, Before, After);
1984 if (EntryBlockName ==
"")
1986 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
1988 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
1989 DG.generateDotFile(DotFile);
1994 errs() <<
"Error: " << EC.message() <<
"\n";
2003 return "Unable to find dot executable.";
2008 return "Error executing system dot.";
2012 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2017 assert(
HTML &&
"Expected outstream to be set");
2018 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2019 <<
"Initial IR (by function)</button>\n"
2020 <<
"<div class=\"content\">\n"
2029 [&](
bool InModule,
unsigned Minor,
2033 Minor, Before, After);
2046 assert(
HTML &&
"Expected outstream to be set");
2048 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2049 N, makeHTMLReady(PassID),
Name);
2057 assert(
HTML &&
"Expected outstream to be set");
2060 [&](
bool InModule,
unsigned Minor,
2064 Minor, Before, After);
2066 *
HTML <<
" </p></div>\n";
2071 assert(
HTML &&
"Expected outstream to be set");
2073 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2079 assert(
HTML &&
"Expected outstream to be set");
2081 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2082 makeHTMLReady(PassID),
Name);
2088 assert(
HTML &&
"Expected outstream to be set");
2090 makeHTMLReady(PassID),
Name);
2097 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2103 *
HTML <<
"<!doctype html>"
2106 <<
"<style>.collapsible { "
2107 <<
"background-color: #777;"
2109 <<
" cursor: pointer;"
2110 <<
" padding: 18px;"
2113 <<
" text-align: left;"
2114 <<
" outline: none;"
2115 <<
" font-size: 15px;"
2116 <<
"} .active, .collapsible:hover {"
2117 <<
" background-color: #555;"
2119 <<
" padding: 0 18px;"
2120 <<
" display: none;"
2121 <<
" overflow: hidden;"
2122 <<
" background-color: #f1f1f1;"
2125 <<
"<title>passes.html</title>"
2135 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2137 <<
"for (i = 0; i < coll.length; i++) {"
2138 <<
"coll[i].addEventListener(\"click\", function() {"
2139 <<
" this.classList.toggle(\"active\");"
2140 <<
" var content = this.nextElementSibling;"
2141 <<
" if (content.style.display === \"block\"){"
2142 <<
" content.style.display = \"none\";"
2145 <<
" content.style.display= \"block\";"
2163 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2169 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2176 : PrintPass(DebugLogging, PrintPassOpts),
2177 OptNone(DebugLogging),
2192void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2207 CrashReporter =
nullptr;
2216 CrashReporter =
this;
2222 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2225 OS <<
" Filtered Out ***\n";
2228 OS <<
" Started ***\n";
2229 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.
Statically lint checks LLVM IR
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
Module.h This file contains the declarations for the Module class.
return ToRemove size() > 0
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< 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 > PrintCrashIR("print-on-crash", cl::desc("Print the last form of the IR before crash"), 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)
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.