Go to the documentation of this file.
40 #include <unordered_map>
41 #include <unordered_set>
101 "Display patch-like changes"),
103 "Display patch-like changes in quiet mode"),
105 "Display patch-like changes with color"),
107 "Display patch-like changes in quiet mode with color"),
109 "Create a website with graphical changes"),
111 "Create a website with graphical changes in quiet mode"),
120 cl::desc(
"Only consider IR changes for passes whose names "
121 "match for the print-changed option"),
128 cl::desc(
"Print before passes that change them"),
134 cl::desc(
"system diff used by change reporters"));
140 cl::desc(
"system dot used by change reporters"));
153 cl::desc(
"Color for dot-cfg after elements."),
167 cl::desc(
"Generate dot files into specified directory for changed IRs"),
173 cl::desc(
"Print the last form of the IR before crash"),
188 const unsigned NumFiles = 3;
189 static std::string FileName[NumFiles];
190 static int FD[NumFiles]{-1, -1, -1};
191 for (
unsigned I = 0;
I < NumFiles; ++
I) {
197 return "Unable to create temporary file.";
201 if (
I == NumFiles - 1)
206 return "Unable to open temporary file for writing.";
210 return "Error opening file for writing.";
216 return "Unable to find diff executable.";
221 formatv(
"--unchanged-line-format={0}", UnchangedLineFormat);
224 NLF, ULF, FileName[0], FileName[1]};
228 return "Error executing system diff.";
232 Diff = (*B)->getBuffer().str();
234 return "Unable to read result.";
237 for (
const std::string &
I : FileName) {
240 return "Unable to remove temporary file.";
247 const Module *unwrapModule(
Any IR,
bool Force =
false) {
248 if (any_isa<const Module *>(
IR))
249 return any_cast<const Module *>(
IR);
251 if (any_isa<const Function *>(
IR)) {
252 const Function *
F = any_cast<const Function *>(
IR);
256 return F->getParent();
259 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
264 return F.getParent();
267 assert(!Force &&
"Expected a module");
271 if (any_isa<const Loop *>(
IR)) {
272 const Loop *L = any_cast<const Loop *>(
IR);
276 return F->getParent();
290 M->print(OS,
nullptr);
292 for (
const auto &
F :
M->functions()) {
314 std::string getIRName(
Any IR) {
315 if (any_isa<const Module *>(
IR))
318 if (any_isa<const Function *>(
IR)) {
319 const Function *
F = any_cast<const Function *>(
IR);
320 return F->getName().str();
323 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
328 if (any_isa<const Loop *>(
IR)) {
329 const Loop *L = any_cast<const Loop *>(
IR);
332 L->
print(OS,
false,
false);
339 bool moduleContainsFilterPrintFunc(
const Module &M) {
342 return isFunctionInPrintList(F.getName());
355 bool shouldPrintIR(
Any IR) {
356 if (any_isa<const Module *>(
IR)) {
357 const Module *
M = any_cast<const Module *>(
IR);
358 return moduleContainsFilterPrintFunc(*M);
361 if (any_isa<const Function *>(
IR)) {
362 const Function *
F = any_cast<const Function *>(
IR);
366 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
368 return sccContainsFilterPrintFunc(*
C);
371 if (any_isa<const Loop *>(
IR)) {
372 const Loop *L = any_cast<const Loop *>(
IR);
381 if (!shouldPrintIR(
IR))
385 auto *
M = unwrapModule(
IR);
386 assert(M &&
"should have unwrapped module");
391 if (any_isa<const Module *>(
IR)) {
392 const Module *
M = any_cast<const Module *>(
IR);
397 if (any_isa<const Function *>(
IR)) {
398 const Function *
F = any_cast<const Function *>(
IR);
403 if (any_isa<const LazyCallGraph::SCC *>(
IR)) {
409 if (any_isa<const Loop *>(
IR)) {
410 const Loop *L = any_cast<const Loop *>(
IR);
420 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
421 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass"});
424 std::string makeHTMLReady(
StringRef SR) {
429 S.append(Clean.
str());
433 S.append(SR[0] ==
'<' ?
"<" :
">");
441 if (any_isa<const Module *>(
IR))
442 return any_cast<const Module *>(
IR);
443 if (any_isa<const LazyCallGraph::SCC *>(
IR))
444 return any_cast<const LazyCallGraph::SCC *>(
IR)
451 bool isInterestingFunction(
const Function &
F) {
455 bool isInterestingPass(
StringRef PassID) {
456 if (isIgnored(PassID))
459 static std::unordered_set<std::string> PrintPassNames(
PrintPassesList.begin(),
461 return PrintPassNames.empty() || PrintPassNames.count(PassID.
str());
467 if (!isInterestingPass(PassID))
469 if (any_isa<const Function *>(
IR))
470 return isInterestingFunction(*any_cast<const Function *>(
IR));
477 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
480 template <
typename T>
485 BeforeStack.emplace_back();
497 T &
Data = BeforeStack.back();
498 generateIRRepresentation(
IR, PassID,
Data);
501 template <
typename T>
503 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
505 std::string
Name = getIRName(
IR);
507 if (isIgnored(PassID)) {
509 handleIgnored(PassID,
Name);
512 handleFiltered(PassID,
Name);
515 T &Before = BeforeStack.
back();
518 generateIRRepresentation(
IR, PassID, After);
521 if (Before == After) {
523 omitAfter(PassID,
Name);
525 handleAfter(PassID,
Name, Before, After,
IR);
527 BeforeStack.pop_back();
530 template <
typename T>
532 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
539 handleInvalidated(PassID);
540 BeforeStack.pop_back();
543 template <
typename T>
551 handleIRAfterPass(
IR,
P);
555 handleInvalidatedPass(
P);
559 template <
typename T>
566 auto *
M = unwrapModule(
IR,
true);
567 assert(
M &&
"Expected module to be unwrapped when forced.");
568 Out <<
"*** IR Dump At Start ***\n";
569 M->print(Out,
nullptr);
572 template <
typename T>
574 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
578 template <
typename T>
580 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
583 template <
typename T>
587 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
591 template <
typename T>
593 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
596 IRChangedPrinter::~IRChangedPrinter() =
default;
605 std::string &Output) {
607 unwrapAndPrint(OS,
IR);
612 const std::string &Before,
613 const std::string &After,
Any) {
616 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
622 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
626 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" << After;
629 template <
typename T>
633 const auto &BFD = Before.
getData();
634 const auto &AFD = After.
getData();
635 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
636 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
637 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
638 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
640 auto HandlePotentiallyRemovedData = [&](std::string
S) {
644 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
647 auto HandleNewData = [&](std::vector<const T *> &Q) {
649 for (
const T *NBI : Q)
650 HandlePair(
nullptr, NBI);
663 std::vector<const T *> NewDataQueue;
665 if (!BFD.count(*AI)) {
668 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
675 HandlePotentiallyRemovedData(*BI);
679 HandleNewData(NewDataQueue);
681 const T &AData = AFD.find(*AI)->getValue();
682 const T &BData = BFD.find(*AI)->getValue();
683 HandlePair(&BData, &AData);
690 HandlePotentiallyRemovedData(*BI);
694 HandleNewData(NewDataQueue);
697 template <
typename T>
703 if (!CompareModule) {
706 "Expected only one function.");
707 CompareFunc(
false, 0, Before.
getData().
begin()->getValue(),
716 assert((
B || A) &&
"Both functions cannot be missing.");
721 CompareFunc(
true, Minor++, *
B, *A);
726 if (
const Module *
M = getModuleForComparison(
IR)) {
729 generateFunctionData(
Data,
F);
734 if (any_isa<const Function *>(
IR))
735 F = any_cast<const Function *>(
IR);
737 assert(any_isa<const Loop *>(
IR) &&
"Unknown IR unit.");
738 const Loop *L = any_cast<const Loop *>(
IR);
741 assert(
F &&
"Unknown IR unit.");
742 generateFunctionData(
Data, *
F);
745 template <
typename T>
749 for (
const auto &
B :
F) {
753 Data.getOrder().emplace_back(
F.getName());
754 Data.getData().insert({
F.getName(), FD});
761 assert(ModuleDescStack.empty() &&
"ModuleDescStack is not empty at exit");
764 void PrintIRInstrumentation::pushModuleDesc(
StringRef PassID,
Any IR) {
769 PrintIRInstrumentation::PrintModuleDesc
770 PrintIRInstrumentation::popModuleDesc(
StringRef PassID) {
771 assert(!ModuleDescStack.empty() &&
"empty ModuleDescStack");
772 PrintModuleDesc ModuleDesc = ModuleDescStack.
pop_back_val();
773 assert(std::get<2>(ModuleDesc).equals(PassID) &&
"malformed ModuleDescStack");
777 void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
778 if (isIgnored(PassID))
785 if (shouldPrintAfterPass(PassID))
786 pushModuleDesc(PassID,
IR);
788 if (!shouldPrintBeforePass(PassID))
791 if (!shouldPrintIR(
IR))
794 dbgs() <<
"*** IR Dump Before " << PassID <<
" on " << getIRName(
IR)
796 unwrapAndPrint(
dbgs(),
IR);
799 void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
800 if (isIgnored(PassID))
803 if (!shouldPrintAfterPass(PassID))
809 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
810 assert(StoredPassID == PassID &&
"mismatched PassID");
812 if (!shouldPrintIR(
IR))
815 dbgs() <<
"*** IR Dump After " << PassID <<
" on " << IRName <<
" ***\n";
816 unwrapAndPrint(
dbgs(),
IR);
819 void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
821 if (!shouldPrintAfterPass(
PassName))
824 if (isIgnored(PassID))
830 std::tie(M, IRName, StoredPassID) = popModuleDesc(PassID);
831 assert(StoredPassID == PassID &&
"mismatched PassID");
838 formatv(
"*** IR Dump After {0} on {1} (invalidated) ***", PassID, IRName);
839 dbgs() << Banner <<
"\n";
843 bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
851 bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
872 this->printAfterPass(
P,
IR);
876 this->printAfterPassInvalidated(
P);
887 bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
889 if (any_isa<const Function *>(
IR)) {
890 F = any_cast<const Function *>(
IR);
891 }
else if (any_isa<const Loop *>(
IR)) {
892 F = any_cast<const Loop *>(
IR)->getHeader()->getParent();
894 bool ShouldRun = !(
F &&
F->hasOptNone());
895 if (!ShouldRun && DebugLogging) {
896 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
897 <<
" due to optnone attribute\n";
907 return isIgnored(PassID) ||
OptBisector->checkPass(PassID, getIRName(
IR));
924 std::vector<StringRef> SpecialPasses;
926 SpecialPasses.emplace_back(
"PassManager");
927 SpecialPasses.emplace_back(
"PassAdaptor");
933 "Unexpectedly skipping special pass");
935 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
942 print() <<
"Running pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
963 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
970 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
974 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
980 bool TrackBBLifetime) {
983 for (
const auto &
BB : *
F) {
996 out <<
BB->getName() <<
"<" <<
BB <<
">";
1000 if (!
BB->getParent()) {
1001 out <<
"unnamed_removed<" <<
BB <<
">";
1005 if (
BB->isEntryBlock()) {
1007 <<
"<" <<
BB <<
">";
1011 unsigned FuncOrderBlockNum = 0;
1012 for (
auto &FuncBB : *
BB->getParent()) {
1015 FuncOrderBlockNum++;
1017 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" <<
BB <<
">";
1025 out <<
"Some blocks were deleted\n";
1030 if (Before.
Graph.size() != After.
Graph.size())
1031 out <<
"Different number of non-leaf basic blocks: before="
1032 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1034 for (
auto &
BB : Before.
Graph) {
1035 auto BA = After.
Graph.find(
BB.first);
1036 if (BA == After.
Graph.end()) {
1037 out <<
"Non-leaf block ";
1039 out <<
" is removed (" <<
BB.second.size() <<
" successors)\n";
1043 for (
auto &BA : After.
Graph) {
1044 auto BB = Before.
Graph.find(BA.first);
1045 if (
BB == Before.
Graph.end()) {
1046 out <<
"Non-leaf block ";
1048 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1052 if (
BB->second == BA.second)
1055 out <<
"Different successors of block ";
1057 out <<
" (unordered):\n";
1058 out <<
"- before (" <<
BB->second.size() <<
"): ";
1059 for (
auto &SuccB :
BB->second) {
1061 if (SuccB.second != 1)
1062 out <<
"(" << SuccB.second <<
"), ";
1067 out <<
"- after (" << BA.second.size() <<
"): ";
1068 for (
auto &SuccA : BA.second) {
1070 if (SuccA.second != 1)
1071 out <<
"(" << SuccA.second <<
"), ";
1122 const CFG &GraphAfter) {
1123 if (GraphAfter == GraphBefore)
1127 <<
" does not invalidate CFG analyses but CFG changes detected in "
1129 << FuncName <<
":\n";
1135 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1136 assert(&PassStack.emplace_back(
P));
1139 if (!any_isa<const Function *>(
IR))
1142 const auto *
F = any_cast<const Function *>(
IR);
1149 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1150 assert(PassStack.pop_back_val() ==
P &&
1151 "Before and After callbacks must correspond");
1159 #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1160 assert(PassStack.pop_back_val() ==
P &&
1161 "Before and After callbacks must correspond");
1165 if (!any_isa<const Function *>(
IR))
1172 const auto *
F = any_cast<const Function *>(
IR);
1175 checkCFG(
P,
F->getName(), *GraphBefore,
1184 if (isIgnored(
P) ||
P ==
"VerifierPass")
1186 if (any_isa<const Function *>(
IR) || any_isa<const Loop *>(
IR)) {
1188 if (any_isa<const Loop *>(
IR))
1189 F = any_cast<const Loop *>(
IR)->getHeader()->
getParent();
1191 F = any_cast<const Function *>(
IR);
1193 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1197 }
else if (any_isa<const Module *>(
IR) ||
1198 any_isa<const LazyCallGraph::SCC *>(
IR)) {
1200 if (any_isa<const LazyCallGraph::SCC *>(
IR))
1201 M = any_cast<const LazyCallGraph::SCC *>(
IR)
1206 M = any_cast<const Module *>(
IR);
1208 dbgs() <<
"Verifying module " <<
M->getName() <<
"\n";
1227 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1231 [&](
bool InModule,
unsigned Minor,
1234 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1235 Minor, Before, After);
1246 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1252 StringRef AStr = A ? A->getBody() :
"\n";
1253 const std::string Removed =
1254 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1255 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1256 const std::string NoChange =
" %l\n";
1257 Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1272 class DotCfgDiffDisplayGraph;
1275 class DisplayElement {
1278 StringRef getColour()
const {
return Colour; }
1281 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1287 class DisplayEdge :
public DisplayElement {
1289 DisplayEdge(std::string
Value, DisplayNode &Node,
StringRef Colour)
1290 : DisplayElement(Colour),
Value(
Value), Node(Node) {}
1292 std::string getValue()
const {
return Value; }
1294 const DisplayNode &getDestinationNode()
const {
return Node; }
1298 const DisplayNode &Node;
1302 class DisplayNode :
public DisplayElement {
1310 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1311 ChildIterator children_begin()
const {
return Children.cbegin(); }
1312 ChildIterator children_end()
const {
return Children.cend(); }
1315 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1316 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1317 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1323 std::string getContent()
const {
return Content; }
1326 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1327 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1328 return *EdgeMap.find(&To)->second;
1333 std::string getEdgeSourceLabel(
const DisplayNode &
Sink)
const {
1334 return getEdge(
Sink).getValue();
1337 void createEdgeMap();
1345 std::vector<DisplayEdge> Edges;
1347 std::vector<DisplayEdge *> EdgePtrs;
1348 std::unordered_set<DisplayNode *> Children;
1349 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1352 bool AllEdgesCreated =
false;
1356 class DotCfgDiffDisplayGraph {
1358 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1361 void generateDotFile(
StringRef DotFile);
1364 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1365 NodeIterator nodes_begin()
const {
1366 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1367 return NodePtrs.cbegin();
1369 NodeIterator nodes_end()
const {
1370 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1371 return NodePtrs.cend();
1376 void setEntryNode(
unsigned N) {
1378 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1379 NodeGenerationComplete =
true;
1380 for (
auto &
N : Nodes)
1381 NodePtrs.emplace_back(&
N);
1383 EntryNode = NodePtrs[
N];
1387 void createNode(std::string
C,
StringRef Colour) {
1388 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1389 Nodes.emplace_back(
C, Colour);
1392 DisplayNode &getNode(
unsigned N) {
1393 assert(
N < Nodes.size() &&
"Node is out of bounds");
1396 unsigned size()
const {
1397 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1398 return Nodes.size();
1402 std::string getGraphName()
const {
return GraphName; }
1406 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1407 return Node.getContent();
1411 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1412 return attribute(Node.getColour());
1416 std::string getEdgeColorAttr(
const DisplayNode &
From,
1417 const DisplayNode &To)
const {
1418 return attribute(
From.getEdge(To).getColour());
1422 DisplayNode *getEntryNode()
const {
1423 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1429 std::string attribute(
StringRef Colour)
const {
1430 return "color=" + Colour.
str();
1433 bool NodeGenerationComplete =
false;
1434 const std::string GraphName;
1435 std::vector<DisplayNode> Nodes;
1436 std::vector<DisplayNode *> NodePtrs;
1437 DisplayNode *EntryNode =
nullptr;
1442 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1443 Edges.emplace_back(
Value.str(), Node, Colour);
1444 Children.insert(&Node);
1447 void DisplayNode::createEdgeMap() {
1450 AllEdgesCreated =
true;
1451 for (
auto &
E : Edges)
1452 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1455 class DotCfgDiffNode;
1459 class DotCfgDiffNode {
1461 DotCfgDiffNode() =
delete;
1467 : Graph(
G),
N(
N),
Data{&BD,
nullptr}, Colour(Colour) {}
1468 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1469 : Graph(DN.Graph),
N(DN.
N),
Data{DN.Data[0], DN.Data[1]},
1470 Colour(DN.Colour), EdgesMap(DN.EdgesMap), Children(DN.Children),
1473 unsigned getIndex()
const {
return N; }
1477 assert(
Data[0] &&
"Expected Data[0] to be set.");
1478 return Data[0]->getLabel();
1481 StringRef getColour()
const {
return Colour; }
1485 assert(!
Data[1] &&
"Expected only one block datum");
1493 "Unexpected edge count and color.");
1494 EdgesMap[
E] = {
Value.str(), Colour};
1500 StringRef getEdgeColour(
const unsigned S)
const {
1501 assert(EdgesMap.count(
S) == 1 &&
"Expected to find edge.");
1502 return EdgesMap.at(
S).second;
1506 std::string getBodyContent()
const;
1508 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1509 std::map<const unsigned, unsigned> &NodeMap)
const;
1516 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1517 std::vector<unsigned> Children;
1518 std::vector<unsigned> Edges;
1531 DotCfgDiff(
const DotCfgDiff &) =
delete;
1532 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1534 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1542 const unsigned &
Sink)
const {
1544 getNode(
Source).getLabel().str() +
" " + getNode(
Sink).getLabel().str();
1545 assert(EdgeLabels.count(
S) == 1 &&
"Expected to find edge label.");
1546 return EdgeLabels.find(
S)->getValue();
1550 unsigned size()
const {
return Nodes.size(); }
1552 const DotCfgDiffNode &getNode(
unsigned N)
const {
1553 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1559 std::string colourize(std::string
S,
StringRef Colour)
const;
1562 unsigned Pos = Nodes.size();
1563 Nodes.emplace_back(*
this, Pos, BD,
C);
1564 NodePosition.insert({
Label, Pos});
1570 std::vector<DotCfgDiffNode> Nodes;
1572 const std::string GraphName;
1577 std::string DotCfgDiffNode::getBodyContent()
const {
1579 assert(
Data[1] &&
"Expected Data[1] to be set.");
1582 for (
unsigned I = 0;
I < 2; ++
I) {
1583 SR[
I] =
Data[
I]->getBody();
1585 if (SR[
I][0] ==
'\n')
1588 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1592 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1594 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1596 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1597 std::string Diff =
Data[0]->getLabel().str();
1598 Diff +=
":\n<BR align=\"left\"/>" +
1599 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1600 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1605 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1608 std::string
S =
R.sub(
"", Diff, &
Error);
1619 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1620 std::string Body = makeHTMLReady(
Data[0]->getBody());
1624 if (BS.
front() ==
'\n')
1629 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1631 std::string
S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1634 while (BS1.
size()) {
1635 S.append(
"<BR align=\"left\"/>");
1637 S.append(Line.
str());
1640 S.append(
"<BR align=\"left\"/></FONT>");
1644 std::string DotCfgDiff::colourize(std::string
S,
StringRef Colour)
const {
1645 if (
S.length() == 0)
1647 return "<FONT COLOR=\"" + Colour.
str() +
"\">" +
S +
"</FONT>";
1652 : GraphName(Title.str()) {
1666 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1673 for (
auto &A : After.
getData()) {
1676 unsigned C = NodePosition.count(Label);
1681 assert(
C == 1 &&
"Unexpected multiple nodes.");
1682 Nodes[NodePosition[
Label]].setCommon(BD);
1688 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1700 for (
auto &
E : EdgesMap) {
1703 auto SP1 =
S.rsplit(
' ');
1704 auto &SourceSink = SP1.first;
1705 auto SP2 = SourceSink.split(
' ');
1710 assert(NodePosition.count(
Source) == 1 &&
"Expected to find node.");
1711 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
1712 assert(NodePosition.count(
Sink) == 1 &&
"Expected to find node.");
1713 unsigned SinkNode = NodePosition[
Sink];
1717 if (EdgeLabels.count(SourceSink) == 0)
1718 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
1721 std::string
NV = colourize(V.
str() +
" " +
Value.str(), Colour);
1723 EdgeLabels[SourceSink] =
NV;
1725 SourceNode.addEdge(SinkNode,
Value, Colour);
1727 for (
auto &
I : Nodes)
1731 DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
1733 assert(NodePosition.count(EntryNodeName) == 1 &&
1734 "Expected to find entry block in map.");
1735 unsigned Entry = NodePosition[EntryNodeName];
1736 assert(Entry < Nodes.size() &&
"Expected to find entry node");
1737 DotCfgDiffDisplayGraph
G(Title.
str());
1739 std::map<const unsigned, unsigned> NodeMap;
1741 int EntryIndex = -1;
1743 for (
auto &
I : Nodes) {
1744 if (
I.getIndex() == Entry)
1746 G.createNode(
I.getBodyContent(),
I.getColour());
1747 NodeMap.insert({
I.getIndex(),
Index++});
1749 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
1750 G.setEntryNode(EntryIndex);
1752 for (
auto &
I : NodeMap) {
1753 unsigned SourceNode =
I.first;
1754 unsigned DisplayNode =
I.second;
1755 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
1760 void DotCfgDiffNode::createDisplayEdges(
1761 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
1762 std::map<const unsigned, unsigned> &NodeMap)
const {
1764 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
1766 for (
auto I : Edges) {
1767 unsigned SinkNodeIndex =
I;
1768 StringRef Colour = getEdgeColour(SinkNodeIndex);
1769 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
1771 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
1772 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
1773 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
1775 SourceDisplayNode.createEdgeMap();
1779 for (
auto E : EdgesMap) {
1780 Children.emplace_back(
E.first);
1781 Edges.emplace_back(
E.first);
1797 return G->getEntryNode();
1800 return N->children_begin();
1804 return G->nodes_begin();
1807 return G->nodes_end();
1810 return N->edges_begin();
1814 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
1824 return DiffData->getGraphName();
1828 return "\tsize=\"190, 190\";\n";
1831 const DotCfgDiffDisplayGraph *DiffData) {
1832 return DiffData->getNodeLabel(*Node);
1835 const DotCfgDiffDisplayGraph *DiffData) {
1836 return DiffData->getNodeAttributes(*Node);
1839 DisplayNode::ChildIterator &To) {
1840 return From->getEdgeSourceLabel(**To);
1843 DisplayNode::ChildIterator &To,
1844 const DotCfgDiffDisplayGraph *DiffData) {
1845 return DiffData->getEdgeColorAttr(*
From, **To);
1853 void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
1857 errs() <<
"Error: " <<
EC.message() <<
"\n";
1873 if (Br->isUnconditional())
1879 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(
Term)) {
1882 for (
auto &
C : Sw->cases()) {
1883 assert(
C.getCaseValue() &&
"Expected to find case value.");
1899 assert(
HTML &&
"Expected outstream to be set");
1904 Extender =
formatv(
"{0}_{1}",
N, Minor);
1913 std::string DotFile =
Twine(SV).
str();
1921 DotCfgDiff Diff(Text, Before, After);
1924 if (EntryBlockName ==
"")
1926 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
1928 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
1929 DG.generateDotFile(DotFile);
1934 errs() <<
"Error: " << EC.message() <<
"\n";
1943 return "Unable to find dot executable.";
1948 return "Error executing system dot.";
1952 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
1957 assert(
HTML &&
"Expected outstream to be set");
1958 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
1959 <<
"Initial IR (by function)</button>\n"
1960 <<
"<div class=\"content\">\n"
1969 [&](
bool InModule,
unsigned Minor,
1973 Minor, Before, After);
1986 assert(
HTML &&
"Expected outstream to be set");
1988 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
1989 N, makeHTMLReady(PassID),
Name);
1997 assert(
HTML &&
"Expected outstream to be set");
2000 [&](
bool InModule,
unsigned Minor,
2004 Minor, Before, After);
2006 *
HTML <<
" </p></div>\n";
2011 assert(
HTML &&
"Expected outstream to be set");
2013 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2019 assert(
HTML &&
"Expected outstream to be set");
2021 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2022 makeHTMLReady(PassID),
Name);
2028 assert(
HTML &&
"Expected outstream to be set");
2030 makeHTMLReady(PassID),
Name);
2037 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2043 *
HTML <<
"<!doctype html>"
2046 <<
"<style>.collapsible { "
2047 <<
"background-color: #777;"
2049 <<
" cursor: pointer;"
2050 <<
" padding: 18px;"
2053 <<
" text-align: left;"
2054 <<
" outline: none;"
2055 <<
" font-size: 15px;"
2056 <<
"} .active, .collapsible:hover {"
2057 <<
" background-color: #555;"
2059 <<
" padding: 0 18px;"
2060 <<
" display: none;"
2061 <<
" overflow: hidden;"
2062 <<
" background-color: #f1f1f1;"
2065 <<
"<title>passes.html</title>"
2075 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2077 <<
"for (i = 0; i < coll.length; i++) {"
2078 <<
"coll[i].addEventListener(\"click\", function() {"
2079 <<
" this.classList.toggle(\"active\");"
2080 <<
" var content = this.nextElementSibling;"
2081 <<
" if (content.style.display === \"block\"){"
2082 <<
" content.style.display = \"none\";"
2085 <<
" content.style.display= \"block\";"
2103 assert(!OutputDir.empty() &&
"expected output dir to be non-empty");
2109 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2115 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2131 void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2146 CrashReporter =
nullptr;
2155 CrashReporter =
this;
2160 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2163 OS <<
" Filtered Out ***\n";
2166 OS <<
" Started ***\n";
2167 unwrapAndPrint(OS,
IR);
static cl::opt< std::string > DiffBinary("print-changed-diff-path", cl::Hidden, cl::init("diff"), cl::desc("system diff used by change reporters"))
void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
const T & getData() const
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
~InLineChangePrinter() override
A set of analyses that are preserved following a run of a transformation pass.
LLVM_NODISCARD char back() const
back - Get the last character in the string.
static bool generateFunctionData(IRDataT< T > &Data, const Function &F)
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
This is an optimization pass for GlobalISel generic memory operations.
DisplayNode::EdgeIterator ChildEdgeIterator
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
print lazy value Lazy Value Info Printer Pass
~DotCfgChangeReporter() override
const Function * getParent() const
Return the enclosing method, or null if none.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
std::vector< std::string > & getOrder()
Interval::succ_iterator succ_end(Interval *I)
DotCfgDiffDisplayGraph::NodeIterator nodes_iterator
Represents a single loop in the control flow graph.
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
LLVM_NODISCARD 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...
A raw_ostream that writes to an std::string.
static cl::opt< std::string > DotCfgDir("dot-cfg-dir", cl::desc("Generate dot files into specified directory for changed IRs"), cl::Hidden, cl::init("./"))
TextChangeReporter(bool Verbose)
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
void registerBeforeNonSkippedPassCallback(CallableT C)
LLVM_NODISCARD size_t find(char C, size_t From=0) const
Search for the first character C in the string.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static ChildIteratorType child_begin(NodeRef N)
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< DCData > &Output) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< DCData > &Before, const FuncDataT< DCData > &After)
static cl::list< std::string > PrintPassesList("filter-passes", cl::value_desc("pass names"), cl::desc("Only consider IR changes for passes whose names " "match for the print-changed option"), cl::CommaSeparated, cl::Hidden)
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager *FAM=nullptr)
DotCfgChangeReporter(bool Verbose)
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
~PrintIRInstrumentation()
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)
StringMap< std::string >::const_iterator end() const
void registerCallbacks(PassInstrumentationCallbacks &PIC)
FunctionAnalysisManager FAM
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void omitAfter(StringRef PassID, std::string &Name) override
void registerAnalysesClearedCallback(CallableT C)
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
void handleInitialIR(Any IR) override
PassInstrumentationCallbacks PIC
DiagnosticInfoOptimizationBase::Argument NV
auto successors(MachineBasicBlock *BB)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
@ PrintChangedDotCfgQuiet
virtual void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< EmptyData > &Output) override
LLVM_NODISCARD T pop_back_val()
static void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
StandardInstrumentations(bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
void saveIRBeforePass(Any IR, StringRef PassID)
__FakeVCSRevision h endif() endif() set(generated_files "$
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
void registerCallbacks(PassInstrumentationCallbacks &PIC, FunctionAnalysisManager &FAM)
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
bool shouldPrintBeforeAll()
LLVM Basic Block Representation.
std::string getEntryBlockName() const
ppc ctr loops PowerPC CTR Loops Verify
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool shouldPrintAfterSomePass()
static nodes_iterator nodes_begin(const DotCfgDiffDisplayGraph *G)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
bool SkipAnalyses
Don't print information for analyses.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
cl::opt< std::string > BeforeColour("dot-cfg-before-color", cl::desc("Color for dot-cfg before elements."), cl::Hidden, cl::init("red"))
void registerCallbacks(PassInstrumentationCallbacks &PIC)
DCData(const BasicBlock &B)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
An SCC of the call graph.
static ChildEdgeIterator child_edge_begin(NodeRef N)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This class implements a mechanism to disable passes and individual optimizations at compile time base...
StringMap< T > & getData()
(vector float) vec_cmpeq(*A, *B) C
static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData)
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
static NodeRef getEntryNode(const DotCfgDiffDisplayGraph *G)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
static void report(const OrderedChangedData &Before, const OrderedChangedData &After, function_ref< void(const T *, const T *)> HandlePair)
StringRef getSuccessorLabel(StringRef S) const
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class implements an extremely fast bulk output stream that can only output to a stream.
LLVM_NODISCARD 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...
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements."), cl::Hidden, cl::init("black"))
Statically lint checks LLVM IR
API to communicate dependencies between analyses during invalidation.
void registerShouldRunOptionalPassCallback(CallableT C)
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
bool Indent
Indent based on hierarchy.
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, Any) override
void addSuccessorLabel(StringRef Succ, StringRef Label)
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
std::string str() const
Return the twine contents as a std::string.
void handleIgnored(StringRef PassID, std::string &Name) override
virtual ~ChangeReporter()
DOTGraphTraits(bool Simple=false)
@ PrintChangedColourDiffQuiet
void registerBeforeAnalysisCallback(CallableT C)
An efficient, type-erasing, non-owning reference to a callable.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
void registerAnalysisInvalidatedCallback(CallableT C)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static std::string getNodeLabel(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
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,...
bool shouldPrintAfterAll()
A special type used by analysis passes to provide an address that identifies that particular analysis...
LLVM_NODISCARD char front() const
front - Get the first character in the string.
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...
cl::opt< std::string > AfterColour("dot-cfg-after-color", cl::desc("Color for dot-cfg after elements."), cl::Hidden, cl::init("forestgreen"))
initializer< Ty > init(const Ty &Val)
Optional< DenseMap< intptr_t, BBGuard > > BBGuards
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
bool isFunctionInPrintList(StringRef FunctionName)
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
~PrintCrashIRInstrumentation()
@ PrintChangedDotCfgVerbose
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void handleIRAfterPass(Any IR, StringRef PassID)
static void analyzeIR(Any IR, IRDataT< T > &Data)
void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
Result run(Function &F, FunctionAnalysisManager &FAM)
Run the analysis pass over a function and produce CFG.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
print Print MemDeps of function
std::vector< std::string > printBeforePasses()
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
bool allAnalysesInSetPreserved() const
Directly test whether a set of analyses is preserved.
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
A Module instance is used to store all the information related to an LLVM module.
A CRTP mix-in that provides informational APIs needed for analysis passes.
static std::string getEdgeSourceLabel(const DisplayNode *From, DisplayNode::ChildIterator &To)
A node in the call graph.
std::vector< std::string > printAfterPasses()
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None)
Create a file in the system temporary directory.
void registerAfterAnalysisCallback(CallableT C)
const DisplayNode * NodeRef
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
static std::string getGraphProperties(const DotCfgDiffDisplayGraph *DiffData)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Represents analyses that only rely on functions' control flow.
static const Function * getParent(const Value *V)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
DisplayNode::ChildIterator ChildIteratorType
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
StringRef getName() const
Return a constant reference to the value's name.
A raw_ostream that writes to a file descriptor.
void registerAfterPassInvalidatedCallback(CallableT C)
SI registerCallbacks(PIC, &FAM)
bool Verbose
Print adaptors and pass managers.
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to CFG
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
virtual void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, Any) override
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_NODISCARD StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
static unsigned size(const DotCfgDiffDisplayGraph *G)
Lightweight error class with error context and mandatory checking.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
BlockT * getHeader() const
void handleInvalidated(StringRef PassID) override
ManagedStatic< OptBisect > OptBisector
Singleton instance of the OptBisect class, so multiple pass managers don't need to coordinate their u...
void registerBeforeSkippedPassCallback(CallableT C)
static NodeRef edge_dest(EdgeRef E)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
void handleInvalidatedPass(StringRef PassID)
void registerAfterPassCallback(CallableT C)
const DisplayEdge * EdgeRef
CFG(const Function *F, bool TrackBBLifetime)
Pass interface - Implemented by all 'passes'.
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
StringMap< std::string >::const_iterator begin() const
static cl::opt< ChangePrinter > PrintChanged("print-changed", cl::desc("Print changed IRs"), cl::Hidden, cl::ValueOptional, cl::init(ChangePrinter::NoChangePrinter), cl::values(clEnumValN(ChangePrinter::PrintChangedQuiet, "quiet", "Run in quiet mode"), clEnumValN(ChangePrinter::PrintChangedDiffVerbose, "diff", "Display patch-like changes"), clEnumValN(ChangePrinter::PrintChangedDiffQuiet, "diff-quiet", "Display patch-like changes in quiet mode"), clEnumValN(ChangePrinter::PrintChangedColourDiffVerbose, "cdiff", "Display patch-like changes with color"), clEnumValN(ChangePrinter::PrintChangedColourDiffQuiet, "cdiff-quiet", "Display patch-like changes in quiet mode with color"), clEnumValN(ChangePrinter::PrintChangedDotCfgVerbose, "dot-cfg", "Create a website with graphical changes"), clEnumValN(ChangePrinter::PrintChangedDotCfgQuiet, "dot-cfg-quiet", "Create a website with graphical changes in quiet mode"), clEnumValN(ChangePrinter::PrintChangedVerbose, "", "")))
int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, Optional< ArrayRef< StringRef >> Env=None, ArrayRef< Optional< StringRef >> Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, Optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
static bool renderNodesUsingHTML()
Represents either an error or a value T.
@ PrintChangedDiffVerbose
bool forcePrintModuleIR()
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
static nodes_iterator nodes_end(const DotCfgDiffDisplayGraph *G)
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
A container for analyses that lazily runs them and caches their results.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void print(raw_ostream &OS, bool Verbose=false, bool PrintNested=true, unsigned Depth=0) const
Print loop with all the BBs inside it.
static std::string getNodeAttributes(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
static ChildIteratorType child_end(NodeRef N)
BlockVerifier::State From
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
static cl::opt< bool > PrintCrashIR("print-on-crash", cl::desc("Print the last form of the IR before crash"), cl::init(false), cl::Hidden)
Conditional or Unconditional Branch instruction.
std::unique_ptr< raw_fd_ostream > HTML
static std::string getEdgeAttributes(const DisplayNode *From, DisplayNode::ChildIterator &To, const DotCfgDiffDisplayGraph *DiffData)
std::string & str()
Returns the string's reference.
LLVM Value Representation.
static ChildEdgeIterator child_edge_end(NodeRef N)
void handleFiltered(StringRef PassID, std::string &Name) override
static void printBBName(raw_ostream &out, const BasicBlock *BB)
static const char PassName[]
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
@ PrintChangedColourDiffVerbose
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Optional< std::vector< StOtherPiece > > Other
reference emplace_back(ArgTypes &&... Args)
static cl::opt< bool > VerifyPreservedCFG