52#ifdef EXPENSIVE_CHECKS
64 cl::desc(
"Print before passes that change them"),
71 cl::desc(
"system dot used by change reporters"));
99 cl::desc(
"Generate dot files into specified directory for changed IRs"),
104 "print-on-crash-path",
105 cl::desc(
"Print the last form of the IR before crash to a file"),
110 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
114 "opt-bisect-print-ir-path",
119 cl::desc(
"Print pass names and their ordinals"));
123 cl::desc(
"Print IR before the passes with specified numbers as "
124 "reported by print-pass-numbers"));
128 cl::desc(
"Print IR after the passes with specified numbers as "
129 "reported by print-pass-numbers"));
133 cl::desc(
"If specified, IR printed using the "
134 "-print-[before|after]{-all} options will be dumped into "
135 "files in this directory rather than written to stderr"),
140 cl::desc(
"Dump dropped debug variables stats"),
145 return IRPtr ? *IRPtr :
nullptr;
159 cl::desc(
"exe called with module IR after each pass that "
164const Module *unwrapModule(
const Any &
IR,
bool Force =
false) {
172 return F->getParent();
179 return F.getParent();
182 assert(!Force &&
"Expected a module");
187 const Function *
F =
L->getHeader()->getParent();
190 return F->getParent();
196 return MF->getFunction().getParent();
210 M->print(OS,
nullptr);
212 for (
const auto &
F : M->functions()) {
228 const Function *
F = L->getHeader()->getParent();
240std::string getIRName(
const Any &
IR) {
245 return F->getName().str();
251 return "loop %" + L->getName().str() +
" in function " +
252 L->getHeader()->getParent()->getName().str();
260bool moduleContainsFilterPrintFunc(
const Module &M) {
261 return any_of(M.functions(),
263 return isFunctionInPrintList(F.getName());
276bool shouldPrintIR(
const Any &
IR) {
278 return moduleContainsFilterPrintFunc(*M);
284 return sccContainsFilterPrintFunc(*
C);
297 if (!shouldPrintIR(
IR))
301 auto *M = unwrapModule(
IR);
302 assert(M &&
"should have unwrapped module");
337 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
338 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
339 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
340 "PrintMIRPreparePass",
"RequireAnalysisPass",
341 "InvalidateAnalysisPass"});
349 S.append(Clean.
str());
353 S.append(SR[0] ==
'<' ?
"<" :
">");
360const Module *getModuleForComparison(
const Any &
IR) {
364 return C->begin()->getFunction().getParent();
368bool isInterestingFunction(
const Function &
F) {
378 return isInterestingFunction(*
F);
416 std::string Name = getIRName(
IR);
418 if (isIgnored(PassID)) {
432 if (Before == After) {
457 PIC.registerBeforeNonSkippedPassCallback(
462 PIC.registerAfterPassCallback(
466 PIC.registerAfterPassInvalidatedCallback(
480 auto *M = unwrapModule(
IR,
true);
481 assert(M &&
"Expected module to be unwrapped when forced.");
482 Out <<
"*** IR Dump At Start ***\n";
483 M->print(
Out,
nullptr);
488 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
494 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
501 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);
507 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID, Name);
519 std::string &Output) {
521 unwrapAndPrint(OS,
IR);
526 const std::string &Before,
527 const std::string &After,
const Any &) {
530 Out <<
"*** IR Dump Before " << PassID <<
" on " << Name <<
" ***\n"
536 Out <<
"*** IR Deleted After " << PassID <<
" on " << Name <<
" ***\n";
540 Out <<
"*** IR Dump After " << PassID <<
" on " << Name <<
" ***\n" << After;
546 if (TestChanged !=
"")
556 dbgs() <<
"Unable to create temporary file.";
561 dbgs() <<
"Unable to find test-changed executable.";
565 StringRef Args[] = {TestChanged, FileName[0], PassID};
568 dbgs() <<
"Error executing test-changed executable.";
573 dbgs() <<
"Unable to remove temporary file.";
589 const std::string &Before,
590 const std::string &After,
const Any &) {
598 const auto &BFD = Before.
getData();
599 const auto &AFD = After.
getData();
600 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
601 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
602 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
603 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
605 auto HandlePotentiallyRemovedData = [&](std::string S) {
609 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
612 auto HandleNewData = [&](std::vector<const T *> &Q) {
614 for (
const T *NBI : Q)
615 HandlePair(
nullptr, NBI);
628 std::vector<const T *> NewDataQueue;
630 if (!BFD.count(*AI)) {
633 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
642 while (BI != BE && *BI != *AI) {
643 HandlePotentiallyRemovedData(*BI);
647 HandleNewData(NewDataQueue);
649 const T &AData = AFD.find(*AI)->getValue();
650 const T &BData = BFD.find(*AI)->getValue();
651 HandlePair(&BData, &AData);
659 HandlePotentiallyRemovedData(*BI);
663 HandleNewData(NewDataQueue);
669 std::function<
void(
bool InModule,
unsigned Minor,
672 if (!CompareModule) {
675 "Expected only one function.");
676 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
677 After.getData().begin()->getValue());
685 assert((
B ||
A) &&
"Both functions cannot be missing.");
690 CompareFunc(
true, Minor++, *
B, *
A);
696 if (
const Module *M = getModuleForComparison(
IR)) {
709 auto *
F = L->getHeader()->getParent();
731template <
typename FunctionT>
736 for (
const auto &
B :
F) {
737 std::string BBName =
B.getName().str();
738 if (BBName.empty()) {
745 Data.getOrder().emplace_back(
F.getName());
746 Data.getData().insert({
F.getName(), FD});
753 assert(PassRunDescriptorStack.empty() &&
754 "PassRunDescriptorStack is not empty at exit");
758 const Module *M = unwrapModule(
IR,
true);
759 assert(M &&
"should have unwrapped module");
761 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
764 ResultStream <<
"-module";
766 ResultStream <<
"-function-";
771 ResultStream <<
"-scc-";
775 ResultStream <<
"-loop-";
779 ResultStream <<
"-machine-function-";
795StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
796 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
798 return FileSuffixes[
static_cast<size_t>(
Type)];
801std::string PrintIRInstrumentation::fetchDumpFilename(
803 IRDumpFileSuffixType SuffixType) {
805 "The flag -ir-dump-directory must be passed to dump IR to files");
808 raw_svector_ostream FilenameStream(
Filename);
809 FilenameStream << PassNumber;
810 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
812 FilenameStream << getFileSuffix(SuffixType);
814 SmallString<128> ResultPath;
816 return std::string(ResultPath);
819void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
821 unsigned PassNumber) {
824 getIRName(
IR), PassID);
827PrintIRInstrumentation::PassRunDescriptor
828PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
829 assert(!PassRunDescriptorStack.empty() &&
"empty PassRunDescriptorStack");
830 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
831 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
839 if (!ParentPath.empty()) {
843 " to support -ir-dump-directory: " + EC.message());
850 " to support -ir-dump-directory: " + EC.message());
854void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
const Any &
IR) {
855 if (isIgnored(PassID))
862 if (shouldPrintAfterPass(PassID))
863 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
865 if (!shouldPrintIR(
IR))
870 if (shouldPrintPassNumbers())
871 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
872 <<
" on " << getIRName(
IR) <<
"\n";
874 if (shouldPrintAfterCurrentPassNumber())
875 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
877 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
880 auto WriteIRToStream = [&](raw_ostream &Stream) {
881 Stream <<
"; *** IR Dump Before ";
882 if (shouldPrintBeforeSomePassNumber())
883 Stream << CurrentPassNumber <<
"-";
884 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
885 unwrapAndPrint(Stream,
IR);
889 std::string DumpIRFilename =
891 IRDumpFileSuffixType::Before);
892 llvm::raw_fd_ostream DumpIRFileStream{
894 WriteIRToStream(DumpIRFileStream);
896 WriteIRToStream(
dbgs());
900void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
const Any &
IR) {
901 if (isIgnored(PassID))
904 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
907 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
908 popPassRunDescriptor(PassID);
909 assert(StoredPassID == PassID &&
"mismatched PassID");
911 if (!shouldPrintIR(
IR) ||
912 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
915 auto WriteIRToStream = [&](raw_ostream &Stream,
const StringRef IRName) {
916 Stream <<
"; *** IR Dump After ";
917 if (shouldPrintAfterSomePassNumber())
918 Stream << CurrentPassNumber <<
"-";
919 Stream << StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
920 unwrapAndPrint(Stream,
IR);
924 std::string DumpIRFilename =
926 IRDumpFileSuffixType::After);
927 llvm::raw_fd_ostream DumpIRFileStream{
930 WriteIRToStream(DumpIRFileStream, IRName);
932 WriteIRToStream(
dbgs(), IRName);
936void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
937 if (isIgnored(PassID))
940 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
943 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
944 popPassRunDescriptor(PassID);
945 assert(StoredPassID == PassID &&
"mismatched PassID");
949 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
952 auto WriteIRToStream = [&](raw_ostream &Stream,
const Module *
M,
953 const StringRef IRName) {
954 SmallString<20> Banner;
955 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
957 Stream << Banner <<
"\n";
962 std::string DumpIRFilename =
963 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
964 IRDumpFileSuffixType::Invalidated);
965 llvm::raw_fd_ostream DumpIRFileStream{
968 WriteIRToStream(DumpIRFileStream, M, IRName);
970 WriteIRToStream(
dbgs(), M, IRName);
974bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
978 StringRef
PassName = PIC->getPassNameForClassName(PassID);
982bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
986 StringRef
PassName = PIC->getPassNameForClassName(PassID);
990bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
991 return shouldPrintBeforeSomePassNumber() &&
995bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
996 return shouldPrintAfterSomePassNumber() &&
1000bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1004bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1008bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1019 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1026 PIC.registerAfterPassCallback(
1028 this->printAfterPass(
P,
IR);
1030 PIC.registerAfterPassInvalidatedCallback(
1032 this->printAfterPassInvalidated(
P);
1039 PIC.registerShouldRunOptionalPassCallback(
1043bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
const Any &
IR) {
1044 bool ShouldRun =
true;
1046 ShouldRun = !
F->hasOptNone();
1048 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1052 if (!ShouldRun && DebugLogging) {
1053 errs() <<
"Skipping pass " << PassID <<
" on " << getIRName(
IR)
1054 <<
" due to optnone attribute\n";
1064 Context.getOptPassGate().shouldRunPass(
PassName, getIRName(
IR));
1068 this->HasWrittenIR =
true;
1069 const Module *M = unwrapModule(
IR,
true);
1070 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1075 M->print(OS,
nullptr);
1082 const OptPassGate &PassGate = Context.getOptPassGate();
1086 PIC.registerShouldRunOptionalPassCallback(
1108 std::vector<StringRef> SpecialPasses;
1109 if (!Opts.Verbose) {
1110 SpecialPasses.emplace_back(
"PassManager");
1111 SpecialPasses.emplace_back(
"PassAdaptor");
1114 PIC.registerBeforeSkippedPassCallback([
this, SpecialPasses](
StringRef PassID,
1117 "Unexpectedly skipping special pass");
1119 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1121 PIC.registerBeforeNonSkippedPassCallback(
1127 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1129 unsigned Count =
F->getInstructionCount();
1130 OS <<
" (" <<
Count <<
" instruction";
1136 OS <<
" (" <<
Count <<
" node";
1144 PIC.registerAfterPassCallback(
1152 PIC.registerAfterPassInvalidatedCallback(
1160 if (!Opts.SkipAnalyses) {
1162 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1166 PIC.registerAfterAnalysisCallback(
1168 PIC.registerAnalysisInvalidatedCallback([
this](
StringRef PassID,
1170 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1173 PIC.registerAnalysesClearedCallback([
this](
StringRef IRName) {
1174 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1180 bool TrackBBLifetime) {
1181 if (TrackBBLifetime)
1183 for (
const auto &BB : *
F) {
1185 BBGuards->try_emplace(intptr_t(&BB), &BB);
1189 BBGuards->try_emplace(intptr_t(Succ), Succ);
1196 out << BB->
getName() <<
"<" << BB <<
">";
1201 out <<
"unnamed_removed<" << BB <<
">";
1207 <<
"<" << BB <<
">";
1211 unsigned FuncOrderBlockNum = 0;
1215 FuncOrderBlockNum++;
1217 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1225 out <<
"Some blocks were deleted\n";
1230 if (Before.
Graph.size() != After.
Graph.size())
1231 out <<
"Different number of non-leaf basic blocks: before="
1232 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1234 for (
auto &BB : Before.
Graph) {
1235 auto BA = After.
Graph.find(BB.first);
1236 if (BA == After.
Graph.end()) {
1237 out <<
"Non-leaf block ";
1239 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1243 for (
auto &BA : After.
Graph) {
1244 auto BB = Before.
Graph.find(BA.first);
1245 if (BB == Before.
Graph.end()) {
1246 out <<
"Non-leaf block ";
1248 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1252 if (BB->second == BA.second)
1255 out <<
"Different successors of block ";
1257 out <<
" (unordered):\n";
1258 out <<
"- before (" << BB->second.size() <<
"): ";
1259 for (
auto &SuccB : BB->second) {
1261 if (SuccB.second != 1)
1262 out <<
"(" << SuccB.second <<
"), ";
1267 out <<
"- after (" << BA.second.size() <<
"): ";
1268 for (
auto &SuccA : BA.second) {
1270 if (SuccA.second != 1)
1271 out <<
"(" << SuccA.second <<
"), ";
1342 FunctionAnalysisManager::Invalidator &) {
1352 Functions.push_back(
const_cast<Function *
>(MaybeF));
1355 Functions.push_back(&
F);
1365 bool Registered =
false;
1366 PIC.registerBeforeNonSkippedPassCallback([
this, &
MAM,
1368 const Any &
IR)
mutable {
1369#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1370 assert(&PassStack.emplace_back(
P));
1375 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1391 auto &M = *
const_cast<Module *
>(MPtr);
1396 PIC.registerAfterPassInvalidatedCallback(
1398#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1399 assert(PassStack.pop_back_val() ==
P &&
1400 "Before and After callbacks must correspond");
1407#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1408 assert(PassStack.pop_back_val() ==
P &&
1409 "Before and After callbacks must correspond");
1417 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1421 if (
auto *HashBefore =
1425 "Function @{0} changed by {1} without invalidating analyses",
1431 const CFG &GraphBefore,
const CFG &GraphAfter) {
1432 if (GraphAfter == GraphBefore)
1436 <<
"Error: " <<
Pass
1437 <<
" does not invalidate CFG analyses but CFG changes detected in "
1439 << FuncName <<
":\n";
1444 if (
auto *GraphBefore =
1446 CheckCFG(
P,
F->getName(), *GraphBefore,
1450 auto &M = *
const_cast<Module *
>(MPtr);
1451 if (
auto *HashBefore =
1455 "Module changed by {0} without invalidating analyses",
P));
1464 PIC.registerAfterPassCallback(
1466 if (isIgnored(
P) ||
P ==
"VerifierPass")
1471 F = L->getHeader()->getParent();
1476 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1480 "\"{0}\", compilation aborted!",
1486 M =
C->begin()->getFunction().getParent();
1491 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1495 "\"{0}\", compilation aborted!",
1501 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1502 std::string Banner =
1503 formatv(
"Broken machine function found after pass "
1504 "\"{0}\", compilation aborted!",
1534 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID, Name);
1538 [&](
bool InModule,
unsigned Minor,
1542 Minor, Before, After);
1553 Out <<
"\n*** IR for function " << Name <<
" ***\n";
1560 const std::string Removed =
1561 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1562 const std::string Added =
UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1563 const std::string NoChange =
" %l\n";
1582 PIC.registerBeforeNonSkippedPassCallback(
1584 PIC.registerAfterPassCallback(
1586 this->runAfterPass();
1589 PIC.registerAfterPassInvalidatedCallback(
1592 PIC.registerBeforeAnalysisCallback(
1594 PIC.registerAfterAnalysisCallback(
1598void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
1608class DotCfgDiffDisplayGraph;
1611class DisplayElement {
1614 StringRef getColour()
const {
return Colour; }
1617 DisplayElement(StringRef Colour) : Colour(Colour) {}
1618 const StringRef Colour;
1623class DisplayEdge :
public DisplayElement {
1625 DisplayEdge(std::string
Value, DisplayNode &Node, StringRef Colour)
1630 const DisplayNode &getDestinationNode()
const {
return Node; }
1634 const DisplayNode &
Node;
1638class DisplayNode :
public DisplayElement {
1642 DisplayNode(std::string Content, StringRef Colour)
1643 : DisplayElement(Colour), Content(Content) {}
1646 using ChildIterator = SmallPtrSet<DisplayNode *, 0>::const_iterator;
1647 ChildIterator children_begin()
const {
return Children.begin(); }
1648 ChildIterator children_end()
const {
return Children.end(); }
1651 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1652 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1653 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1656 void createEdge(StringRef
Value, DisplayNode &Node, StringRef Colour);
1659 std::string getContent()
const {
return Content; }
1662 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1663 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1664 return *EdgeMap.find(&To)->second;
1669 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1670 return getEdge(Sink).getValue();
1673 void createEdgeMap();
1676 const std::string Content;
1681 std::vector<DisplayEdge> Edges;
1683 std::vector<DisplayEdge *> EdgePtrs;
1684 SmallPtrSet<DisplayNode *, 0>
Children;
1685 DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
1688 bool AllEdgesCreated =
false;
1692class DotCfgDiffDisplayGraph {
1694 DotCfgDiffDisplayGraph(std::string Name) : GraphName(
Name) {}
1697 void generateDotFile(StringRef DotFile);
1700 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1701 NodeIterator nodes_begin()
const {
1702 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1703 return NodePtrs.cbegin();
1705 NodeIterator nodes_end()
const {
1706 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1707 return NodePtrs.cend();
1712 void setEntryNode(
unsigned N) {
1714 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1715 NodeGenerationComplete =
true;
1716 for (
auto &
N : Nodes)
1717 NodePtrs.emplace_back(&
N);
1719 EntryNode = NodePtrs[
N];
1723 void createNode(std::string
C, StringRef Colour) {
1724 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1725 Nodes.emplace_back(
C, Colour);
1729 assert(
N < Nodes.size() &&
"Node is out of bounds");
1732 unsigned size()
const {
1733 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1734 return Nodes.size();
1738 std::string getGraphName()
const {
return GraphName; }
1742 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1743 return Node.getContent();
1747 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1748 return attribute(
Node.getColour());
1752 std::string getEdgeColorAttr(
const DisplayNode &From,
1753 const DisplayNode &To)
const {
1754 return attribute(From.getEdge(To).getColour());
1758 DisplayNode *getEntryNode()
const {
1759 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1765 std::string attribute(StringRef Colour)
const {
1766 return "color=" + Colour.
str();
1769 bool NodeGenerationComplete =
false;
1770 const std::string GraphName;
1771 std::vector<DisplayNode> Nodes;
1772 std::vector<DisplayNode *> NodePtrs;
1773 DisplayNode *EntryNode =
nullptr;
1776void DisplayNode::createEdge(StringRef
Value, DisplayNode &Node,
1778 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1779 Edges.emplace_back(
Value.str(), Node, Colour);
1783void DisplayNode::createEdgeMap() {
1786 AllEdgesCreated =
true;
1787 for (
auto &
E : Edges)
1788 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1791class DotCfgDiffNode;
1795class DotCfgDiffNode {
1797 DotCfgDiffNode() =
delete;
1801 DotCfgDiffNode(DotCfgDiff &
G,
unsigned N,
const BlockDataT<DCData> &BD,
1803 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1804 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1809 unsigned getIndex()
const {
return N; }
1812 StringRef getLabel()
const {
1813 assert(
Data[0] &&
"Expected Data[0] to be set.");
1814 return Data[0]->getLabel();
1817 StringRef getColour()
const {
return Colour; }
1820 void setCommon(
const BlockDataT<DCData> &
Other) {
1821 assert(!
Data[1] &&
"Expected only one block datum");
1826 void addEdge(
unsigned E, StringRef
Value, StringRef Colour) {
1829 "Unexpected edge count and color.");
1830 EdgesMap[
E] = {
Value.str(), Colour};
1836 StringRef getEdgeColour(
const unsigned S)
const {
1837 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1838 return EdgesMap.at(S).second;
1842 std::string getBodyContent()
const;
1844 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1845 std::map<const unsigned, unsigned> &NodeMap)
const;
1850 const BlockDataT<DCData> *
Data[2];
1852 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1854 std::vector<unsigned> Edges;
1864 DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1865 const FuncDataT<DCData> &After);
1867 DotCfgDiff(
const DotCfgDiff &) =
delete;
1868 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1870 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1871 StringRef EntryNodeName);
1877 StringRef getEdgeSourceLabel(
const unsigned &Source,
1878 const unsigned &Sink)
const {
1880 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1881 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1882 return EdgeLabels.find(S)->getValue();
1886 unsigned size()
const {
return Nodes.size(); }
1888 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1889 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1895 std::string colourize(std::string S, StringRef Colour)
const;
1897 void createNode(StringRef Label,
const BlockDataT<DCData> &BD, StringRef
C) {
1898 unsigned Pos = Nodes.size();
1899 Nodes.emplace_back(*
this, Pos, BD,
C);
1900 NodePosition.insert({
Label, Pos});
1906 std::vector<DotCfgDiffNode> Nodes;
1907 StringMap<unsigned> NodePosition;
1908 const std::string GraphName;
1910 StringMap<std::string> EdgeLabels;
1913std::string DotCfgDiffNode::getBodyContent()
const {
1915 assert(
Data[1] &&
"Expected Data[1] to be set.");
1918 for (
unsigned I = 0;
I < 2; ++
I) {
1919 SR[
I] =
Data[
I]->getBody();
1923 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1926 SmallString<80> OldLineFormat =
formatv(
1927 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1928 SmallString<80> NewLineFormat =
formatv(
1929 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1930 SmallString<80> UnchangedLineFormat =
formatv(
1931 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1932 std::string Diff =
Data[0]->getLabel().str();
1933 Diff +=
":\n<BR align=\"left\"/>" +
1934 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1935 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1940 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1943 std::string S =
R.sub(
"", Diff, &
Error);
1954 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1955 std::string Body = makeHTMLReady(
Data[0]->getBody());
1956 const StringRef BS = Body;
1959 if (BS.
front() ==
'\n')
1964 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1966 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1969 while (BS1.
size()) {
1970 S.append(
"<BR align=\"left\"/>");
1972 S.append(
Line.str());
1975 S.append(
"<BR align=\"left\"/></FONT>");
1979std::string DotCfgDiff::colourize(std::string S, StringRef Colour)
const {
1980 if (S.length() == 0)
1982 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1985DotCfgDiff::DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1986 const FuncDataT<DCData> &After)
1987 : GraphName(Title.str()) {
1988 StringMap<StringRef> EdgesMap;
1992 StringRef Label = B.getKey();
1993 const BlockDataT<DCData> &BD = B.getValue();
1994 createNode(Label, BD, BeforeColour);
1998 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1999 E = BD.getData().end();
2000 Sink != E; ++Sink) {
2001 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
2002 BD.getData().getSuccessorLabel(Sink->getKey()).str();
2003 EdgesMap.insert({Key, BeforeColour});
2009 StringRef Label = A.getKey();
2010 const BlockDataT<DCData> &BD = A.getValue();
2011 auto It = NodePosition.find(Label);
2012 if (It == NodePosition.end())
2014 createNode(Label, BD, AfterColour);
2016 Nodes[It->second].setCommon(BD);
2018 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
2019 E = BD.getData().end();
2020 Sink != E; ++Sink) {
2021 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
2022 BD.getData().getSuccessorLabel(Sink->getKey()).str();
2023 auto [It, Inserted] = EdgesMap.try_emplace(Key, AfterColour);
2025 It->second = CommonColour;
2030 for (
auto &
E : EdgesMap) {
2033 auto SP1 = S.
rsplit(
' ');
2034 auto &SourceSink = SP1.first;
2035 auto SP2 = SourceSink.split(
' ');
2040 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2041 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2042 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2043 unsigned SinkNode = NodePosition[
Sink];
2047 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2049 It->getValue() = colourize(
Value.str(), Colour);
2052 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2054 It->getValue() =
NV;
2056 SourceNode.addEdge(SinkNode,
Value, Colour);
2058 for (
auto &
I : Nodes)
2062DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2064 assert(NodePosition.count(EntryNodeName) == 1 &&
2065 "Expected to find entry block in map.");
2066 unsigned Entry = NodePosition[EntryNodeName];
2067 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2068 DotCfgDiffDisplayGraph
G(Title.
str());
2070 std::map<const unsigned, unsigned> NodeMap;
2072 int EntryIndex = -1;
2074 for (
auto &
I : Nodes) {
2075 if (
I.getIndex() == Entry)
2077 G.createNode(
I.getBodyContent(),
I.getColour());
2078 NodeMap.insert({
I.getIndex(),
Index++});
2080 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2081 G.setEntryNode(EntryIndex);
2083 for (
auto &
I : NodeMap) {
2084 unsigned SourceNode =
I.first;
2085 unsigned DisplayNode =
I.second;
2086 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2091void DotCfgDiffNode::createDisplayEdges(
2092 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2093 std::map<const unsigned, unsigned> &NodeMap)
const {
2095 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2097 for (
auto I : Edges) {
2098 unsigned SinkNodeIndex =
I;
2099 StringRef Colour = getEdgeColour(SinkNodeIndex);
2100 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2102 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2103 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2104 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2106 SourceDisplayNode.createEdgeMap();
2109void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2110 for (
auto E : EdgesMap) {
2112 Edges.emplace_back(
E.first);
2128 return G->getEntryNode();
2131 return N->children_begin();
2135 return G->nodes_begin();
2138 return G->nodes_end();
2141 return N->edges_begin();
2145 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2155 return DiffData->getGraphName();
2159 return "\tsize=\"190, 190\";\n";
2162 const DotCfgDiffDisplayGraph *DiffData) {
2163 return DiffData->getNodeLabel(*
Node);
2166 const DotCfgDiffDisplayGraph *DiffData) {
2167 return DiffData->getNodeAttributes(*
Node);
2170 DisplayNode::ChildIterator &To) {
2171 return From->getEdgeSourceLabel(**To);
2174 DisplayNode::ChildIterator &To,
2175 const DotCfgDiffDisplayGraph *DiffData) {
2176 return DiffData->getEdgeColorAttr(*From, **To);
2184void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
2186 raw_fd_ostream OutStream(DotFile, EC);
2188 errs() <<
"Error: " <<
EC.message() <<
"\n";
2209 for (
auto &
C : Sw->cases()) {
2210 assert(
C.getCaseValue() &&
"Expected to find case value.");
2231 assert(
HTML &&
"Expected outstream to be set");
2236 Extender =
formatv(
"{0}_{1}",
N, Minor);
2245 std::string DotFile =
Twine(SV).
str();
2253 DotCfgDiff Diff(
Text, Before, After);
2256 if (EntryBlockName ==
"")
2258 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2260 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2261 DG.generateDotFile(DotFile);
2266 errs() <<
"Error: " << EC.message() <<
"\n";
2275 return "Unable to find dot executable.";
2280 return "Error executing system dot.";
2284 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2289 assert(
HTML &&
"Expected outstream to be set");
2290 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2291 <<
"Initial IR (by function)</button>\n"
2292 <<
"<div class=\"content\">\n"
2301 [&](
bool InModule,
unsigned Minor,
2305 Minor, Before, After);
2319 assert(
HTML &&
"Expected outstream to be set");
2321 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2322 N, makeHTMLReady(PassID), Name);
2331 assert(
HTML &&
"Expected outstream to be set");
2334 [&](
bool InModule,
unsigned Minor,
2338 Minor, Before, After);
2340 *
HTML <<
" </p></div>\n";
2345 assert(
HTML &&
"Expected outstream to be set");
2347 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2353 assert(
HTML &&
"Expected outstream to be set");
2355 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2356 makeHTMLReady(PassID), Name);
2362 assert(
HTML &&
"Expected outstream to be set");
2364 makeHTMLReady(PassID), Name);
2371 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2377 *
HTML <<
"<!doctype html>"
2380 <<
"<style>.collapsible { "
2381 <<
"background-color: #777;"
2383 <<
" cursor: pointer;"
2384 <<
" padding: 18px;"
2387 <<
" text-align: left;"
2388 <<
" outline: none;"
2389 <<
" font-size: 15px;"
2390 <<
"} .active, .collapsible:hover {"
2391 <<
" background-color: #555;"
2393 <<
" padding: 0 18px;"
2394 <<
" display: none;"
2395 <<
" overflow: hidden;"
2396 <<
" background-color: #f1f1f1;"
2399 <<
"<title>passes.html</title>"
2409 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2411 <<
"for (i = 0; i < coll.length; i++) {"
2412 <<
"coll[i].addEventListener(\"click\", function() {"
2413 <<
" this.classList.toggle(\"active\");"
2414 <<
" var content = this.nextElementSibling;"
2415 <<
" if (content.style.display === \"block\"){"
2416 <<
" content.style.display = \"none\";"
2419 <<
" content.style.display= \"block\";"
2437 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2443 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2448 LLVMContext &Context,
bool DebugLogging,
bool VerifyEach,
2450 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2451 OptPassGate(Context),
2459 VerifyEach(VerifyEach) {}
2476void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2483 "Did not expect to get here without option set.");
2492 "Did not expect to get here without option set.");
2493 CrashReporter =
nullptr;
2502 CrashReporter =
this;
2504 PIC.registerBeforeNonSkippedPassCallback(
2508 OS <<
formatv(
"; *** Dump of {0}IR Before Last Pass {1}",
2511 OS <<
" Filtered Out ***\n";
2514 OS <<
" Started ***\n";
2515 unwrapAndPrint(OS,
IR);
2521 PrintIR.registerCallbacks(
PIC);
2522 PrintPass.registerCallbacks(
PIC);
2523 TimePasses.registerCallbacks(
PIC);
2524 OptNone.registerCallbacks(
PIC);
2525 OptPassGate.registerCallbacks(
PIC);
2526 PrintChangedIR.registerCallbacks(
PIC);
2527 PseudoProbeVerification.registerCallbacks(
PIC);
2529 Verify.registerCallbacks(
PIC,
MAM);
2530 PrintChangedDiff.registerCallbacks(
PIC);
2531 WebsiteChangeReporter.registerCallbacks(
PIC);
2532 ChangeTester.registerCallbacks(
PIC);
2533 PrintCrashIR.registerCallbacks(
PIC);
2534 DroppedStatsIR.registerCallbacks(
PIC);
2536 PreservedCFGChecker.registerCallbacks(
PIC, *
MAM);
2544 TimeProfilingPasses.registerCallbacks(
PIC);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file provides Any, a non-template class modeled in the spirit of std::any.
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
Machine Check Debug Module
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 void writeIRFileDisplayName(raw_ostream &ResultStream, const Any &IR)
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 const IRUnitT * unwrapIR(const Any &IR)
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
static void printBBName(raw_ostream &out, const BasicBlock *BB)
static std::string getIRFileDisplayName(const Any &IR)
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 SmallVector< Function *, 1 > GetFunctions(const Any &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
void saveIRBeforePass(const Any &IR, StringRef PassID, StringRef PassName)
void handleIRAfterPass(const Any &IR, StringRef PassID, StringRef PassName)
virtual void handleIgnored(StringRef PassID, std::string &Name)=0
virtual void handleAfter(StringRef PassID, std::string &Name, const IRUnitT &Before, const IRUnitT &After, const Any &)=0
virtual void handleInvalidated(StringRef PassID)=0
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
std::vector< IRUnitT > BeforeStack
virtual void generateIRRepresentation(const Any &IR, StringRef PassID, IRUnitT &Output)=0
virtual void omitAfter(StringRef PassID, std::string &Name)=0
void handleInvalidatedPass(StringRef PassID)
ChangeReporter(bool RunInVerboseMode)
virtual ~ChangeReporter()
virtual void handleInitialIR(const Any &IR)=0
Conditional Branch instruction.
void addSuccessorLabel(StringRef Succ, StringRef Label)
LLVM_ABI DCData(const BasicBlock &B)
void generateIRRepresentation(const Any &IR, StringRef PassID, IRDataT< DCData > &Output) override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, const Any &) override
std::unique_ptr< raw_fd_ostream > HTML
void handleInvalidated(StringRef PassID) override
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
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 handleFiltered(StringRef PassID, std::string &Name) override
void handleInitialIR(const Any &IR) 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 generateIRRepresentation(const Any &IR, StringRef PassID, std::string &Output) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, const Any &) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, const Any &) override
void omitAfter(StringRef PassID, std::string &Name) override
void handleInitialIR(const Any &IR) 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
const IRDataT< T > & Before
static bool generateFunctionData(IRDataT< T > &Data, const FunctionT &F)
const IRDataT< T > & After
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
static void analyzeIR(const Any &IR, IRDataT< T > &Data)
void generateIRRepresentation(const Any &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, const Any &) 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.
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, const 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().
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 handleInitialIR(const 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
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 std::error_code prepareTempFiles(SmallVector< int > &FD, ArrayRef< StringRef > SR, SmallVector< std::string > &FileName)
T any_cast(const Any &Value)
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 void timeTraceProfilerEnd()
Manually end the last time section.
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 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.