39#include <unordered_map>
40#include <unordered_set>
60 cl::desc(
"Print before passes that change them"),
67 cl::desc(
"system dot used by change reporters"));
95 cl::desc(
"Generate dot files into specified directory for changed IRs"),
101 cl::desc(
"Print the last form of the IR before crash"),
105 "opt-bisect-print-ir-path",
119 cl::desc(
"exe called with module IR after each pass that "
124const Module *unwrapModule(
Any IR,
bool Force =
false) {
125 if (
const auto **M = any_cast<const Module *>(&
IR))
128 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
132 return (*F)->getParent();
135 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
139 return F.getParent();
142 assert(!Force &&
"Expected a module");
146 if (
const auto **L = any_cast<const Loop *>(&
IR)) {
147 const Function *
F = (*L)->getHeader()->getParent();
150 return F->getParent();
164 M->print(OS,
nullptr);
166 for (
const auto &
F :
M->functions()) {
189 if (any_cast<const Module *>(&
IR))
192 if (
const auto **
F = any_cast<const Function *>(&
IR))
193 return (*F)->getName().str();
195 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
196 return (*C)->getName();
198 if (
const auto **L = any_cast<const Loop *>(&
IR))
199 return (*L)->getName().str();
204bool moduleContainsFilterPrintFunc(
const Module &M) {
205 return any_of(M.functions(),
207 return isFunctionInPrintList(F.getName());
220bool shouldPrintIR(
Any IR) {
221 if (
const auto **M = any_cast<const Module *>(&
IR))
222 return moduleContainsFilterPrintFunc(**M);
224 if (
const auto **
F = any_cast<const Function *>(&
IR))
227 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
228 return sccContainsFilterPrintFunc(**
C);
230 if (
const auto **L = any_cast<const Loop *>(&
IR))
238 if (!shouldPrintIR(
IR))
242 auto *M = unwrapModule(
IR);
243 assert(M &&
"should have unwrapped module");
248 if (
const auto **M = any_cast<const Module *>(&
IR)) {
253 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
258 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
263 if (
const auto **L = any_cast<const Loop *>(&
IR)) {
273 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
274 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass"});
282 S.append(Clean.
str());
286 S.append(SR[0] ==
'<' ?
"<" :
">");
294 if (
const auto **M = any_cast<const Module *>(&
IR))
296 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
304bool isInterestingFunction(
const Function &
F) {
313 if (
const auto **
F = any_cast<const Function *>(&
IR))
314 return isInterestingFunction(**
F);
321 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
337 BeforeStack.emplace_back();
343 T &
Data = BeforeStack.back();
344 generateIRRepresentation(
IR, PassID,
Data);
350 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
352 std::string
Name = getIRName(
IR);
354 if (isIgnored(PassID)) {
356 handleIgnored(PassID,
Name);
359 handleFiltered(PassID,
Name);
362 T &Before = BeforeStack.back();
365 generateIRRepresentation(
IR, PassID, After);
368 if (Before == After) {
370 omitAfter(PassID,
Name);
372 handleAfter(PassID,
Name, Before, After,
IR);
374 BeforeStack.pop_back();
379 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
386 handleInvalidated(PassID);
387 BeforeStack.pop_back();
403 handleInvalidatedPass(
P);
414 auto *M = unwrapModule(
IR,
true);
415 assert(M &&
"Expected module to be unwrapped when forced.");
416 Out <<
"*** IR Dump At Start ***\n";
417 M->print(Out,
nullptr);
422 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
428 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
435 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
441 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
453 std::string &Output) {
455 unwrapAndPrint(OS,
IR);
460 const std::string &Before,
461 const std::string &After,
Any) {
464 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
470 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
474 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" << After;
480 if (TestChanged !=
"")
490 dbgs() <<
"Unable to create temporary file.";
495 dbgs() <<
"Unable to find test-changed executable.";
499 StringRef Args[] = {TestChanged, FileName[0], PassID};
502 dbgs() <<
"Error executing test-changed executable.";
507 dbgs() <<
"Unable to remove temporary file.";
523 const std::string &Before,
524 const std::string &After,
Any) {
532 const auto &BFD = Before.
getData();
533 const auto &AFD = After.
getData();
534 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
535 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
536 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
537 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
539 auto HandlePotentiallyRemovedData = [&](std::string S) {
543 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
546 auto HandleNewData = [&](std::vector<const T *> &Q) {
548 for (
const T *NBI : Q)
549 HandlePair(
nullptr, NBI);
562 std::vector<const T *> NewDataQueue;
564 if (!BFD.count(*AI)) {
567 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
576 while (BI != BE && *BI != *AI) {
577 HandlePotentiallyRemovedData(*BI);
581 HandleNewData(NewDataQueue);
583 const T &AData = AFD.find(*AI)->getValue();
584 const T &BData = BFD.find(*AI)->getValue();
585 HandlePair(&BData, &AData);
593 HandlePotentiallyRemovedData(*BI);
597 HandleNewData(NewDataQueue);
603 std::function<
void(
bool InModule,
unsigned Minor,
606 if (!CompareModule) {
609 "Expected only one function.");
610 CompareFunc(
false, 0, Before.
getData().
begin()->getValue(),
619 assert((
B ||
A) &&
"Both functions cannot be missing.");
624 CompareFunc(
true, Minor++, *
B, *
A);
629 if (
const Module *M = getModuleForComparison(
IR)) {
632 generateFunctionData(
Data,
F);
636 const Function **FPtr = any_cast<const Function *>(&
IR);
637 const Function *
F = FPtr ? *FPtr :
nullptr;
639 const Loop **L = any_cast<const Loop *>(&
IR);
640 assert(L &&
"Unknown IR unit.");
641 F = (*L)->getHeader()->getParent();
643 assert(
F &&
"Unknown IR unit.");
644 generateFunctionData(
Data, *
F);
652 for (
const auto &
B :
F) {
653 std::string BBName =
B.getName().str();
654 if (BBName.empty()) {
661 Data.getOrder().emplace_back(
F.getName());
662 Data.getData().insert({
F.getName(), FD});
669 assert(ModuleDescStack.
empty() &&
"ModuleDescStack is not empty at exit");
672void PrintIRInstrumentation::pushModuleDesc(
StringRef PassID,
Any IR) {
677PrintIRInstrumentation::PrintModuleDesc
678PrintIRInstrumentation::popModuleDesc(
StringRef PassID) {
679 assert(!ModuleDescStack.
empty() &&
"empty ModuleDescStack");
680 PrintModuleDesc ModuleDesc = ModuleDescStack.
pop_back_val();
681 assert(std::get<2>(ModuleDesc).equals(PassID) &&
"malformed ModuleDescStack");
685void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
686 if (isIgnored(PassID))
693 if (shouldPrintAfterPass(PassID))
694 pushModuleDesc(PassID,
IR);
696 if (!shouldPrintBeforePass(PassID))
699 if (!shouldPrintIR(
IR))
702 dbgs() <<
"*** IR Dump Before " << PassID <<
" on " << getIRName(
IR)
704 unwrapAndPrint(
dbgs(),
IR);
707void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
708 if (isIgnored(PassID))
711 if (!shouldPrintAfterPass(PassID))
717 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
718 assert(StoredPassID == PassID &&
"mismatched PassID");
720 if (!shouldPrintIR(
IR))
723 dbgs() <<
"*** IR Dump After " << PassID <<
" on " << IRName <<
" ***\n";
724 unwrapAndPrint(
dbgs(),
IR);
727void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
729 if (!shouldPrintAfterPass(
PassName))
732 if (isIgnored(PassID))
738 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
739 assert(StoredPassID == PassID &&
"mismatched PassID");
746 formatv(
"*** IR Dump After {0} on {1} (invalidated) ***", PassID, IRName);
747 dbgs() << Banner <<
"\n";
751bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
759bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
780 this->printAfterPass(
P,
IR);
784 this->printAfterPassInvalidated(
P);
796 const Function **FPtr = any_cast<const Function *>(&
IR);
797 const Function *
F = FPtr ? *FPtr :
nullptr;
799 if (
const auto **L = any_cast<const Loop *>(&
IR))
800 F = (*L)->getHeader()->getParent();
802 bool ShouldRun = !(
F &&
F->hasOptNone());
803 if (!ShouldRun && DebugLogging) {
804 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
805 <<
" due to optnone attribute\n";
819 this->HasWrittenIR =
true;
820 const Module *M = unwrapModule(
IR,
true);
821 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
826 M->print(OS,
nullptr);
855 std::vector<StringRef> SpecialPasses;
857 SpecialPasses.emplace_back(
"PassManager");
858 SpecialPasses.emplace_back(
"PassAdaptor");
864 "Unexpectedly skipping special pass");
866 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
874 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
875 if (
const auto **
F = any_cast<const Function *>(&
IR)) {
876 unsigned Count = (*F)->getInstructionCount();
877 OS <<
" (" << Count <<
" instruction";
881 }
else if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR)) {
882 int Count = (*C)->size();
883 OS <<
" (" << Count <<
" node";
909 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
916 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
920 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
926 bool TrackBBLifetime) {
929 for (
const auto &BB : *
F) {
942 out << BB->
getName() <<
"<" << BB <<
">";
947 out <<
"unnamed_removed<" << BB <<
">";
957 unsigned FuncOrderBlockNum = 0;
963 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
971 out <<
"Some blocks were deleted\n";
976 if (Before.
Graph.size() != After.
Graph.size())
977 out <<
"Different number of non-leaf basic blocks: before="
978 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
980 for (
auto &BB : Before.
Graph) {
981 auto BA = After.
Graph.find(BB.first);
982 if (BA == After.
Graph.end()) {
983 out <<
"Non-leaf block ";
985 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
989 for (
auto &BA : After.
Graph) {
990 auto BB = Before.
Graph.find(BA.first);
991 if (BB == Before.
Graph.end()) {
992 out <<
"Non-leaf block ";
994 out <<
" is added (" << BA.second.size() <<
" successors)\n";
998 if (BB->second == BA.second)
1001 out <<
"Different successors of block ";
1003 out <<
" (unordered):\n";
1004 out <<
"- before (" << BB->second.size() <<
"): ";
1005 for (
auto &SuccB : BB->second) {
1007 if (SuccB.second != 1)
1008 out <<
"(" << SuccB.second <<
"), ";
1013 out <<
"- after (" << BA.second.size() <<
"): ";
1014 for (
auto &SuccA : BA.second) {
1016 if (SuccA.second != 1)
1017 out <<
"(" << SuccA.second <<
"), ";
1068 const CFG &GraphAfter) {
1069 if (GraphAfter == GraphBefore)
1073 <<
" does not invalidate CFG analyses but CFG changes detected in "
1075 << FuncName <<
":\n";
1082#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1083 assert(&PassStack.emplace_back(
P));
1086 const auto **
F = any_cast<const Function *>(&
IR);
1096#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1097 assert(PassStack.pop_back_val() ==
P &&
1098 "Before and After callbacks must correspond");
1106#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1107 assert(PassStack.pop_back_val() ==
P &&
1108 "Before and After callbacks must correspond");
1112 const auto **
F = any_cast<const Function *>(&
IR);
1122 checkCFG(
P, (*F)->getName(), *GraphBefore,
1131 if (isIgnored(
P) ||
P ==
"VerifierPass")
1133 const Function **FPtr = any_cast<const Function *>(&
IR);
1134 const Function *
F = FPtr ? *FPtr :
nullptr;
1136 if (
const auto **L = any_cast<const Loop *>(&
IR))
1137 F = (*L)->getHeader()->getParent();
1142 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1147 const Module **MPtr = any_cast<const Module *>(&
IR);
1148 const Module *M = MPtr ? *MPtr :
nullptr;
1150 if (
const auto **
C = any_cast<const LazyCallGraph::SCC *>(&
IR))
1151 M = (*C)->begin()->getFunction().getParent();
1156 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1178 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1182 [&](
bool InModule,
unsigned Minor,
1185 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1186 Minor, Before, After);
1197 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1204 const std::string Removed =
1205 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1206 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1207 const std::string NoChange =
" %l\n";
1208 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1230 this->runAfterPass();
1242void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1251class DotCfgDiffDisplayGraph;
1254class DisplayElement {
1257 StringRef getColour()
const {
return Colour; }
1260 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1266class DisplayEdge :
public DisplayElement {
1271 std::string getValue()
const {
return Value; }
1273 const DisplayNode &getDestinationNode()
const {
return Node; }
1277 const DisplayNode &
Node;
1281class DisplayNode :
public DisplayElement {
1289 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1290 ChildIterator children_begin()
const {
return Children.cbegin(); }
1291 ChildIterator children_end()
const {
return Children.cend(); }
1294 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1295 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1296 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1302 std::string getContent()
const {
return Content; }
1305 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1306 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1307 return *EdgeMap.find(&To)->second;
1312 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1313 return getEdge(Sink).getValue();
1316 void createEdgeMap();
1324 std::vector<DisplayEdge> Edges;
1326 std::vector<DisplayEdge *> EdgePtrs;
1327 std::unordered_set<DisplayNode *>
Children;
1328 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1331 bool AllEdgesCreated =
false;
1335class DotCfgDiffDisplayGraph {
1337 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1340 void generateDotFile(
StringRef DotFile);
1343 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1344 NodeIterator nodes_begin()
const {
1345 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1346 return NodePtrs.cbegin();
1348 NodeIterator nodes_end()
const {
1349 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1350 return NodePtrs.cend();
1355 void setEntryNode(
unsigned N) {
1357 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1358 NodeGenerationComplete =
true;
1359 for (
auto &
N : Nodes)
1360 NodePtrs.emplace_back(&
N);
1362 EntryNode = NodePtrs[
N];
1366 void createNode(std::string
C,
StringRef Colour) {
1367 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1368 Nodes.emplace_back(
C, Colour);
1371 DisplayNode &getNode(
unsigned N) {
1372 assert(
N < Nodes.size() &&
"Node is out of bounds");
1375 unsigned size()
const {
1376 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1377 return Nodes.size();
1381 std::string getGraphName()
const {
return GraphName; }
1386 return Node.getContent();
1390 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1391 return attribute(
Node.getColour());
1395 std::string getEdgeColorAttr(
const DisplayNode &
From,
1396 const DisplayNode &To)
const {
1397 return attribute(
From.getEdge(To).getColour());
1401 DisplayNode *getEntryNode()
const {
1402 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1408 std::string attribute(
StringRef Colour)
const {
1409 return "color=" + Colour.
str();
1412 bool NodeGenerationComplete =
false;
1413 const std::string GraphName;
1414 std::vector<DisplayNode> Nodes;
1415 std::vector<DisplayNode *> NodePtrs;
1416 DisplayNode *EntryNode =
nullptr;
1421 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1422 Edges.emplace_back(
Value.str(),
Node, Colour);
1426void DisplayNode::createEdgeMap() {
1429 AllEdgesCreated =
true;
1430 for (
auto &
E : Edges)
1431 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1434class DotCfgDiffNode;
1438class DotCfgDiffNode {
1440 DotCfgDiffNode() =
delete;
1446 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1447 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1452 unsigned getIndex()
const {
return N; }
1456 assert(
Data[0] &&
"Expected Data[0] to be set.");
1457 return Data[0]->getLabel();
1460 StringRef getColour()
const {
return Colour; }
1464 assert(!
Data[1] &&
"Expected only one block datum");
1472 "Unexpected edge count and color.");
1473 EdgesMap[
E] = {
Value.str(), Colour};
1479 StringRef getEdgeColour(
const unsigned S)
const {
1480 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1481 return EdgesMap.at(S).second;
1485 std::string getBodyContent()
const;
1487 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1488 std::map<const unsigned, unsigned> &NodeMap)
const;
1495 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1497 std::vector<unsigned> Edges;
1510 DotCfgDiff(
const DotCfgDiff &) =
delete;
1511 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1513 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1520 StringRef getEdgeSourceLabel(
const unsigned &Source,
1521 const unsigned &Sink)
const {
1523 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1524 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1525 return EdgeLabels.find(S)->getValue();
1529 unsigned size()
const {
return Nodes.size(); }
1531 const DotCfgDiffNode &getNode(
unsigned N)
const {
1532 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1538 std::string colourize(std::string S,
StringRef Colour)
const;
1541 unsigned Pos = Nodes.size();
1542 Nodes.emplace_back(*
this, Pos, BD,
C);
1543 NodePosition.insert({
Label, Pos});
1549 std::vector<DotCfgDiffNode> Nodes;
1551 const std::string GraphName;
1556std::string DotCfgDiffNode::getBodyContent()
const {
1558 assert(
Data[1] &&
"Expected Data[1] to be set.");
1561 for (
unsigned I = 0;
I < 2; ++
I) {
1562 SR[
I] =
Data[
I]->getBody();
1564 if (SR[
I][0] ==
'\n')
1567 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1571 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1573 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1575 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1576 std::string Diff =
Data[0]->getLabel().str();
1577 Diff +=
":\n<BR align=\"left\"/>" +
1578 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1579 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1584 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1587 std::string S =
R.sub(
"", Diff, &
Error);
1598 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1599 std::string Body = makeHTMLReady(
Data[0]->getBody());
1603 if (BS.
front() ==
'\n')
1608 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1610 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1613 while (BS1.
size()) {
1614 S.append(
"<BR align=\"left\"/>");
1616 S.append(
Line.str());
1619 S.append(
"<BR align=\"left\"/></FONT>");
1623std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1624 if (S.length() == 0)
1626 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1631 : GraphName(Title.str()) {
1644 Sink !=
E; ++Sink) {
1645 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1646 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1655 unsigned C = NodePosition.count(Label);
1660 assert(
C == 1 &&
"Unexpected multiple nodes.");
1661 Nodes[NodePosition[
Label]].setCommon(BD);
1666 Sink !=
E; ++Sink) {
1667 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1668 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1669 unsigned C = EdgesMap.
count(Key);
1679 for (
auto &
E : EdgesMap) {
1682 auto SP1 = S.
rsplit(
' ');
1683 auto &SourceSink = SP1.first;
1684 auto SP2 = SourceSink.split(
' ');
1689 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
1690 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
1691 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
1692 unsigned SinkNode = NodePosition[
Sink];
1696 if (EdgeLabels.count(SourceSink) == 0)
1697 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
1700 std::string
NV = colourize(V.
str() +
" " +
Value.str(), Colour);
1702 EdgeLabels[SourceSink] =
NV;
1704 SourceNode.addEdge(SinkNode,
Value, Colour);
1706 for (
auto &
I : Nodes)
1710DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
1712 assert(NodePosition.count(EntryNodeName) == 1 &&
1713 "Expected to find entry block in map.");
1714 unsigned Entry = NodePosition[EntryNodeName];
1715 assert(Entry < Nodes.size() &&
"Expected to find entry node");
1716 DotCfgDiffDisplayGraph
G(Title.
str());
1718 std::map<const unsigned, unsigned> NodeMap;
1720 int EntryIndex = -1;
1722 for (
auto &
I : Nodes) {
1723 if (
I.getIndex() == Entry)
1725 G.createNode(
I.getBodyContent(),
I.getColour());
1726 NodeMap.insert({
I.getIndex(),
Index++});
1728 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
1729 G.setEntryNode(EntryIndex);
1731 for (
auto &
I : NodeMap) {
1732 unsigned SourceNode =
I.first;
1733 unsigned DisplayNode =
I.second;
1734 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
1739void DotCfgDiffNode::createDisplayEdges(
1740 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
1741 std::map<const unsigned, unsigned> &NodeMap)
const {
1743 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
1745 for (
auto I : Edges) {
1746 unsigned SinkNodeIndex =
I;
1747 StringRef Colour = getEdgeColour(SinkNodeIndex);
1748 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
1750 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
1751 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
1752 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
1754 SourceDisplayNode.createEdgeMap();
1757void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
1758 for (
auto E : EdgesMap) {
1760 Edges.emplace_back(
E.first);
1776 return G->getEntryNode();
1779 return N->children_begin();
1783 return G->nodes_begin();
1786 return G->nodes_end();
1789 return N->edges_begin();
1793 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
1803 return DiffData->getGraphName();
1807 return "\tsize=\"190, 190\";\n";
1810 const DotCfgDiffDisplayGraph *DiffData) {
1811 return DiffData->getNodeLabel(*Node);
1814 const DotCfgDiffDisplayGraph *DiffData) {
1815 return DiffData->getNodeAttributes(*Node);
1818 DisplayNode::ChildIterator &To) {
1819 return From->getEdgeSourceLabel(**To);
1822 DisplayNode::ChildIterator &To,
1823 const DotCfgDiffDisplayGraph *DiffData) {
1824 return DiffData->getEdgeColorAttr(*
From, **To);
1832void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
1836 errs() <<
"Error: " <<
EC.message() <<
"\n";
1851 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
1852 if (Br->isUnconditional())
1858 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
1861 for (
auto &
C : Sw->cases()) {
1862 assert(
C.getCaseValue() &&
"Expected to find case value.");
1878 assert(
HTML &&
"Expected outstream to be set");
1883 Extender =
formatv(
"{0}_{1}",
N, Minor);
1892 std::string DotFile =
Twine(SV).
str();
1897 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
1900 DotCfgDiff Diff(Text, Before, After);
1903 if (EntryBlockName ==
"")
1905 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
1907 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
1908 DG.generateDotFile(DotFile);
1913 errs() <<
"Error: " << EC.message() <<
"\n";
1922 return "Unable to find dot executable.";
1927 return "Error executing system dot.";
1931 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
1936 assert(
HTML &&
"Expected outstream to be set");
1937 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
1938 <<
"Initial IR (by function)</button>\n"
1939 <<
"<div class=\"content\">\n"
1948 [&](
bool InModule,
unsigned Minor,
1952 Minor, Before, After);
1965 assert(
HTML &&
"Expected outstream to be set");
1967 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
1968 N, makeHTMLReady(PassID),
Name);
1976 assert(
HTML &&
"Expected outstream to be set");
1979 [&](
bool InModule,
unsigned Minor,
1983 Minor, Before, After);
1985 *
HTML <<
" </p></div>\n";
1990 assert(
HTML &&
"Expected outstream to be set");
1992 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
1998 assert(
HTML &&
"Expected outstream to be set");
2000 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2001 makeHTMLReady(PassID),
Name);
2007 assert(
HTML &&
"Expected outstream to be set");
2009 makeHTMLReady(PassID),
Name);
2016 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2022 *
HTML <<
"<!doctype html>"
2025 <<
"<style>.collapsible { "
2026 <<
"background-color: #777;"
2028 <<
" cursor: pointer;"
2029 <<
" padding: 18px;"
2032 <<
" text-align: left;"
2033 <<
" outline: none;"
2034 <<
" font-size: 15px;"
2035 <<
"} .active, .collapsible:hover {"
2036 <<
" background-color: #555;"
2038 <<
" padding: 0 18px;"
2039 <<
" display: none;"
2040 <<
" overflow: hidden;"
2041 <<
" background-color: #f1f1f1;"
2044 <<
"<title>passes.html</title>"
2054 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2056 <<
"for (i = 0; i < coll.length; i++) {"
2057 <<
"coll[i].addEventListener(\"click\", function() {"
2058 <<
" this.classList.toggle(\"active\");"
2059 <<
" var content = this.nextElementSibling;"
2060 <<
" if (content.style.display === \"block\"){"
2061 <<
" content.style.display = \"none\";"
2064 <<
" content.style.display= \"block\";"
2082 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2088 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2095 : PrintPass(DebugLogging, PrintPassOpts),
2096 OptNone(DebugLogging),
2111void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2126 CrashReporter =
nullptr;
2135 CrashReporter =
this;
2141 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2144 OS <<
" Filtered Out ***\n";
2147 OS <<
" Started ***\n";
2148 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
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< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
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)
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.
BlockT * getHeader() const
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.
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager &FAM)
static cl::opt< bool > VerifyPreservedCFG
~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)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM=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...
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
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.
std::string & str()
Returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
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)
Wrapper function around std::find to detect if an element exists in a container.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
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.
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.