42#include <unordered_map>
43#include <unordered_set>
51#ifdef EXPENSIVE_CHECKS
63 cl::desc(
"Print before passes that change them"),
70 cl::desc(
"system dot used by change reporters"));
98 cl::desc(
"Generate dot files into specified directory for changed IRs"),
103 "print-on-crash-path",
104 cl::desc(
"Print the last form of the IR before crash to a file"),
109 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
113 "opt-bisect-print-ir-path",
118 cl::desc(
"Print pass names and their ordinals"));
122 cl::desc(
"Print IR at pass with this number as "
123 "reported by print-passes-names"));
127 cl::desc(
"If specified, IR printed using the "
128 "-print-[before|after]{-all} options will be dumped into "
129 "files in this directory rather than written to stderr"),
143 cl::desc(
"exe called with module IR after each pass that "
148const Module *unwrapModule(
Any IR,
bool Force =
false) {
149 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
152 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR)) {
156 return (*F)->getParent();
159 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
163 return F.getParent();
166 assert(!Force &&
"Expected a module");
170 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR)) {
171 const Function *
F = (*L)->getHeader()->getParent();
174 return F->getParent();
188 M->print(
OS,
nullptr);
190 for (
const auto &
F :
M->functions()) {
206 const Function *
F = L->getHeader()->getParent();
212std::string getIRName(
Any IR) {
213 if (llvm::any_cast<const Module *>(&
IR))
216 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
217 return (*F)->getName().str();
219 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
220 return (*C)->getName();
222 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
223 return (*L)->getName().str();
228bool moduleContainsFilterPrintFunc(
const Module &M) {
229 return any_of(M.functions(),
231 return isFunctionInPrintList(F.getName());
244bool shouldPrintIR(
Any IR) {
245 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
246 return moduleContainsFilterPrintFunc(**M);
248 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
251 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
252 return sccContainsFilterPrintFunc(**
C);
254 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
262 if (!shouldPrintIR(
IR))
266 auto *M = unwrapModule(
IR);
267 assert(M &&
"should have unwrapped module");
272 if (
const auto **M = llvm::any_cast<const Module *>(&
IR)) {
277 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR)) {
282 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
287 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR)) {
297 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
298 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
299 "VerifierPass",
"PrintModulePass"});
307 S.append(Clean.
str());
311 S.append(SR[0] ==
'<' ?
"<" :
">");
319 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
321 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
329bool isInterestingFunction(
const Function &
F) {
338 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
339 return isInterestingFunction(**
F);
346 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
362 BeforeStack.emplace_back();
368 T &
Data = BeforeStack.back();
369 generateIRRepresentation(
IR, PassID,
Data);
375 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
377 std::string
Name = getIRName(
IR);
379 if (isIgnored(PassID)) {
381 handleIgnored(PassID,
Name);
384 handleFiltered(PassID,
Name);
387 T &
Before = BeforeStack.back();
390 generateIRRepresentation(
IR, PassID,
After);
395 omitAfter(PassID,
Name);
399 BeforeStack.pop_back();
404 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
411 handleInvalidated(PassID);
412 BeforeStack.pop_back();
428 handleInvalidatedPass(
P);
439 auto *M = unwrapModule(
IR,
true);
440 assert(M &&
"Expected module to be unwrapped when forced.");
441 Out <<
"*** IR Dump At Start ***\n";
442 M->print(Out,
nullptr);
447 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
453 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
460 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
466 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
478 std::string &Output) {
480 unwrapAndPrint(
OS,
IR);
485 const std::string &
Before,
489 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
495 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
499 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" <<
After;
505 if (TestChanged !=
"")
515 dbgs() <<
"Unable to create temporary file.";
520 dbgs() <<
"Unable to find test-changed executable.";
524 StringRef Args[] = {TestChanged, FileName[0], PassID};
527 dbgs() <<
"Error executing test-changed executable.";
532 dbgs() <<
"Unable to remove temporary file.";
548 const std::string &
Before,
557 const auto &BFD =
Before.getData();
558 const auto &AFD =
After.getData();
559 std::vector<std::string>::const_iterator BI =
Before.getOrder().begin();
560 std::vector<std::string>::const_iterator BE =
Before.getOrder().end();
561 std::vector<std::string>::const_iterator AI =
After.getOrder().begin();
562 std::vector<std::string>::const_iterator AE =
After.getOrder().end();
564 auto HandlePotentiallyRemovedData = [&](std::string S) {
568 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
571 auto HandleNewData = [&](std::vector<const T *> &Q) {
573 for (
const T *NBI : Q)
574 HandlePair(
nullptr, NBI);
587 std::vector<const T *> NewDataQueue;
589 if (!BFD.count(*AI)) {
592 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
601 while (BI != BE && *BI != *AI) {
602 HandlePotentiallyRemovedData(*BI);
606 HandleNewData(NewDataQueue);
608 const T &AData = AFD.find(*AI)->getValue();
609 const T &BData = BFD.find(*AI)->getValue();
610 HandlePair(&BData, &AData);
618 HandlePotentiallyRemovedData(*BI);
622 HandleNewData(NewDataQueue);
628 std::function<
void(
bool InModule,
unsigned Minor,
631 if (!CompareModule) {
634 "Expected only one function.");
635 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
636 After.getData().begin()->getValue());
644 assert((
B ||
A) &&
"Both functions cannot be missing.");
649 CompareFunc(
true, Minor++, *
B, *
A);
654 if (
const Module *M = getModuleForComparison(
IR)) {
657 generateFunctionData(
Data,
F);
661 const Function **FPtr = llvm::any_cast<const Function *>(&
IR);
662 const Function *
F = FPtr ? *FPtr :
nullptr;
664 const Loop **L = llvm::any_cast<const Loop *>(&
IR);
665 assert(L &&
"Unknown IR unit.");
666 F = (*L)->getHeader()->getParent();
668 assert(
F &&
"Unknown IR unit.");
669 generateFunctionData(
Data, *
F);
677 for (
const auto &
B :
F) {
678 std::string BBName =
B.getName().str();
679 if (BBName.empty()) {
686 Data.getOrder().emplace_back(
F.getName());
687 Data.getData().insert({
F.getName(), FD});
695 "PassRunDescriptorStack is not empty at exit");
703 unsigned int MaxHashWidth =
sizeof(
stable_hash) * 8 / 4;
705 if (llvm::any_cast<const Module *>(&
IR)) {
706 ResultStream <<
"-module";
707 }
else if (
const Function **
F = llvm::any_cast<const Function *>(&
IR)) {
708 ResultStream <<
"-function-";
713 llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
714 ResultStream <<
"-scc-";
717 }
else if (
const Loop **L = llvm::any_cast<const Loop *>(&
IR)) {
718 ResultStream <<
"-loop-";
731 "The flag -ir-dump-directory must be passed to dump IR to files");
733 ResultPath += RootDirectory;
736 FilenameStream << CurrentPassNumber;
737 FilenameStream <<
"-";
739 FilenameStream <<
"-";
742 return std::string(ResultPath);
752 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
754 return FileSuffixes[
static_cast<size_t>(
Type)];
757void PrintIRInstrumentation::pushPassRunDescriptor(
761 PassRunDescriptor(M, DumpIRFilename, getIRName(
IR), PassID));
764PrintIRInstrumentation::PassRunDescriptor
765PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
766 assert(!PassRunDescriptorStack.
empty() &&
"empty PassRunDescriptorStack");
767 PassRunDescriptor Descriptor = PassRunDescriptorStack.
pop_back_val();
768 assert(Descriptor.PassID.equals(PassID) &&
769 "malformed PassRunDescriptorStack");
777 if (!ParentPath.empty()) {
781 " to support -ir-dump-directory: " + EC.message());
788 " to support -ir-dump-directory: " + EC.message());
792void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
793 if (isIgnored(PassID))
796 std::string DumpIRFilename;
798 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID)))
799 DumpIRFilename = fetchDumpFilename(PassID,
IR);
805 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
806 shouldPrintAfterPass(PassID))
807 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
809 if (!shouldPrintIR(
IR))
814 if (shouldPrintPassNumbers())
815 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID <<
"\n";
817 if (!shouldPrintBeforePass(PassID))
821 Stream <<
"; *** IR Dump Before " << PassID <<
" on " << getIRName(
IR)
823 unwrapAndPrint(Stream,
IR);
826 if (!DumpIRFilename.empty()) {
827 DumpIRFilename +=
getFileSuffix(IRDumpFileSuffixType::Before);
830 WriteIRToStream(DumpIRFileStream);
832 WriteIRToStream(
dbgs());
836void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
837 if (isIgnored(PassID))
840 if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
841 !shouldPrintAtPassNumber())
844 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
845 assert(StoredPassID == PassID &&
"mismatched PassID");
847 if (!shouldPrintIR(
IR) || !shouldPrintAfterPass(PassID))
851 Stream <<
"; *** IR Dump "
852 << (shouldPrintAtPassNumber()
855 <<
" on " << IRName <<
" ***\n";
856 unwrapAndPrint(Stream,
IR);
860 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
861 "should be set in printBeforePass");
862 const std::string DumpIRFilenameWithSuffix =
867 WriteIRToStream(DumpIRFileStream, IRName);
869 WriteIRToStream(
dbgs(), IRName);
873void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
874 if (isIgnored(PassID))
877 if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
878 !shouldPrintAtPassNumber())
881 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
882 assert(StoredPassID == PassID &&
"mismatched PassID");
885 if (!M || !shouldPrintAfterPass(PassID))
891 if (shouldPrintAtPassNumber())
892 Banner =
formatv(
"; *** IR Dump At {0}-{1} on {2} (invalidated) ***",
893 CurrentPassNumber, PassID, IRName);
895 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***",
897 Stream << Banner <<
"\n";
902 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
903 "should be set in printBeforePass");
904 const std::string DumpIRFilenameWithSuffix =
909 WriteIRToStream(DumpIRFileStream, M, IRName);
911 WriteIRToStream(
dbgs(), M, IRName);
915bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
923bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
934bool PrintIRInstrumentation::shouldPrintPassNumbers() {
938bool PrintIRInstrumentation::shouldPrintAtPassNumber() {
948 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
953 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
957 this->printAfterPass(
P,
IR);
961 this->printAfterPassInvalidated(
P);
973 const Function **FPtr = llvm::any_cast<const Function *>(&
IR);
974 const Function *
F = FPtr ? *FPtr :
nullptr;
976 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
977 F = (*L)->getHeader()->getParent();
979 bool ShouldRun = !(
F &&
F->hasOptNone());
980 if (!ShouldRun && DebugLogging) {
981 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
982 <<
" due to optnone attribute\n";
996 this->HasWrittenIR =
true;
997 const Module *M = unwrapModule(
IR,
true);
998 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1003 M->print(
OS,
nullptr);
1032 std::vector<StringRef> SpecialPasses;
1034 SpecialPasses.emplace_back(
"PassManager");
1035 SpecialPasses.emplace_back(
"PassAdaptor");
1041 "Unexpectedly skipping special pass");
1043 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1051 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1052 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR)) {
1053 unsigned Count = (*F)->getInstructionCount();
1054 OS <<
" (" << Count <<
" instruction";
1058 }
else if (
const auto **
C =
1059 llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
1060 int Count = (*C)->size();
1061 OS <<
" (" << Count <<
" node";
1087 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1094 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1098 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1104 bool TrackBBLifetime) {
1105 if (TrackBBLifetime)
1107 for (
const auto &BB : *
F) {
1109 BBGuards->try_emplace(intptr_t(&BB), &BB);
1113 BBGuards->try_emplace(intptr_t(Succ), Succ);
1120 out << BB->
getName() <<
"<" << BB <<
">";
1125 out <<
"unnamed_removed<" << BB <<
">";
1131 <<
"<" << BB <<
">";
1135 unsigned FuncOrderBlockNum = 0;
1139 FuncOrderBlockNum++;
1141 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1148 if (
Before.isPoisoned()) {
1149 out <<
"Some blocks were deleted\n";
1155 out <<
"Different number of non-leaf basic blocks: before="
1156 <<
Before.Graph.size() <<
", after=" <<
After.Graph.size() <<
"\n";
1158 for (
auto &BB :
Before.Graph) {
1159 auto BA =
After.Graph.find(BB.first);
1160 if (BA ==
After.Graph.end()) {
1161 out <<
"Non-leaf block ";
1163 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1167 for (
auto &BA :
After.Graph) {
1168 auto BB =
Before.Graph.find(BA.first);
1169 if (BB ==
Before.Graph.end()) {
1170 out <<
"Non-leaf block ";
1172 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1176 if (BB->second == BA.second)
1179 out <<
"Different successors of block ";
1181 out <<
" (unordered):\n";
1182 out <<
"- before (" << BB->second.size() <<
"): ";
1183 for (
auto &SuccB : BB->second) {
1185 if (SuccB.second != 1)
1186 out <<
"(" << SuccB.second <<
"), ";
1191 out <<
"- after (" << BA.second.size() <<
"): ";
1192 for (
auto &SuccA : BA.second) {
1194 if (SuccA.second != 1)
1195 out <<
"(" << SuccA.second <<
"), ";
1275 if (
const auto **MaybeF = llvm::any_cast<const Function *>(&
IR)) {
1277 }
else if (
const auto **MaybeM = llvm::any_cast<const Module *>(&
IR)) {
1289 bool Registered =
false;
1292#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1293 assert(&PassStack.emplace_back(
P));
1298 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1313 if (
auto *MaybeM = llvm::any_cast<const Module *>(&
IR)) {
1321#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1322 assert(PassStack.pop_back_val() ==
P &&
1323 "Before and After callbacks must correspond");
1330#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1331 assert(PassStack.pop_back_val() ==
P &&
1332 "Before and After callbacks must correspond");
1340 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1344 if (
auto *HashBefore =
1348 "Function @{0} changed by {1} without invalidating analyses",
1354 const CFG &GraphBefore,
const CFG &GraphAfter) {
1355 if (GraphAfter == GraphBefore)
1359 <<
"Error: " <<
Pass
1360 <<
" does not invalidate CFG analyses but CFG changes detected in "
1362 << FuncName <<
":\n";
1367 if (
auto *GraphBefore =
1369 CheckCFG(
P,
F->getName(), *GraphBefore,
1372 if (
auto *MaybeM = llvm::any_cast<const Module *>(&
IR)) {
1374 if (
auto *HashBefore =
1378 "Module changed by {0} without invalidating analyses",
P));
1389 if (isIgnored(
P) ||
P ==
"VerifierPass")
1391 const Function **FPtr = llvm::any_cast<const Function *>(&
IR);
1392 const Function *
F = FPtr ? *FPtr :
nullptr;
1394 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
1395 F = (*L)->getHeader()->getParent();
1400 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1405 const Module **MPtr = llvm::any_cast<const Module *>(&
IR);
1406 const Module *M = MPtr ? *MPtr :
nullptr;
1408 if (
const auto **
C =
1409 llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
1410 M = (*C)->begin()->getFunction().getParent();
1415 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1437 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1441 [&](
bool InModule,
unsigned Minor,
1444 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1456 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1463 const std::string Removed =
1464 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1465 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1466 const std::string NoChange =
" %l\n";
1467 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1489 this->runAfterPass();
1501void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1510class DotCfgDiffDisplayGraph;
1513class DisplayElement {
1516 StringRef getColour()
const {
return Colour; }
1519 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1525class DisplayEdge :
public DisplayElement {
1530 std::string getValue()
const {
return Value; }
1532 const DisplayNode &getDestinationNode()
const {
return Node; }
1536 const DisplayNode &
Node;
1540class DisplayNode :
public DisplayElement {
1548 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1549 ChildIterator children_begin()
const {
return Children.cbegin(); }
1550 ChildIterator children_end()
const {
return Children.cend(); }
1553 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1554 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1555 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1561 std::string getContent()
const {
return Content; }
1564 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1565 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1566 return *EdgeMap.find(&To)->second;
1571 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1572 return getEdge(Sink).getValue();
1575 void createEdgeMap();
1583 std::vector<DisplayEdge> Edges;
1585 std::vector<DisplayEdge *> EdgePtrs;
1586 std::unordered_set<DisplayNode *>
Children;
1587 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1590 bool AllEdgesCreated =
false;
1594class DotCfgDiffDisplayGraph {
1596 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1599 void generateDotFile(
StringRef DotFile);
1602 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1603 NodeIterator nodes_begin()
const {
1604 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1605 return NodePtrs.cbegin();
1607 NodeIterator nodes_end()
const {
1608 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1609 return NodePtrs.cend();
1614 void setEntryNode(
unsigned N) {
1616 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1617 NodeGenerationComplete =
true;
1618 for (
auto &
N : Nodes)
1619 NodePtrs.emplace_back(&
N);
1621 EntryNode = NodePtrs[
N];
1625 void createNode(std::string
C,
StringRef Colour) {
1626 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1627 Nodes.emplace_back(
C, Colour);
1630 DisplayNode &getNode(
unsigned N) {
1631 assert(
N < Nodes.size() &&
"Node is out of bounds");
1634 unsigned size()
const {
1635 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1636 return Nodes.size();
1640 std::string getGraphName()
const {
return GraphName; }
1645 return Node.getContent();
1649 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1650 return attribute(
Node.getColour());
1654 std::string getEdgeColorAttr(
const DisplayNode &
From,
1655 const DisplayNode &To)
const {
1656 return attribute(
From.getEdge(To).getColour());
1660 DisplayNode *getEntryNode()
const {
1661 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1667 std::string attribute(
StringRef Colour)
const {
1668 return "color=" + Colour.
str();
1671 bool NodeGenerationComplete =
false;
1672 const std::string GraphName;
1673 std::vector<DisplayNode> Nodes;
1674 std::vector<DisplayNode *> NodePtrs;
1675 DisplayNode *EntryNode =
nullptr;
1680 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1681 Edges.emplace_back(
Value.str(),
Node, Colour);
1685void DisplayNode::createEdgeMap() {
1688 AllEdgesCreated =
true;
1689 for (
auto &
E : Edges)
1690 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1693class DotCfgDiffNode;
1697class DotCfgDiffNode {
1699 DotCfgDiffNode() =
delete;
1705 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1706 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1711 unsigned getIndex()
const {
return N; }
1715 assert(
Data[0] &&
"Expected Data[0] to be set.");
1716 return Data[0]->getLabel();
1719 StringRef getColour()
const {
return Colour; }
1723 assert(!
Data[1] &&
"Expected only one block datum");
1731 "Unexpected edge count and color.");
1732 EdgesMap[
E] = {
Value.str(), Colour};
1738 StringRef getEdgeColour(
const unsigned S)
const {
1739 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1740 return EdgesMap.at(S).second;
1744 std::string getBodyContent()
const;
1746 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1747 std::map<const unsigned, unsigned> &NodeMap)
const;
1754 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1756 std::vector<unsigned> Edges;
1769 DotCfgDiff(
const DotCfgDiff &) =
delete;
1770 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1772 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1779 StringRef getEdgeSourceLabel(
const unsigned &Source,
1780 const unsigned &Sink)
const {
1782 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1783 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1784 return EdgeLabels.find(S)->getValue();
1788 unsigned size()
const {
return Nodes.size(); }
1790 const DotCfgDiffNode &getNode(
unsigned N)
const {
1791 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1797 std::string colourize(std::string S,
StringRef Colour)
const;
1800 unsigned Pos = Nodes.size();
1801 Nodes.emplace_back(*
this, Pos, BD,
C);
1802 NodePosition.insert({
Label, Pos});
1808 std::vector<DotCfgDiffNode> Nodes;
1810 const std::string GraphName;
1815std::string DotCfgDiffNode::getBodyContent()
const {
1817 assert(
Data[1] &&
"Expected Data[1] to be set.");
1820 for (
unsigned I = 0;
I < 2; ++
I) {
1821 SR[
I] =
Data[
I]->getBody();
1823 if (SR[
I][0] ==
'\n')
1826 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1830 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1832 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1834 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1835 std::string Diff =
Data[0]->getLabel().str();
1836 Diff +=
":\n<BR align=\"left\"/>" +
1837 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1838 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1843 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1846 std::string S =
R.sub(
"", Diff, &
Error);
1857 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1858 std::string Body = makeHTMLReady(
Data[0]->getBody());
1862 if (BS.
front() ==
'\n')
1867 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1869 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1872 while (BS1.
size()) {
1873 S.append(
"<BR align=\"left\"/>");
1875 S.append(
Line.str());
1878 S.append(
"<BR align=\"left\"/></FONT>");
1882std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1883 if (S.length() == 0)
1885 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1890 : GraphName(Title.str()) {
1894 for (
auto &
B :
Before.getData()) {
1903 Sink !=
E; ++Sink) {
1904 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1905 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1911 for (
auto &
A :
After.getData()) {
1914 unsigned C = NodePosition.count(Label);
1919 assert(
C == 1 &&
"Unexpected multiple nodes.");
1920 Nodes[NodePosition[
Label]].setCommon(BD);
1925 Sink !=
E; ++Sink) {
1926 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1927 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1928 unsigned C = EdgesMap.
count(Key);
1938 for (
auto &
E : EdgesMap) {
1941 auto SP1 = S.
rsplit(
' ');
1942 auto &SourceSink = SP1.first;
1943 auto SP2 = SourceSink.split(
' ');
1948 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
1949 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
1950 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
1951 unsigned SinkNode = NodePosition[
Sink];
1955 if (EdgeLabels.count(SourceSink) == 0)
1956 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
1958 StringRef V = EdgeLabels.find(SourceSink)->getValue();
1959 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
1961 EdgeLabels[SourceSink] =
NV;
1963 SourceNode.addEdge(SinkNode,
Value, Colour);
1965 for (
auto &
I : Nodes)
1969DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
1971 assert(NodePosition.count(EntryNodeName) == 1 &&
1972 "Expected to find entry block in map.");
1973 unsigned Entry = NodePosition[EntryNodeName];
1974 assert(Entry < Nodes.size() &&
"Expected to find entry node");
1975 DotCfgDiffDisplayGraph
G(Title.
str());
1977 std::map<const unsigned, unsigned> NodeMap;
1979 int EntryIndex = -1;
1981 for (
auto &
I : Nodes) {
1982 if (
I.getIndex() == Entry)
1984 G.createNode(
I.getBodyContent(),
I.getColour());
1985 NodeMap.insert({
I.getIndex(),
Index++});
1987 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
1988 G.setEntryNode(EntryIndex);
1990 for (
auto &
I : NodeMap) {
1991 unsigned SourceNode =
I.first;
1992 unsigned DisplayNode =
I.second;
1993 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
1998void DotCfgDiffNode::createDisplayEdges(
1999 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2000 std::map<const unsigned, unsigned> &NodeMap)
const {
2002 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2004 for (
auto I : Edges) {
2005 unsigned SinkNodeIndex =
I;
2006 StringRef Colour = getEdgeColour(SinkNodeIndex);
2007 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2009 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2010 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2011 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2013 SourceDisplayNode.createEdgeMap();
2016void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2017 for (
auto E : EdgesMap) {
2019 Edges.emplace_back(
E.first);
2035 return G->getEntryNode();
2038 return N->children_begin();
2042 return G->nodes_begin();
2045 return G->nodes_end();
2048 return N->edges_begin();
2052 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2062 return DiffData->getGraphName();
2066 return "\tsize=\"190, 190\";\n";
2069 const DotCfgDiffDisplayGraph *DiffData) {
2070 return DiffData->getNodeLabel(*Node);
2073 const DotCfgDiffDisplayGraph *DiffData) {
2074 return DiffData->getNodeAttributes(*Node);
2077 DisplayNode::ChildIterator &To) {
2078 return From->getEdgeSourceLabel(**To);
2081 DisplayNode::ChildIterator &To,
2082 const DotCfgDiffDisplayGraph *DiffData) {
2083 return DiffData->getEdgeColorAttr(*
From, **To);
2091void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2095 errs() <<
"Error: " <<
EC.message() <<
"\n";
2110 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2111 if (Br->isUnconditional())
2117 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2120 for (
auto &
C : Sw->cases()) {
2121 assert(
C.getCaseValue() &&
"Expected to find case value.");
2137 assert(
HTML &&
"Expected outstream to be set");
2142 Extender =
formatv(
"{0}_{1}",
N, Minor);
2151 std::string DotFile =
Twine(SV).
str();
2156 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2160 std::string EntryBlockName =
After.getEntryBlockName();
2162 if (EntryBlockName ==
"")
2163 EntryBlockName =
Before.getEntryBlockName();
2164 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2166 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2167 DG.generateDotFile(DotFile);
2172 errs() <<
"Error: " << EC.message() <<
"\n";
2181 return "Unable to find dot executable.";
2186 return "Error executing system dot.";
2190 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2195 assert(
HTML &&
"Expected outstream to be set");
2196 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2197 <<
"Initial IR (by function)</button>\n"
2198 <<
"<div class=\"content\">\n"
2207 [&](
bool InModule,
unsigned Minor,
2224 assert(
HTML &&
"Expected outstream to be set");
2226 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2227 N, makeHTMLReady(PassID),
Name);
2235 assert(
HTML &&
"Expected outstream to be set");
2238 [&](
bool InModule,
unsigned Minor,
2244 *
HTML <<
" </p></div>\n";
2249 assert(
HTML &&
"Expected outstream to be set");
2251 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2257 assert(
HTML &&
"Expected outstream to be set");
2259 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2260 makeHTMLReady(PassID),
Name);
2266 assert(
HTML &&
"Expected outstream to be set");
2268 makeHTMLReady(PassID),
Name);
2275 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2281 *
HTML <<
"<!doctype html>"
2284 <<
"<style>.collapsible { "
2285 <<
"background-color: #777;"
2287 <<
" cursor: pointer;"
2288 <<
" padding: 18px;"
2291 <<
" text-align: left;"
2292 <<
" outline: none;"
2293 <<
" font-size: 15px;"
2294 <<
"} .active, .collapsible:hover {"
2295 <<
" background-color: #555;"
2297 <<
" padding: 0 18px;"
2298 <<
" display: none;"
2299 <<
" overflow: hidden;"
2300 <<
" background-color: #f1f1f1;"
2303 <<
"<title>passes.html</title>"
2313 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2315 <<
"for (i = 0; i < coll.length; i++) {"
2316 <<
"coll[i].addEventListener(\"click\", function() {"
2317 <<
" this.classList.toggle(\"active\");"
2318 <<
" var content = this.nextElementSibling;"
2319 <<
" if (content.style.display === \"block\"){"
2320 <<
" content.style.display = \"none\";"
2323 <<
" content.style.display= \"block\";"
2341 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2347 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2354 : PrintPass(DebugLogging, PrintPassOpts),
2355 OptNone(DebugLogging),
2380void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2387 "Did not expect to get here without option set.");
2396 "Did not expect to get here without option set.");
2397 CrashReporter =
nullptr;
2406 CrashReporter =
this;
2412 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2415 OS <<
" Filtered Out ***\n";
2418 OS <<
" Started ***\n";
2419 unwrapAndPrint(
OS,
IR);
This file provides Any, a non-template class modeled in the spirit of std::any.
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::optional< std::vector< StOtherPiece > > Other
static bool isInteresting(const SCEV *S, const Instruction *I, const Loop *L, ScalarEvolution *SE, LoopInfo *LI)
isInteresting - Test whether the given expression is "interesting" when used by the given expression,...
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
Implements a lazy call graph analysis and related passes for the new pass manager.
Legalize the Machine IR a function s Machine IR
static std::string getNodeLabel(const ValueInfo &VI, GlobalValueSummary *GVS)
Module.h This file contains the declarations for the Module class.
ppc ctr loops PowerPC CTR Loops Verify
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
This header defines various interfaces for pass management in LLVM.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static cl::opt< std::string > BeforeColour("dot-cfg-before-color", cl::desc("Color for dot-cfg before elements"), cl::Hidden, cl::init("red"))
static cl::opt< std::string > IRDumpDirectory("ir-dump-directory", cl::desc("If specified, IR printed using the " "-print-[before|after]{-all} options will be dumped into " "files in this directory rather than written to stderr"), cl::Hidden, cl::value_desc("filename"))
static cl::opt< std::string > OptBisectPrintIRPath("opt-bisect-print-ir-path", cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden)
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
static cl::opt< std::string > DotCfgDir("dot-cfg-dir", cl::desc("Generate dot files into specified directory for changed IRs"), cl::Hidden, cl::init("./"))
static cl::opt< bool > VerifyAnalysisInvalidation("verify-analysis-invalidation", cl::Hidden, cl::init(false))
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
static StringRef getFileSuffix(IRDumpFileSuffixType Type)
static SmallString< 32 > getIRFileDisplayName(Any IR)
static SmallVector< Function *, 1 > GetFunctions(Any IR)
static void printBBName(raw_ostream &out, const BasicBlock *BB)
static cl::opt< unsigned > PrintAtPassNumber("print-at-pass-number", cl::init(0), cl::Hidden, cl::desc("Print IR at pass with this number as " "reported by print-passes-names"))
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
static int prepareDumpIRFileDescriptor(const StringRef DumpIRFilename)
static cl::opt< std::string > AfterColour("dot-cfg-after-color", cl::desc("Color for dot-cfg after elements"), cl::Hidden, cl::init("forestgreen"))
static cl::opt< bool > PrintOnCrash("print-on-crash", cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"), cl::Hidden)
static cl::opt< bool > PrintPassNumbers("print-pass-numbers", cl::init(false), cl::Hidden, cl::desc("Print pass names and their ordinals"))
static cl::opt< std::string > PrintOnCrashPath("print-on-crash-path", cl::desc("Print the last form of the IR before crash to a file"), cl::Hidden)
This header defines a class that provides bookkeeping for all standard (i.e in-tree) pass instrumenta...
static const char PassName[]
This templated class represents "all analyses that operate over <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
bool isEntryBlock() const
Return true if this is the entry block of the containing function.
const Function * getParent() const
Return the enclosing method, or null if none.
const T & getData() const
Conditional or Unconditional Branch instruction.
Represents analyses that only rely on functions' control flow.
void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName)
void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName)
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
void handleInvalidatedPass(StringRef PassID)
virtual ~ChangeReporter()
void addSuccessorLabel(StringRef Succ, StringRef Label)
DCData(const BasicBlock &B)
std::unique_ptr< raw_fd_ostream > HTML
void handleInvalidated(StringRef PassID) override
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< DCData > &Output) override
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
void handleInitialIR(Any IR) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< DCData > &Before, const FuncDataT< DCData > &After)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
DotCfgChangeReporter(bool Verbose)
void handleIgnored(StringRef PassID, std::string &Name) override
~DotCfgChangeReporter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, Any) override
void handleFiltered(StringRef PassID, std::string &Name) override
void omitAfter(StringRef PassID, std::string &Name) override
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
~IRChangedPrinter() override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
void omitAfter(StringRef PassID, std::string &Name) override
void handleInvalidated(StringRef PassID) override
void handleIR(const std::string &IR, StringRef PassID)
void handleInitialIR(Any IR) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleFiltered(StringRef PassID, std::string &Name) override
~IRChangedTester() override
static void analyzeIR(Any IR, IRDataT< T > &Data)
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
static bool generateFunctionData(IRDataT< T > &Data, const Function &F)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~InLineChangePrinter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, Any) override
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< EmptyData > &Output) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This is an important class for using LLVM in a threaded context.
OptPassGate & getOptPassGate() const
Access the object which can disable optional passes and individual optimizations at compile time.
A node in the call graph.
An SCC of the call graph.
Represents a single loop in the control flow graph.
A Module instance is used to store all the information related to an LLVM module.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
bool shouldRun(StringRef PassName, Any IR)
Extensions to this class implement mechanisms to disable passes and individual optimizations at compi...
virtual bool isEnabled() const
isEnabled() should return true before calling shouldRunPass().
virtual bool shouldRunPass(const StringRef PassName, StringRef IRDescription)
IRDescription is a textual description of the IR unit the pass is running over.
static void report(const OrderedChangedData &Before, const OrderedChangedData &After, function_ref< void(const T *, const T *)> HandlePair)
StringMap< T > & getData()
std::vector< std::string > & getOrder()
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerAnalysesClearedCallback(CallableT C)
void registerBeforeAnalysisCallback(CallableT C)
void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront=false)
void registerAnalysisInvalidatedCallback(CallableT C)
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
void registerAfterAnalysisCallback(CallableT C, bool ToFront=false)
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerBeforeSkippedPassCallback(CallableT C)
void registerShouldRunOptionalPassCallback(CallableT C)
void registerAfterPassCallback(CallableT C, bool ToFront=false)
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
~PrintCrashIRInstrumentation()
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~PrintIRInstrumentation()
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)
StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef drop_until(function_ref< bool(char)> F) const
Return a StringRef equal to 'this', but with all characters not satisfying the given predicate droppe...
constexpr size_t size() const
size - Get the string size.
char front() const
front - Get the first character in the string.
StringRef take_until(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
void handleInitialIR(Any IR) override
void handleInvalidated(StringRef PassID) override
TextChangeReporter(bool Verbose)
void omitAfter(StringRef PassID, std::string &Name) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleFiltered(StringRef PassID, std::string &Name) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
TimeProfilingPassesHandler()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
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.
A raw_ostream that writes to an SmallVector or SmallString.
#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.
std::error_code openFile(const Twine &Name, int &ResultFD, CreationDisposition Disp, FileAccess Access, OpenFlags Flags, unsigned Mode=0666)
Opens a file with the specified creation disposition, access mode, and flags and returns a file descr...
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.
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)
This function executes the program using the arguments provided.
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
This is an optimization pass for GlobalISel generic memory operations.
Interval::succ_iterator succ_end(Interval *I)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code prepareTempFiles(SmallVector< int > &FD, ArrayRef< StringRef > SR, SmallVector< std::string > &FileName)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
bool forcePrintModuleIR()
std::vector< std::string > printAfterPasses()
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
auto successors(const MachineBasicBlock *BB)
bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
bool shouldPrintBeforeAll()
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool shouldPrintAfterAll()
cl::opt< ChangePrinter > PrintChanged
TimeTraceProfiler * getTimeTraceProfilerInstance()
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
std::vector< std::string > printBeforePasses()
bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
bool shouldPrintAfterSomePass()
void timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
IRHash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
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.
void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)
stable_hash stable_hash_combine_string(const StringRef &S)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
std::array< uint32_t, 5 > ModuleHash
160 bits SHA1
uint64_t stable_hash
An opaque object representing a stable hash code.
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.
Result run(Function &F, FunctionAnalysisManager &FAM)
Result run(Module &F, ModuleAnalysisManager &FAM)
A CRTP mix-in that provides informational APIs needed for analysis passes.
A special type used by analysis passes to provide an address that identifies that particular analysis...
static std::string getEdgeAttributes(const DisplayNode *From, DisplayNode::ChildIterator &To, const DotCfgDiffDisplayGraph *DiffData)
static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData)
static std::string getEdgeSourceLabel(const DisplayNode *From, DisplayNode::ChildIterator &To)
static std::string getNodeAttributes(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
static std::string getNodeLabel(const DisplayNode *Node, const DotCfgDiffDisplayGraph *DiffData)
static bool renderNodesUsingHTML()
static std::string getGraphProperties(const DotCfgDiffDisplayGraph *DiffData)
DOTGraphTraits(bool Simple=false)
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
static ChildEdgeIterator child_edge_end(NodeRef N)
static unsigned size(const DotCfgDiffDisplayGraph *G)
static NodeRef getEntryNode(const DotCfgDiffDisplayGraph *G)
DisplayNode::EdgeIterator ChildEdgeIterator
static ChildIteratorType child_begin(NodeRef N)
const DisplayEdge * EdgeRef
static ChildIteratorType child_end(NodeRef N)
const DisplayNode * NodeRef
static NodeRef edge_dest(EdgeRef E)
DotCfgDiffDisplayGraph::NodeIterator nodes_iterator
DisplayNode::ChildIterator ChildIteratorType
static nodes_iterator nodes_begin(const DotCfgDiffDisplayGraph *G)
static ChildEdgeIterator child_edge_begin(NodeRef N)
static nodes_iterator nodes_end(const DotCfgDiffDisplayGraph *G)
std::optional< DenseMap< intptr_t, BBGuard > > BBGuards
static void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
CFG(const Function *F, bool TrackBBLifetime)
bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
bool SkipAnalyses
Don't print information for analyses.
bool Verbose
Print adaptors and pass managers.
bool Indent
Indent based on hierarchy.