54#ifdef EXPENSIVE_CHECKS
66 cl::desc(
"Print before passes that change them"),
73 cl::desc(
"system dot used by change reporters"));
101 cl::desc(
"Generate dot files into specified directory for changed IRs"),
106 "print-on-crash-path",
107 cl::desc(
"Print the last form of the IR before crash to a file"),
112 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
116 "opt-bisect-print-ir-path",
121 cl::desc(
"Print pass names and their ordinals"));
125 cl::desc(
"Print IR before the passes with specified numbers as "
126 "reported by print-pass-numbers"));
130 cl::desc(
"Print IR after the passes with specified numbers as "
131 "reported by print-pass-numbers"));
135 cl::desc(
"If specified, IR printed using the "
136 "-print-[before|after]{-all} options will be dumped into "
137 "files in this directory rather than written to stderr"),
142 cl::desc(
"Dump dropped debug variables stats"),
159 cl::desc(
"exe called with module IR after each pass that "
162bool loopContainsPrintSourceLoc(
const Loop &L) {
163 const Function *
F = L.getHeader()->getParent();
168 if (SourceLocFilterEmpty)
188 return F->getParent();
195 return F.getParent();
198 assert(!Force &&
"Expected a module");
203 const Function *
F =
L->getHeader()->getParent();
204 if (!Force && !loopContainsPrintSourceLoc(*L))
206 return F->getParent();
212 return MF->getFunction().getParent();
226 M->print(OS,
nullptr);
228 for (
const auto &
F : M->functions()) {
244 if (!loopContainsPrintSourceLoc(*L))
260 return F->getName().str();
266 return "loop %" +
L->getName().str() +
" in function " +
267 L->getHeader()->getParent()->getName().str();
275bool moduleContainsFilterPrintFunc(
const Module &M) {
278 return any_of(M.functions(),
279 [](
const Function &
F) { return shouldPrintFunction(F); });
291 return moduleContainsFilterPrintFunc(*M);
297 return sccContainsFilterPrintFunc(*
C);
300 return loopContainsPrintSourceLoc(*L);
310 if (!shouldPrintIR(
IR))
314 auto *M = unwrapModule(
IR);
315 assert(M &&
"should have unwrapped module");
350 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
351 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
352 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
353 "PrintMIRPreparePass",
"RequireAnalysisPass",
354 "InvalidateAnalysisPass"});
362 S.append(Clean.
str());
366 S.append(SR[0] ==
'<' ?
"<" :
">");
377 return C->begin()->getFunction().getParent();
389 return isInterestingFunction(*
F);
415 if (!Before.IsInteresting)
427 std::string Name = getIRName(
IR);
429 if (isIgnored(PassID)) {
435 if (!Before.IsInteresting && !AfterIsInteresting) {
440 if (AfterIsInteresting)
444 if (Before.Data == After) {
470 PIC.registerBeforeNonSkippedPassCallback(
475 PIC.registerAfterPassCallback(
479 PIC.registerAfterPassInvalidatedCallback(
493 auto *M = unwrapModule(
IR,
true);
494 assert(M &&
"Expected module to be unwrapped when forced.");
495 Out <<
"*** IR Dump At Start ***\n";
496 M->print(
Out,
nullptr);
501 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
507 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
514 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
520 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
532 std::string &Output) {
534 unwrapAndPrint(OS,
IR);
539 const std::string &Before,
543 Out <<
"*** IR Dump Before " << PassID <<
" on " << Name <<
" ***\n"
549 Out <<
"*** IR Deleted After " << PassID <<
" on " << Name <<
" ***\n";
553 Out <<
"*** IR Dump After " << PassID <<
" on " << Name <<
" ***\n" << After;
559 if (TestChanged !=
"")
569 dbgs() <<
"Unable to create temporary file.";
574 dbgs() <<
"Unable to find test-changed executable.";
578 StringRef Args[] = {TestChanged, FileName[0], PassID};
581 dbgs() <<
"Error executing test-changed executable.";
586 dbgs() <<
"Unable to remove temporary file.";
602 const std::string &Before,
611 const auto &BFD = Before.
getData();
612 const auto &AFD = After.
getData();
613 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
614 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
615 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
616 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
618 auto HandlePotentiallyRemovedData = [&](std::string S) {
622 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
625 auto HandleNewData = [&](std::vector<const T *> &Q) {
627 for (
const T *NBI : Q)
628 HandlePair(
nullptr, NBI);
641 std::vector<const T *> NewDataQueue;
643 if (!BFD.count(*AI)) {
646 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
655 while (BI != BE && *BI != *AI) {
656 HandlePotentiallyRemovedData(*BI);
660 HandleNewData(NewDataQueue);
662 const T &AData = AFD.find(*AI)->getValue();
663 const T &BData = BFD.find(*AI)->getValue();
664 HandlePair(&BData, &AData);
672 HandlePotentiallyRemovedData(*BI);
676 HandleNewData(NewDataQueue);
682 std::function<
void(
bool InModule,
unsigned Minor,
685 if (!CompareModule) {
688 (!
Before.getData().empty() || !
After.getData().empty()) &&
689 "Expected one function in at least one IR unit.");
692 Before.getData().empty() ? Missing
693 :
Before.getData().begin()->getValue();
695 After.getData().empty() ? Missing :
After.getData().begin()->getValue();
696 CompareFunc(
false, 0, BeforeFunction, AfterFunction);
704 assert((
B ||
A) &&
"Both functions cannot be missing.");
709 CompareFunc(
true, Minor++, *
B, *
A);
715 if (
const Module *M = getModuleForComparison(
IR)) {
728 auto *
F = L->getHeader()->getParent();
750 if (SourceLocFilterEmpty)
761template <
typename FunctionT>
766 for (
const auto &
B :
F) {
767 std::string BBName =
B.getName().str();
768 if (BBName.empty()) {
775 Data.getOrder().emplace_back(
F.getName());
776 Data.getData().insert({
F.getName(), FD});
783 assert(PassRunDescriptorStack.empty() &&
784 "PassRunDescriptorStack is not empty at exit");
788 const Module *M = unwrapModule(
IR,
true);
789 assert(M &&
"should have unwrapped module");
791 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
794 ResultStream <<
"-module";
796 ResultStream <<
"-function-";
801 ResultStream <<
"-scc-";
805 ResultStream <<
"-loop-";
809 ResultStream <<
"-machine-function-";
825StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
826 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
828 return FileSuffixes[
static_cast<size_t>(
Type)];
831std::string PrintIRInstrumentation::fetchDumpFilename(
833 IRDumpFileSuffixType SuffixType) {
835 "The flag -ir-dump-directory must be passed to dump IR to files");
838 raw_svector_ostream FilenameStream(
Filename);
839 FilenameStream << PassNumber;
840 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
842 FilenameStream << getFileSuffix(SuffixType);
844 SmallString<128> ResultPath;
846 return std::string(ResultPath);
849void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
851 unsigned PassNumber) {
854 getIRName(
IR), PassID);
857PrintIRInstrumentation::PassRunDescriptor
858PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
859 assert(!PassRunDescriptorStack.empty() &&
"empty PassRunDescriptorStack");
860 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
861 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
869 if (!ParentPath.empty()) {
873 " to support -ir-dump-directory: " + EC.message());
880 " to support -ir-dump-directory: " + EC.message());
885 if (isIgnored(PassID))
892 if (shouldPrintAfterPass(PassID))
893 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
895 if (!shouldPrintIR(
IR))
900 if (shouldPrintPassNumbers())
901 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
902 <<
" on " << getIRName(
IR) <<
"\n";
904 if (shouldPrintAfterCurrentPassNumber())
905 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
907 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
910 auto WriteIRToStream = [&](raw_ostream &Stream) {
911 Stream <<
"; *** IR Dump Before ";
912 if (shouldPrintBeforeSomePassNumber())
913 Stream << CurrentPassNumber <<
"-";
914 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
915 unwrapAndPrint(Stream,
IR);
919 std::string DumpIRFilename =
921 IRDumpFileSuffixType::Before);
922 llvm::raw_fd_ostream DumpIRFileStream{
924 WriteIRToStream(DumpIRFileStream);
926 WriteIRToStream(
dbgs());
931 if (isIgnored(PassID))
934 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
937 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
938 popPassRunDescriptor(PassID);
939 assert(StoredPassID == PassID &&
"mismatched PassID");
941 if (!shouldPrintIR(
IR) ||
942 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
945 auto WriteIRToStream = [&](raw_ostream &Stream,
const StringRef IRName) {
946 Stream <<
"; *** IR Dump After ";
947 if (shouldPrintAfterSomePassNumber())
948 Stream << CurrentPassNumber <<
"-";
949 Stream << StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
950 unwrapAndPrint(Stream,
IR);
954 std::string DumpIRFilename =
956 IRDumpFileSuffixType::After);
957 llvm::raw_fd_ostream DumpIRFileStream{
960 WriteIRToStream(DumpIRFileStream, IRName);
962 WriteIRToStream(
dbgs(), IRName);
966void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
967 if (isIgnored(PassID))
970 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
973 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
974 popPassRunDescriptor(PassID);
975 assert(StoredPassID == PassID &&
"mismatched PassID");
979 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
982 auto WriteIRToStream = [&](raw_ostream &Stream,
const Module *
M,
983 const StringRef IRName) {
984 SmallString<20> Banner;
985 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
987 Stream << Banner <<
"\n";
992 std::string DumpIRFilename =
993 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
994 IRDumpFileSuffixType::Invalidated);
995 llvm::raw_fd_ostream DumpIRFileStream{
998 WriteIRToStream(DumpIRFileStream, M, IRName);
1000 WriteIRToStream(
dbgs(), M, IRName);
1004bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
1008 StringRef
PassName = PIC->getPassNameForClassName(PassID);
1012bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
1016 StringRef
PassName = PIC->getPassNameForClassName(PassID);
1020bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
1021 return shouldPrintBeforeSomePassNumber() &&
1025bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
1026 return shouldPrintAfterSomePassNumber() &&
1030bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1034bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1038bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1049 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1056 PIC.registerAfterPassCallback(
1058 this->printAfterPass(
P,
IR);
1060 PIC.registerAfterPassInvalidatedCallback(
1062 this->printAfterPassInvalidated(
P);
1069 PIC.registerShouldRunOptionalPassCallback(
1074 bool ShouldRun =
true;
1076 ShouldRun = !
F->hasOptNone();
1078 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1082 if (!ShouldRun && DebugLogging) {
1083 errs() <<
"Skipping pass " << PassID <<
" on " << getIRName(
IR)
1084 <<
" due to optnone attribute\n";
1094 Context.getOptPassGate().shouldRunPass(
PassName, getIRName(
IR));
1098 this->HasWrittenIR =
true;
1099 const Module *M = unwrapModule(
IR,
true);
1100 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1105 M->print(OS,
nullptr);
1112 const OptPassGate &PassGate = Context.getOptPassGate();
1116 PIC.registerShouldRunOptionalPassCallback(
1138 std::vector<StringRef> SpecialPasses;
1139 if (!Opts.Verbose) {
1140 SpecialPasses.emplace_back(
"PassManager");
1141 SpecialPasses.emplace_back(
"PassAdaptor");
1144 PIC.registerBeforeSkippedPassCallback([
this, SpecialPasses](
StringRef PassID,
1147 "Unexpectedly skipping special pass");
1149 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1151 PIC.registerBeforeNonSkippedPassCallback(
1157 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1159 unsigned Count =
F->getInstructionCount();
1160 OS <<
" (" <<
Count <<
" instruction";
1166 OS <<
" (" <<
Count <<
" node";
1174 PIC.registerAfterPassCallback(
1182 PIC.registerAfterPassInvalidatedCallback(
1190 if (!Opts.SkipAnalyses) {
1192 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1196 PIC.registerAfterAnalysisCallback(
1198 PIC.registerAnalysisInvalidatedCallback([
this](
StringRef PassID,
1200 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1203 PIC.registerAnalysesClearedCallback([
this](
StringRef IRName) {
1204 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1210 bool TrackBBLifetime) {
1211 if (TrackBBLifetime)
1213 for (
const auto &BB : *
F) {
1215 BBGuards->try_emplace(intptr_t(&BB), &BB);
1219 BBGuards->try_emplace(intptr_t(Succ), Succ);
1226 out << BB->
getName() <<
"<" << BB <<
">";
1231 out <<
"unnamed_removed<" << BB <<
">";
1237 <<
"<" << BB <<
">";
1241 unsigned FuncOrderBlockNum = 0;
1245 FuncOrderBlockNum++;
1247 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1255 out <<
"Some blocks were deleted\n";
1260 if (Before.
Graph.size() != After.
Graph.size())
1261 out <<
"Different number of non-leaf basic blocks: before="
1262 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1264 for (
auto &BB : Before.
Graph) {
1265 auto BA = After.
Graph.find(BB.first);
1266 if (BA == After.
Graph.end()) {
1267 out <<
"Non-leaf block ";
1269 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1273 for (
auto &BA : After.
Graph) {
1274 auto BB = Before.
Graph.find(BA.first);
1275 if (BB == Before.
Graph.end()) {
1276 out <<
"Non-leaf block ";
1278 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1282 if (BB->second == BA.second)
1285 out <<
"Different successors of block ";
1287 out <<
" (unordered):\n";
1288 out <<
"- before (" << BB->second.size() <<
"): ";
1289 for (
auto &SuccB : BB->second) {
1291 if (SuccB.second != 1)
1292 out <<
"(" << SuccB.second <<
"), ";
1297 out <<
"- after (" << BA.second.size() <<
"): ";
1298 for (
auto &SuccA : BA.second) {
1300 if (SuccA.second != 1)
1301 out <<
"(" << SuccA.second <<
"), ";
1372 FunctionAnalysisManager::Invalidator &) {
1382 Functions.push_back(
const_cast<Function *
>(MaybeF));
1385 Functions.push_back(&
F);
1395 bool Registered =
false;
1396 PIC.registerBeforeNonSkippedPassCallback([
this, &
MAM,
1399#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1400 assert(&PassStack.emplace_back(
P));
1405 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1421 auto &M = *
const_cast<Module *
>(MPtr);
1426 PIC.registerAfterPassInvalidatedCallback(
1428#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1429 assert(PassStack.pop_back_val() ==
P &&
1430 "Before and After callbacks must correspond");
1437#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1438 assert(PassStack.pop_back_val() ==
P &&
1439 "Before and After callbacks must correspond");
1447 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1451 if (
auto *HashBefore =
1455 "Function @{0} changed by {1} without invalidating analyses",
1461 const CFG &GraphBefore,
const CFG &GraphAfter) {
1462 if (GraphAfter == GraphBefore)
1466 <<
"Error: " <<
Pass
1467 <<
" does not invalidate CFG analyses but CFG changes detected in "
1469 << FuncName <<
":\n";
1474 if (
auto *GraphBefore =
1476 CheckCFG(
P,
F->getName(), *GraphBefore,
1480 auto &M = *
const_cast<Module *
>(MPtr);
1481 if (
auto *HashBefore =
1485 "Module changed by {0} without invalidating analyses",
P));
1494 PIC.registerAfterPassCallback(
1496 if (isIgnored(
P) ||
P ==
"VerifierPass")
1501 F = L->getHeader()->getParent();
1506 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1510 "\"{0}\", compilation aborted!",
1516 M =
C->begin()->getFunction().getParent();
1521 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1525 "\"{0}\", compilation aborted!",
1531 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1532 std::string Banner =
1533 formatv(
"Broken machine function found after pass "
1534 "\"{0}\", compilation aborted!",
1564 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID, Name);
1568 [&](
bool InModule,
unsigned Minor,
1572 Minor, Before, After);
1583 Out <<
"\n*** IR for function " << Name <<
" ***\n";
1590 const std::string Removed =
1591 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1592 const std::string Added =
UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1593 const std::string NoChange =
" %l\n";
1612 PIC.registerBeforeNonSkippedPassCallback(
1614 PIC.registerAfterPassCallback(
1616 this->runAfterPass();
1619 PIC.registerAfterPassInvalidatedCallback(
1622 PIC.registerBeforeAnalysisCallback(
1624 PIC.registerAfterAnalysisCallback(
1637class DotCfgDiffDisplayGraph;
1640class DisplayElement {
1643 StringRef getColour()
const {
return Colour; }
1646 DisplayElement(StringRef Colour) : Colour(Colour) {}
1647 const StringRef Colour;
1652class DisplayEdge :
public DisplayElement {
1654 DisplayEdge(std::string
Value, DisplayNode &Node, StringRef Colour)
1659 const DisplayNode &getDestinationNode()
const {
return Node; }
1663 const DisplayNode &
Node;
1667class DisplayNode :
public DisplayElement {
1671 DisplayNode(std::string Content, StringRef Colour)
1672 : DisplayElement(Colour), Content(Content) {}
1675 using ChildIterator = SmallPtrSet<DisplayNode *, 0>::const_iterator;
1676 ChildIterator children_begin()
const {
return Children.begin(); }
1677 ChildIterator children_end()
const {
return Children.end(); }
1680 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1681 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1682 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1685 void createEdge(StringRef
Value, DisplayNode &Node, StringRef Colour);
1688 std::string getContent()
const {
return Content; }
1691 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1692 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1693 return *EdgeMap.find(&To)->second;
1698 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1699 return getEdge(Sink).getValue();
1702 void createEdgeMap();
1705 const std::string Content;
1710 std::vector<DisplayEdge> Edges;
1712 std::vector<DisplayEdge *> EdgePtrs;
1713 SmallPtrSet<DisplayNode *, 0>
Children;
1714 DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
1717 bool AllEdgesCreated =
false;
1721class DotCfgDiffDisplayGraph {
1723 DotCfgDiffDisplayGraph(std::string Name) : GraphName(
Name) {}
1726 void generateDotFile(StringRef DotFile);
1729 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1730 NodeIterator nodes_begin()
const {
1731 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1732 return NodePtrs.cbegin();
1734 NodeIterator nodes_end()
const {
1735 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1736 return NodePtrs.cend();
1741 void setEntryNode(
unsigned N) {
1743 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1744 NodeGenerationComplete =
true;
1745 for (
auto &
N : Nodes)
1746 NodePtrs.emplace_back(&
N);
1748 EntryNode = NodePtrs[
N];
1752 void createNode(std::string
C, StringRef Colour) {
1753 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1754 Nodes.emplace_back(
C, Colour);
1758 assert(
N < Nodes.size() &&
"Node is out of bounds");
1761 unsigned size()
const {
1762 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1763 return Nodes.size();
1767 std::string getGraphName()
const {
return GraphName; }
1771 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1772 return Node.getContent();
1776 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1777 return attribute(
Node.getColour());
1781 std::string getEdgeColorAttr(
const DisplayNode &From,
1782 const DisplayNode &To)
const {
1783 return attribute(From.getEdge(To).getColour());
1787 DisplayNode *getEntryNode()
const {
1788 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1794 std::string attribute(StringRef Colour)
const {
1795 return "color=" + Colour.
str();
1798 bool NodeGenerationComplete =
false;
1799 const std::string GraphName;
1800 std::vector<DisplayNode> Nodes;
1801 std::vector<DisplayNode *> NodePtrs;
1802 DisplayNode *EntryNode =
nullptr;
1805void DisplayNode::createEdge(StringRef
Value, DisplayNode &Node,
1807 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1808 Edges.emplace_back(
Value.str(), Node, Colour);
1812void DisplayNode::createEdgeMap() {
1815 AllEdgesCreated =
true;
1816 for (
auto &
E : Edges)
1817 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1820class DotCfgDiffNode;
1824class DotCfgDiffNode {
1826 DotCfgDiffNode() =
delete;
1830 DotCfgDiffNode(DotCfgDiff &
G,
unsigned N,
const BlockDataT<DCData> &BD,
1832 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1833 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1838 unsigned getIndex()
const {
return N; }
1841 StringRef getLabel()
const {
1842 assert(
Data[0] &&
"Expected Data[0] to be set.");
1843 return Data[0]->getLabel();
1846 StringRef getColour()
const {
return Colour; }
1849 void setCommon(
const BlockDataT<DCData> &
Other) {
1850 assert(!
Data[1] &&
"Expected only one block datum");
1855 void addEdge(
unsigned E, StringRef
Value, StringRef Colour) {
1858 "Unexpected edge count and color.");
1859 EdgesMap[
E] = {
Value.str(), Colour};
1865 StringRef getEdgeColour(
const unsigned S)
const {
1866 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1867 return EdgesMap.at(S).second;
1871 std::string getBodyContent()
const;
1873 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1874 std::map<const unsigned, unsigned> &NodeMap)
const;
1879 const BlockDataT<DCData> *
Data[2];
1881 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1883 std::vector<unsigned> Edges;
1893 DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1894 const FuncDataT<DCData> &After);
1896 DotCfgDiff(
const DotCfgDiff &) =
delete;
1897 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1899 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1900 StringRef EntryNodeName);
1906 StringRef getEdgeSourceLabel(
const unsigned &Source,
1907 const unsigned &Sink)
const {
1909 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1910 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1911 return EdgeLabels.find(S)->getValue();
1915 unsigned size()
const {
return Nodes.size(); }
1917 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1918 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1924 std::string colourize(std::string S, StringRef Colour)
const;
1926 void createNode(StringRef Label,
const BlockDataT<DCData> &BD, StringRef
C) {
1927 unsigned Pos = Nodes.size();
1928 Nodes.emplace_back(*
this, Pos, BD,
C);
1929 NodePosition.insert({
Label, Pos});
1935 std::vector<DotCfgDiffNode> Nodes;
1936 StringMap<unsigned> NodePosition;
1937 const std::string GraphName;
1939 StringMap<std::string> EdgeLabels;
1942std::string DotCfgDiffNode::getBodyContent()
const {
1944 assert(
Data[1] &&
"Expected Data[1] to be set.");
1947 for (
unsigned I = 0;
I < 2; ++
I) {
1948 SR[
I] =
Data[
I]->getBody();
1952 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1955 SmallString<80> OldLineFormat =
formatv(
1956 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1957 SmallString<80> NewLineFormat =
formatv(
1958 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1959 SmallString<80> UnchangedLineFormat =
formatv(
1960 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1961 std::string Diff =
Data[0]->getLabel().str();
1962 Diff +=
":\n<BR align=\"left\"/>" +
1963 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1964 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1969 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1972 std::string S =
R.sub(
"", Diff, &
Error);
1983 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1984 std::string Body = makeHTMLReady(
Data[0]->getBody());
1985 const StringRef BS = Body;
1988 if (BS.
front() ==
'\n')
1993 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1995 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1998 while (BS1.
size()) {
1999 S.append(
"<BR align=\"left\"/>");
2001 S.append(
Line.str());
2004 S.append(
"<BR align=\"left\"/></FONT>");
2008std::string DotCfgDiff::colourize(std::string S, StringRef Colour)
const {
2009 if (S.length() == 0)
2011 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
2014DotCfgDiff::DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
2015 const FuncDataT<DCData> &After)
2016 : GraphName(Title.str()) {
2017 StringMap<StringRef> EdgesMap;
2021 StringRef Label = B.getKey();
2022 const BlockDataT<DCData> &BD = B.getValue();
2023 createNode(Label, BD, BeforeColour);
2027 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
2028 E = BD.getData().end();
2029 Sink != E; ++Sink) {
2030 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
2031 BD.getData().getSuccessorLabel(Sink->getKey()).str();
2032 EdgesMap.insert({Key, BeforeColour});
2038 StringRef Label = A.getKey();
2039 const BlockDataT<DCData> &BD = A.getValue();
2040 auto It = NodePosition.find(Label);
2041 if (It == NodePosition.end())
2043 createNode(Label, BD, AfterColour);
2045 Nodes[It->second].setCommon(BD);
2047 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
2048 E = BD.getData().end();
2049 Sink != E; ++Sink) {
2050 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
2051 BD.getData().getSuccessorLabel(Sink->getKey()).str();
2052 auto [It, Inserted] = EdgesMap.try_emplace(Key, AfterColour);
2054 It->second = CommonColour;
2059 for (
auto &
E : EdgesMap) {
2062 auto SP1 = S.
rsplit(
' ');
2063 auto &SourceSink = SP1.first;
2064 auto SP2 = SourceSink.split(
' ');
2069 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2070 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2071 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2072 unsigned SinkNode = NodePosition[
Sink];
2076 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2078 It->getValue() = colourize(
Value.str(), Colour);
2081 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2083 It->getValue() =
NV;
2085 SourceNode.addEdge(SinkNode,
Value, Colour);
2087 for (
auto &
I : Nodes)
2091DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2093 assert(NodePosition.count(EntryNodeName) == 1 &&
2094 "Expected to find entry block in map.");
2095 unsigned Entry = NodePosition[EntryNodeName];
2096 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2097 DotCfgDiffDisplayGraph
G(Title.
str());
2099 std::map<const unsigned, unsigned> NodeMap;
2101 int EntryIndex = -1;
2103 for (
auto &
I : Nodes) {
2104 if (
I.getIndex() == Entry)
2106 G.createNode(
I.getBodyContent(),
I.getColour());
2107 NodeMap.insert({
I.getIndex(),
Index++});
2109 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2110 G.setEntryNode(EntryIndex);
2112 for (
auto &
I : NodeMap) {
2113 unsigned SourceNode =
I.first;
2114 unsigned DisplayNode =
I.second;
2115 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2120void DotCfgDiffNode::createDisplayEdges(
2121 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2122 std::map<const unsigned, unsigned> &NodeMap)
const {
2124 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2126 for (
auto I : Edges) {
2127 unsigned SinkNodeIndex =
I;
2128 StringRef Colour = getEdgeColour(SinkNodeIndex);
2129 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2131 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2132 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2133 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2135 SourceDisplayNode.createEdgeMap();
2138void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2139 for (
auto E : EdgesMap) {
2141 Edges.emplace_back(
E.first);
2157 return G->getEntryNode();
2160 return N->children_begin();
2164 return G->nodes_begin();
2167 return G->nodes_end();
2170 return N->edges_begin();
2174 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2184 return DiffData->getGraphName();
2188 return "\tsize=\"190, 190\";\n";
2191 const DotCfgDiffDisplayGraph *DiffData) {
2192 return DiffData->getNodeLabel(*
Node);
2195 const DotCfgDiffDisplayGraph *DiffData) {
2196 return DiffData->getNodeAttributes(*
Node);
2199 DisplayNode::ChildIterator &To) {
2200 return From->getEdgeSourceLabel(**To);
2203 DisplayNode::ChildIterator &To,
2204 const DotCfgDiffDisplayGraph *DiffData) {
2205 return DiffData->getEdgeColorAttr(*From, **To);
2213void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
2215 raw_fd_ostream OutStream(DotFile, EC);
2217 errs() <<
"Error: " <<
EC.message() <<
"\n";
2238 for (
auto &
C : Sw->cases()) {
2239 assert(
C.getCaseValue() &&
"Expected to find case value.");
2260 assert(
HTML &&
"Expected outstream to be set");
2265 Extender =
formatv(
"{0}_{1}",
N, Minor);
2274 std::string DotFile =
Twine(SV).
str();
2282 DotCfgDiff Diff(
Text, Before, After);
2285 if (EntryBlockName ==
"")
2287 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2289 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2290 DG.generateDotFile(DotFile);
2295 errs() <<
"Error: " << EC.message() <<
"\n";
2304 return "Unable to find dot executable.";
2309 return "Error executing system dot.";
2313 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2318 assert(
HTML &&
"Expected outstream to be set");
2319 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2320 <<
"Initial IR (by function)</button>\n"
2321 <<
"<div class=\"content\">\n"
2330 [&](
bool InModule,
unsigned Minor,
2334 Minor, Before, After);
2348 assert(
HTML &&
"Expected outstream to be set");
2350 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2351 N, makeHTMLReady(PassID), Name);
2360 assert(
HTML &&
"Expected outstream to be set");
2363 [&](
bool InModule,
unsigned Minor,
2367 Minor, Before, After);
2369 *
HTML <<
" </p></div>\n";
2374 assert(
HTML &&
"Expected outstream to be set");
2376 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2382 assert(
HTML &&
"Expected outstream to be set");
2384 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2385 makeHTMLReady(PassID), Name);
2391 assert(
HTML &&
"Expected outstream to be set");
2393 makeHTMLReady(PassID), Name);
2400 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2406 *
HTML <<
"<!doctype html>"
2409 <<
"<style>.collapsible { "
2410 <<
"background-color: #777;"
2412 <<
" cursor: pointer;"
2413 <<
" padding: 18px;"
2416 <<
" text-align: left;"
2417 <<
" outline: none;"
2418 <<
" font-size: 15px;"
2419 <<
"} .active, .collapsible:hover {"
2420 <<
" background-color: #555;"
2422 <<
" padding: 0 18px;"
2423 <<
" display: none;"
2424 <<
" overflow: hidden;"
2425 <<
" background-color: #f1f1f1;"
2428 <<
"<title>passes.html</title>"
2438 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2440 <<
"for (i = 0; i < coll.length; i++) {"
2441 <<
"coll[i].addEventListener(\"click\", function() {"
2442 <<
" this.classList.toggle(\"active\");"
2443 <<
" var content = this.nextElementSibling;"
2444 <<
" if (content.style.display === \"block\"){"
2445 <<
" content.style.display = \"none\";"
2448 <<
" content.style.display= \"block\";"
2466 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2472 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2477 LLVMContext &Context,
bool DebugLogging,
bool VerifyEach,
2479 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2480 OptPassGate(Context),
2488 VerifyEach(VerifyEach) {}
2505void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2512 "Did not expect to get here without option set.");
2521 "Did not expect to get here without option set.");
2522 CrashReporter =
nullptr;
2531 CrashReporter =
this;
2533 PIC.registerBeforeNonSkippedPassCallback(
2537 OS <<
formatv(
"; *** Dump of {0}IR Before Last Pass {1}",
2540 OS <<
" Filtered Out ***\n";
2543 OS <<
" Started ***\n";
2544 unwrapAndPrint(OS,
IR);
2550 PrintIR.registerCallbacks(
PIC);
2551 PrintPass.registerCallbacks(
PIC);
2552 TimePasses.registerCallbacks(
PIC);
2553 OptNone.registerCallbacks(
PIC);
2554 OptPassGate.registerCallbacks(
PIC);
2555 PrintChangedIR.registerCallbacks(
PIC);
2556 PseudoProbeVerification.registerCallbacks(
PIC);
2558 Verify.registerCallbacks(
PIC,
MAM);
2559 PrintChangedDiff.registerCallbacks(
PIC);
2560 WebsiteChangeReporter.registerCallbacks(
PIC);
2561 ChangeTester.registerCallbacks(
PIC);
2562 PrintCrashIR.registerCallbacks(
PIC);
2563 DroppedStatsIR.registerCallbacks(
PIC);
2565 PreservedCFGChecker.registerCallbacks(
PIC, *
MAM);
2573 TimeProfilingPasses.registerCallbacks(
PIC);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
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 constexpr Value * getValue(Ty &ValueOrUse)
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)
static constexpr StringLiteral Filename
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
PassInstrumentationCallbacks PIC
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
verify safepoint Safepoint IR Verifier
This file defines the SmallPtrSet class.
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< bool > DroppedVarStats("dropped-variable-stats", cl::Hidden, cl::desc("Dump dropped debug variables stats"), cl::init(false))
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::list< unsigned > PrintBeforePassNumber("print-before-pass-number", cl::CommaSeparated, cl::Hidden, cl::desc("Print IR before the passes with specified numbers as " "reported by print-pass-numbers"))
static cl::opt< bool > VerifyAnalysisInvalidation("verify-analysis-invalidation", cl::Hidden, cl::init(false))
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
static SmallVector< Function *, 1 > GetFunctions(IRUnitRef IR)
static void printBBName(raw_ostream &out, const BasicBlock *BB)
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
static bool shouldGenerateData(const Function &F)
static cl::list< unsigned > PrintAfterPassNumber("print-after-pass-number", cl::CommaSeparated, cl::Hidden, cl::desc("Print IR after the passes with specified numbers as " "reported by print-pass-numbers"))
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 void writeIRFileDisplayName(raw_ostream &ResultStream, IRUnitRef IR)
static std::string getIRFileDisplayName(IRUnitRef IR)
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 <aparticular IR unit>" (e....
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI bool isEntryBlock() const
Return true if this is the entry block of the containing function.
Represents analyses that only rely on functions' control flow.
virtual void handleFiltered(StringRef PassID, std::string &Name)=0
virtual void handleInitialIR(IRUnitRef IR)=0
virtual void generateIRRepresentation(IRUnitRef IR, StringRef PassID, IRUnitT &Output)=0
virtual void handleIgnored(StringRef PassID, std::string &Name)=0
void handleIRAfterPass(IRUnitRef IR, StringRef PassID, StringRef PassName)
void saveIRBeforePass(IRUnitRef IR, StringRef PassID, StringRef PassName)
virtual void handleAfter(StringRef PassID, std::string &Name, const IRUnitT &Before, const IRUnitT &After, IRUnitRef)=0
virtual void handleInvalidated(StringRef PassID)=0
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
virtual void omitAfter(StringRef PassID, std::string &Name)=0
std::vector< BeforeIR > BeforeStack
void handleInvalidatedPass(StringRef PassID)
ChangeReporter(bool RunInVerboseMode)
virtual ~ChangeReporter()
Conditional Branch instruction.
void addSuccessorLabel(StringRef Succ, StringRef Label)
LLVM_ABI DCData(const BasicBlock &B)
void generateIRRepresentation(IRUnitRef IR, StringRef PassID, IRDataT< DCData > &Output) override
std::unique_ptr< raw_fd_ostream > HTML
void handleInvalidated(StringRef PassID) override
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, IRUnitRef) 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 handleInitialIR(IRUnitRef IR) 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.
std::string getEntryBlockName() const
bool hasOptNone() const
Do not optimize this function (-O0).
~IRChangedPrinter() override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, IRUnitRef) override
void generateIRRepresentation(IRUnitRef 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, IRUnitRef) override
void omitAfter(StringRef PassID, std::string &Name) override
void handleInvalidated(StringRef PassID) override
void handleIR(const std::string &IR, StringRef PassID)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleFiltered(StringRef PassID, std::string &Name) override
~IRChangedTester() override
void handleInitialIR(IRUnitRef IR) override
const IRDataT< T > & Before
static bool generateFunctionData(IRDataT< T > &Data, const FunctionT &F)
static void analyzeIR(IRUnitRef IR, IRDataT< T > &Data)
const IRDataT< T > & After
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
A type-erased reference to the IR unit a pass or analysis is running on, together with the kind of IR...
void generateIRRepresentation(IRUnitRef IR, StringRef PassID, IRDataT< EmptyData > &Output) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~InLineChangePrinter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, IRUnitRef) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)
This is an important class for using LLVM in a threaded context.
A node in the call graph.
An SCC of the call graph.
Represents a single loop in the control flow graph.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
Representation of each machine instruction.
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI bool shouldRun(StringRef PassName, IRUnitRef 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().
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 registerBeforeNonSkippedPassCallback(CallableT C)
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.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
LLVM_ABI void reportCrashIR()
LLVM_ABI ~PrintCrashIRInstrumentation()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI ~PrintIRInstrumentation()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)
LLVM_ABI StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef drop_until(function_ref< bool(char)> F) const
Return a StringRef equal to 'this', but with all characters not satisfying the given predicate droppe...
constexpr size_t size() const
Get the string size.
char front() const
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.
bool consume_front(char Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
void handleInvalidated(StringRef PassID) override
void handleInitialIR(IRUnitRef IR) 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
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI TimeProfilingPassesHandler()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI 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.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM)
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
LLVM_ABI 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...
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
LLVM_ABI void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
LLVM_ABI void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
LLVM_ABI 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.
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie, bool NeedsPOSIXUtilitySignalHandling=false)
Add a function to be called when an abort/kill signal is delivered to the process.
LLVM_ABI ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
LLVM_ABI 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.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool isSourceLocInPrintList(const DebugLoc &Loc)
LLVM_ABI 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.
LLVM_ABI bool forcePrintModuleIR()
LLVM_ABI std::vector< std::string > printAfterPasses()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
Inline ArrayRef overloads of the xxhash entry points declared out-of-line in llvm/Support/xxhash....
LLVM_ABI 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)
LLVM_ABI bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)
LLVM_ABI bool shouldPrintBeforeAll()
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI bool shouldPrintAfterAll()
LLVM_ABI cl::opt< ChangePrinter > PrintChanged
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI 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.
LLVM_ABI std::vector< std::string > printBeforePasses()
LLVM_ABI bool shouldPrintBeforeSomePass()
This is a helper to determine whether to print IR before or after a pass.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI bool shouldPrintAfterSomePass()
LLVM_ABI void verifyMachineFunction(const std::string &Banner, const MachineFunction &MF)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool isFunctionInPrintList(StringRef FunctionName)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool isPassInPrintList(StringRef PassName)
LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
LLVM_ABI bool isSourceLocFilterEmpty()
LLVM_ABI void timeTraceProfilerEnd()
Manually end the last time section.
LLVM_ABI bool shouldPrintFunction(const Function &F)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI std::error_code cleanUpTempFiles(ArrayRef< std::string > FileName)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
InnerAnalysisManagerProxy< MachineFunctionAnalysisManager, Module > MachineFunctionAnalysisManagerModuleProxy
LLVM_ABI void printLoop(const Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
LLVM_ABI std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI stable_hash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
LLVM_ABI bool shouldPrintAllFunctions()
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI TimeTraceProfilerEntry * timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
Result run(Function &F, FunctionAnalysisManager &FAM)
Run the analysis pass over a function and produce CFG.
PreservedCFGCheckerInstrumentation::CFG Result
Provide the result type for this analysis pass.
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)
DefaultDOTGraphTraits(bool simple=false)
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 LLVM_ABI void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
LLVM_ABI CFG(const Function *F, bool TrackBBLifetime)
LLVM_ABI bool invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &)
DenseMap< const BasicBlock *, DenseMap< const BasicBlock *, unsigned > > Graph
bool Indent
Indent based on hierarchy.