56 cl::desc(
"Print IR before the passes with specified numbers as "
57 "reported by print-pass-numbers"));
61 cl::desc(
"Print IR after the passes with specified numbers as "
62 "reported by print-pass-numbers"));
69bool loopContainsPrintSourceLoc(
const Loop &L) {
70 const Function *
F = L.getHeader()->getParent();
75 if (SourceLocFilterEmpty)
95 return F->getParent();
102 return F.getParent();
110 const Function *
F =
L->getHeader()->getParent();
111 if (!
Force && !loopContainsPrintSourceLoc(*L))
113 return F->getParent();
119 return MF->getFunction().getParent();
133 M->print(OS,
nullptr);
135 for (
const auto &
F : M->functions()) {
151 if (!loopContainsPrintSourceLoc(*L))
167 return F->getName().str();
173 return "loop %" +
L->getName().str() +
" in function " +
174 L->getHeader()->getParent()->getName().str();
181 for (
const auto &extendedIRTraits : Context->traits) {
182 if (
auto IRName = extendedIRTraits->getIRName(
IR))
190bool moduleContainsFilterPrintFunc(
const Module &M) {
193 return any_of(M.functions(),
194 [](
const Function &
F) { return shouldPrintFunction(F); });
206 return moduleContainsFilterPrintFunc(*M);
212 return sccContainsFilterPrintFunc(*
C);
215 return loopContainsPrintSourceLoc(*L);
225 if (!shouldPrintIR(
IR))
229 auto *M = unwrapModule(
IR);
230 assert(M &&
"should have unwrapped module");
265 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
266 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
267 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
268 "PrintMIRPreparePass",
"RequireAnalysisPass",
269 "InvalidateAnalysisPass"});
277 S.append(Clean.
str());
281 S.append(SR[0] ==
'<' ?
"<" :
">");
292 return C->begin()->getFunction().getParent();
304 return isInterestingFunction(*
F);
330 if (!Before.IsInteresting)
342 std::string Name = getIRName(
IR,
context);
350 if (!Before.IsInteresting && !AfterIsInteresting) {
355 if (AfterIsInteresting)
359 if (Before.Data == After) {
385 PIC.registerBeforeNonSkippedPassCallback(
390 PIC.registerAfterPassCallback(
394 PIC.registerAfterPassInvalidatedCallback(
408 auto *M = unwrapModule(
IR,
true);
409 assert(M &&
"Expected module to be unwrapped when forced.");
410 Out <<
"*** IR Dump At Start ***\n";
411 M->print(
Out,
nullptr);
416 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
429 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n",
PassID, Name);
447 std::string &Output) {
449 unwrapAndPrint(OS,
IR);
454 const std::string &Before,
457 if (PassesOptions::Global.print_before_changed)
458 Out <<
"*** IR Dump Before " <<
PassID <<
" on " << Name <<
" ***\n"
464 Out <<
"*** IR Deleted After " <<
PassID <<
" on " << Name <<
" ***\n";
468 Out <<
"*** IR Dump After " <<
PassID <<
" on " << Name <<
" ***\n" << After;
474 if (PassesOptions::Global.exec_on_ir_change !=
"")
479 const PassesOptions &Opts = PassesOptions::Global;
485 dbgs() <<
"Unable to create temporary file.";
491 dbgs() <<
"Unable to find test-changed executable.";
498 dbgs() <<
"Error executing test-changed executable.";
503 dbgs() <<
"Unable to remove temporary file.";
519 const std::string &Before,
528 const auto &BFD = Before.
getData();
529 const auto &AFD = After.
getData();
530 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
531 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
532 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
533 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
535 auto HandlePotentiallyRemovedData = [&](std::string S) {
539 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
542 auto HandleNewData = [&](std::vector<const T *> &Q) {
544 for (
const T *NBI : Q)
545 HandlePair(
nullptr, NBI);
558 std::vector<const T *> NewDataQueue;
560 if (!BFD.count(*AI)) {
563 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
572 while (BI != BE && *BI != *AI) {
573 HandlePotentiallyRemovedData(*BI);
577 HandleNewData(NewDataQueue);
579 const T &AData = AFD.find(*AI)->getValue();
580 const T &BData = BFD.find(*AI)->getValue();
581 HandlePair(&BData, &AData);
589 HandlePotentiallyRemovedData(*BI);
593 HandleNewData(NewDataQueue);
599 std::function<
void(
bool InModule,
unsigned Minor,
602 if (!CompareModule) {
605 (!
Before.getData().empty() || !
After.getData().empty()) &&
606 "Expected one function in at least one IR unit.");
609 Before.getData().empty() ? Missing
610 :
Before.getData().begin()->getValue();
612 After.getData().empty() ? Missing :
After.getData().begin()->getValue();
613 CompareFunc(
false, 0, BeforeFunction, AfterFunction);
621 assert((
B ||
A) &&
"Both functions cannot be missing.");
626 CompareFunc(
true, Minor++, *
B, *
A);
632 if (
const Module *M = getModuleForComparison(
IR)) {
645 auto *
F = L->getHeader()->getParent();
667 if (SourceLocFilterEmpty)
678template <
typename FunctionT>
683 for (
const auto &
B :
F) {
684 std::string BBName =
B.getName().str();
685 if (BBName.empty()) {
692 Data.getOrder().emplace_back(
F.getName());
693 Data.getData().insert({
F.getName(), FD});
700 assert(PassRunDescriptorStack.empty() &&
701 "PassRunDescriptorStack is not empty at exit");
705 const Module *M = unwrapModule(
IR,
true);
706 assert(M &&
"should have unwrapped module");
708 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
711 ResultStream <<
"-module";
713 ResultStream <<
"-function-";
718 ResultStream <<
"-scc-";
722 ResultStream <<
"-loop-";
726 ResultStream <<
"-machine-function-";
742StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
743 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
745 return FileSuffixes[
static_cast<size_t>(
Type)];
748std::string PrintIRInstrumentation::fetchDumpFilename(
750 IRDumpFileSuffixType SuffixType) {
751 const PassesOptions &Opts = PassesOptions::Global;
752 assert(!Opts.ir_dump_directory.empty() &&
753 "The flag -ir-dump-directory must be passed to dump IR to files");
756 raw_svector_ostream FilenameStream(
Filename);
757 FilenameStream << PassNumber;
758 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
760 FilenameStream << getFileSuffix(SuffixType);
762 SmallString<128> ResultPath;
764 return std::string(ResultPath);
767void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
769 unsigned PassNumber) {
772 getIRName(
IR, IRContext), PassID);
775PrintIRInstrumentation::PassRunDescriptor
776PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
777 assert(!PassRunDescriptorStack.empty() &&
"empty PassRunDescriptorStack");
778 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
779 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
787 if (!ParentPath.empty()) {
791 " to support -ir-dump-directory: " + EC.message());
798 " to support -ir-dump-directory: " + EC.message());
803 if (isIgnored(PassID))
810 if (shouldPrintAfterPass(PassID))
811 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
813 if (!shouldPrintIR(
IR))
818 if (shouldPrintPassNumbers())
819 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID <<
" on "
820 << getIRName(
IR, IRContext) <<
"\n";
822 if (shouldPrintAfterCurrentPassNumber())
823 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
825 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
828 auto WriteIRToStream = [&](raw_ostream &Stream) {
829 Stream <<
"; *** IR Dump Before ";
830 if (shouldPrintBeforeSomePassNumber())
831 Stream << CurrentPassNumber <<
"-";
832 Stream << PassID <<
" on " << getIRName(
IR, IRContext) <<
" ***\n";
833 unwrapAndPrint(Stream,
IR);
836 if (!PassesOptions::Global.ir_dump_directory.empty()) {
837 std::string DumpIRFilename =
839 IRDumpFileSuffixType::Before);
840 llvm::raw_fd_ostream DumpIRFileStream{
842 WriteIRToStream(DumpIRFileStream);
844 WriteIRToStream(
dbgs());
849 if (isIgnored(PassID))
852 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
855 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
856 popPassRunDescriptor(PassID);
857 assert(StoredPassID == PassID &&
"mismatched PassID");
859 if (!shouldPrintIR(
IR) ||
860 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
863 auto WriteIRToStream = [&](raw_ostream &Stream,
const StringRef IRName) {
864 Stream <<
"; *** IR Dump After ";
865 if (shouldPrintAfterSomePassNumber())
866 Stream << CurrentPassNumber <<
"-";
867 Stream << StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
868 unwrapAndPrint(Stream,
IR);
871 if (!PassesOptions::Global.ir_dump_directory.empty()) {
872 std::string DumpIRFilename =
874 IRDumpFileSuffixType::After);
875 llvm::raw_fd_ostream DumpIRFileStream{
878 WriteIRToStream(DumpIRFileStream, IRName);
880 WriteIRToStream(
dbgs(), IRName);
884void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
885 if (isIgnored(PassID))
888 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
891 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
892 popPassRunDescriptor(PassID);
893 assert(StoredPassID == PassID &&
"mismatched PassID");
897 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
900 auto WriteIRToStream = [&](raw_ostream &Stream,
const Module *
M,
901 const StringRef IRName) {
902 SmallString<20> Banner;
903 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
905 Stream << Banner <<
"\n";
909 if (!PassesOptions::Global.ir_dump_directory.empty()) {
910 std::string DumpIRFilename =
911 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
912 IRDumpFileSuffixType::Invalidated);
913 llvm::raw_fd_ostream DumpIRFileStream{
916 WriteIRToStream(DumpIRFileStream, M, IRName);
918 WriteIRToStream(
dbgs(), M, IRName);
922bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
926 StringRef
PassName = PIC->getPassNameForClassName(PassID);
930bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
934 StringRef
PassName = PIC->getPassNameForClassName(PassID);
938bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
939 return shouldPrintBeforeSomePassNumber() &&
943bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
944 return shouldPrintAfterSomePassNumber() &&
948bool PrintIRInstrumentation::shouldPrintPassNumbers() {
949 return PassesOptions::Global.print_pass_numbers;
952bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
956bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
962 this->IRContext = IRContext;
968 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
975 PIC.registerAfterPassCallback(
977 this->printAfterPass(
P,
IR);
979 PIC.registerAfterPassInvalidatedCallback(
981 this->printAfterPassInvalidated(
P);
988 this->IRContext = IRContext;
989 PIC.registerShouldRunOptionalPassCallback(
994 bool ShouldRun =
true;
996 ShouldRun = !
F->hasOptNone();
998 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1002 if (!ShouldRun && DebugLogging) {
1003 errs() <<
"Skipping pass " <<
PassID <<
" on " << getIRName(
IR, IRContext)
1004 <<
" due to optnone attribute\n";
1010 const PassesOptions &Opts = PassesOptions::Global;
1014 bool ShouldRun = Context.getOptPassGate().shouldRunPass(
1016 if (!ShouldRun && !this->HasWrittenIR &&
1017 !Opts.opt_bisect_print_ir_path.empty()) {
1020 this->HasWrittenIR =
true;
1021 const Module *M = unwrapModule(
IR,
true);
1022 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1027 M->print(OS,
nullptr);
1034 this->IRContext = IRContext;
1035 const OptPassGate &PassGate = Context.getOptPassGate();
1039 PIC.registerShouldRunOptionalPassCallback(
1058 this->IRContext = IRContext;
1062 std::vector<StringRef> SpecialPasses;
1063 if (!Opts.Verbose) {
1064 SpecialPasses.emplace_back(
"PassManager");
1065 SpecialPasses.emplace_back(
"PassAdaptor");
1071 "Unexpectedly skipping special pass");
1073 print() <<
"Skipping pass: " <<
PassID <<
" on "
1074 << getIRName(
IR, this->IRContext) <<
"\n";
1076 PIC.registerBeforeNonSkippedPassCallback(
1082 OS <<
"Running pass: " <<
PassID <<
" on "
1083 << getIRName(
IR, this->IRContext);
1085 unsigned Count =
F->getInstructionCount();
1086 OS <<
" (" <<
Count <<
" instruction";
1092 OS <<
" (" <<
Count <<
" node";
1100 PIC.registerAfterPassCallback(
1108 PIC.registerAfterPassInvalidatedCallback(
1116 if (!Opts.SkipAnalyses) {
1118 print() <<
"Running analysis: " <<
PassID <<
" on "
1119 << getIRName(
IR, this->IRContext) <<
"\n";
1122 PIC.registerAfterAnalysisCallback(
1124 PIC.registerAnalysisInvalidatedCallback(
1126 print() <<
"Invalidating analysis: " <<
PassID <<
" on "
1127 << getIRName(
IR, this->IRContext) <<
"\n";
1129 PIC.registerAnalysesClearedCallback([
this](
StringRef IRName) {
1130 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1136 bool TrackBBLifetime) {
1137 if (TrackBBLifetime)
1139 for (
const auto &BB : *
F) {
1141 BBGuards->try_emplace(intptr_t(&BB), &BB);
1145 BBGuards->try_emplace(intptr_t(Succ), Succ);
1152 out << BB->
getName() <<
"<" << BB <<
">";
1157 out <<
"unnamed_removed<" << BB <<
">";
1163 <<
"<" << BB <<
">";
1167 unsigned FuncOrderBlockNum = 0;
1171 FuncOrderBlockNum++;
1173 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1181 out <<
"Some blocks were deleted\n";
1186 if (Before.
Graph.size() != After.
Graph.size())
1187 out <<
"Different number of non-leaf basic blocks: before="
1188 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1190 for (
auto &BB : Before.
Graph) {
1191 auto BA = After.
Graph.find(BB.first);
1192 if (BA == After.
Graph.end()) {
1193 out <<
"Non-leaf block ";
1195 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1199 for (
auto &BA : After.
Graph) {
1200 auto BB = Before.
Graph.find(BA.first);
1201 if (BB == Before.
Graph.end()) {
1202 out <<
"Non-leaf block ";
1204 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1208 if (BB->second == BA.second)
1211 out <<
"Different successors of block ";
1213 out <<
" (unordered):\n";
1214 out <<
"- before (" << BB->second.size() <<
"): ";
1215 for (
auto &SuccB : BB->second) {
1217 if (SuccB.second != 1)
1218 out <<
"(" << SuccB.second <<
"), ";
1223 out <<
"- after (" << BA.second.size() <<
"): ";
1224 for (
auto &SuccA : BA.second) {
1226 if (SuccA.second != 1)
1227 out <<
"(" << SuccA.second <<
"), ";
1298 FunctionAnalysisManager::Invalidator &) {
1308 Functions.push_back(
const_cast<Function *
>(MaybeF));
1311 Functions.push_back(&
F);
1318#ifdef EXPENSIVE_CHECKS
1319 constexpr bool VerifyByDefault =
true;
1321 constexpr bool VerifyByDefault =
false;
1323 if (!
valueOr(PassesOptions::Global.verify_analysis_invalidation,
1327 bool Registered =
false;
1328 PIC.registerBeforeNonSkippedPassCallback([
this, &
MAM,
1331#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1332 assert(&PassStack.emplace_back(
P));
1337 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1353 auto &M = *
const_cast<Module *
>(MPtr);
1358 PIC.registerAfterPassInvalidatedCallback(
1360#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1361 assert(PassStack.pop_back_val() ==
P &&
1362 "Before and After callbacks must correspond");
1369#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1370 assert(PassStack.pop_back_val() ==
P &&
1371 "Before and After callbacks must correspond");
1379 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1383 if (
auto *HashBefore =
1387 "Function @{0} changed by {1} without invalidating analyses",
1393 const CFG &GraphBefore,
const CFG &GraphAfter) {
1394 if (GraphAfter == GraphBefore)
1398 <<
"Error: " <<
Pass
1399 <<
" does not invalidate CFG analyses but CFG changes detected in "
1401 << FuncName <<
":\n";
1406 if (
auto *GraphBefore =
1408 CheckCFG(
P,
F->getName(), *GraphBefore,
1412 auto &M = *
const_cast<Module *
>(MPtr);
1413 if (
auto *HashBefore =
1417 "Module changed by {0} without invalidating analyses",
P));
1426 PIC.registerAfterPassCallback(
1428 if (isIgnored(
P) ||
P ==
"VerifierPass")
1433 F = L->getHeader()->getParent();
1438 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1442 "\"{0}\", compilation aborted!",
1448 M =
C->begin()->getFunction().getParent();
1453 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1457 "\"{0}\", compilation aborted!",
1463 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1464 std::string Banner =
1465 formatv(
"Broken machine function found after pass "
1466 "\"{0}\", compilation aborted!",
1496 formatv(
"*** IR Dump After {0} on {1} ***\n",
PassID, Name);
1500 [&](
bool InModule,
unsigned Minor,
1504 Minor, Before, After);
1515 Out <<
"\n*** IR for function " << Name <<
" ***\n";
1522 const std::string Removed =
1523 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1524 const std::string Added =
UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1525 const std::string NoChange =
" %l\n";
1542 this->IRContext = IRContext;
1545 PIC.registerBeforeNonSkippedPassCallback(
1547 PIC.registerAfterPassCallback(
1549 this->runAfterPass();
1552 PIC.registerAfterPassInvalidatedCallback(
1555 PIC.registerBeforeAnalysisCallback(
1557 PIC.registerAfterAnalysisCallback(
1570class DotCfgDiffDisplayGraph;
1573class DisplayElement {
1576 StringRef getColour()
const {
return Colour; }
1579 DisplayElement(StringRef Colour) : Colour(Colour) {}
1580 const StringRef Colour;
1585class DisplayEdge :
public DisplayElement {
1587 DisplayEdge(std::string
Value, DisplayNode &Node, StringRef Colour)
1592 const DisplayNode &getDestinationNode()
const {
return Node; }
1596 const DisplayNode &
Node;
1600class DisplayNode :
public DisplayElement {
1604 DisplayNode(std::string Content, StringRef Colour)
1605 : DisplayElement(Colour), Content(Content) {}
1608 using ChildIterator = SmallPtrSet<DisplayNode *, 0>::const_iterator;
1609 ChildIterator children_begin()
const {
return Children.begin(); }
1610 ChildIterator children_end()
const {
return Children.end(); }
1613 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1614 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1615 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1618 void createEdge(StringRef
Value, DisplayNode &Node, StringRef Colour);
1621 std::string getContent()
const {
return Content; }
1624 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1625 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1626 return *EdgeMap.find(&To)->second;
1631 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1632 return getEdge(Sink).getValue();
1635 void createEdgeMap();
1638 const std::string Content;
1643 std::vector<DisplayEdge> Edges;
1645 std::vector<DisplayEdge *> EdgePtrs;
1646 SmallPtrSet<DisplayNode *, 0>
Children;
1647 DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
1650 bool AllEdgesCreated =
false;
1654class DotCfgDiffDisplayGraph {
1656 DotCfgDiffDisplayGraph(std::string Name) : GraphName(
Name) {}
1659 void generateDotFile(StringRef DotFile);
1662 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1663 NodeIterator nodes_begin()
const {
1664 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1665 return NodePtrs.cbegin();
1667 NodeIterator nodes_end()
const {
1668 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1669 return NodePtrs.cend();
1674 void setEntryNode(
unsigned N) {
1676 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1677 NodeGenerationComplete =
true;
1678 for (
auto &
N : Nodes)
1679 NodePtrs.emplace_back(&
N);
1681 EntryNode = NodePtrs[
N];
1685 void createNode(std::string
C, StringRef Colour) {
1686 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1687 Nodes.emplace_back(
C, Colour);
1691 assert(
N < Nodes.size() &&
"Node is out of bounds");
1694 unsigned size()
const {
1695 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1696 return Nodes.size();
1700 std::string getGraphName()
const {
return GraphName; }
1704 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1705 return Node.getContent();
1709 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1710 return attribute(
Node.getColour());
1714 std::string getEdgeColorAttr(
const DisplayNode &From,
1715 const DisplayNode &To)
const {
1716 return attribute(From.getEdge(To).getColour());
1720 DisplayNode *getEntryNode()
const {
1721 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1727 std::string attribute(StringRef Colour)
const {
1728 return "color=" + Colour.
str();
1731 bool NodeGenerationComplete =
false;
1732 const std::string GraphName;
1733 std::vector<DisplayNode> Nodes;
1734 std::vector<DisplayNode *> NodePtrs;
1735 DisplayNode *EntryNode =
nullptr;
1738void DisplayNode::createEdge(StringRef
Value, DisplayNode &Node,
1740 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1741 Edges.emplace_back(
Value.str(), Node, Colour);
1745void DisplayNode::createEdgeMap() {
1748 AllEdgesCreated =
true;
1749 for (
auto &
E : Edges)
1750 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1753class DotCfgDiffNode;
1757class DotCfgDiffNode {
1759 DotCfgDiffNode() =
delete;
1763 DotCfgDiffNode(DotCfgDiff &
G,
unsigned N,
const BlockDataT<DCData> &BD,
1765 : Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1766 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1771 unsigned getIndex()
const {
return N; }
1774 StringRef getLabel()
const {
1775 assert(
Data[0] &&
"Expected Data[0] to be set.");
1776 return Data[0]->getLabel();
1779 StringRef getColour()
const {
return Colour; }
1782 void setCommon(
const BlockDataT<DCData> &
Other) {
1783 assert(!
Data[1] &&
"Expected only one block datum");
1785 Colour = PassesOptions::Global.dot_cfg_common_color;
1788 void addEdge(
unsigned E, StringRef
Value, StringRef Colour) {
1790 assert((EdgesMap.count(
E) == 0 ||
1791 Colour == PassesOptions::Global.dot_cfg_common_color) &&
1792 "Unexpected edge count and color.");
1793 EdgesMap[
E] = {
Value.str(), Colour};
1799 StringRef getEdgeColour(
const unsigned S)
const {
1800 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1801 return EdgesMap.at(S).second;
1805 std::string getBodyContent()
const;
1807 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1808 std::map<const unsigned, unsigned> &NodeMap)
const;
1813 const BlockDataT<DCData> *
Data[2];
1815 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1817 std::vector<unsigned> Edges;
1827 DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1828 const FuncDataT<DCData> &After);
1830 DotCfgDiff(
const DotCfgDiff &) =
delete;
1831 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1833 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1834 StringRef EntryNodeName);
1840 StringRef getEdgeSourceLabel(
const unsigned &Source,
1841 const unsigned &Sink)
const {
1843 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1844 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1845 return EdgeLabels.find(S)->getValue();
1849 unsigned size()
const {
return Nodes.size(); }
1851 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1852 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1858 std::string colourize(std::string S, StringRef Colour)
const;
1860 void createNode(StringRef Label,
const BlockDataT<DCData> &BD, StringRef
C) {
1861 unsigned Pos = Nodes.size();
1862 Nodes.emplace_back(*
this, Pos, BD,
C);
1863 NodePosition.insert({
Label, Pos});
1869 std::vector<DotCfgDiffNode> Nodes;
1870 StringMap<unsigned> NodePosition;
1871 const std::string GraphName;
1873 StringMap<std::string> EdgeLabels;
1876std::string DotCfgDiffNode::getBodyContent()
const {
1877 const PassesOptions &Opts = PassesOptions::Global;
1878 if (Colour == Opts.dot_cfg_common_color) {
1879 assert(
Data[1] &&
"Expected Data[1] to be set.");
1882 for (
unsigned I = 0;
I < 2; ++
I) {
1883 SR[
I] =
Data[
I]->getBody();
1887 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1890 SmallString<80> OldLineFormat =
1891 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1892 Opts.dot_cfg_before_color);
1893 SmallString<80> NewLineFormat =
1894 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1895 Opts.dot_cfg_after_color);
1896 SmallString<80> UnchangedLineFormat =
1897 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1898 Opts.dot_cfg_common_color);
1899 std::string Diff =
Data[0]->getLabel().str();
1900 Diff +=
":\n<BR align=\"left\"/>" +
1901 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1902 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1907 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1910 std::string S =
R.sub(
"", Diff, &
Error);
1921 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1922 std::string Body = makeHTMLReady(
Data[0]->getBody());
1923 const StringRef BS = Body;
1926 if (BS.
front() ==
'\n')
1931 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1933 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1936 while (BS1.
size()) {
1937 S.append(
"<BR align=\"left\"/>");
1939 S.append(
Line.str());
1942 S.append(
"<BR align=\"left\"/></FONT>");
1946std::string DotCfgDiff::colourize(std::string S, StringRef Colour)
const {
1947 if (S.length() == 0)
1949 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1952DotCfgDiff::DotCfgDiff(StringRef Title,
const FuncDataT<DCData> &Before,
1953 const FuncDataT<DCData> &After)
1954 : GraphName(Title.str()) {
1955 const PassesOptions &Opts = PassesOptions::Global;
1956 StringMap<StringRef> EdgesMap;
1960 StringRef Label = B.getKey();
1961 const BlockDataT<DCData> &BD = B.getValue();
1962 createNode(Label, BD, Opts.dot_cfg_before_color);
1966 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1967 E = BD.getData().end();
1968 Sink != E; ++Sink) {
1969 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1970 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1971 EdgesMap.insert({Key, Opts.dot_cfg_before_color});
1977 StringRef Label = A.getKey();
1978 const BlockDataT<DCData> &BD = A.getValue();
1979 auto It = NodePosition.find(Label);
1980 if (It == NodePosition.end())
1982 createNode(Label, BD, Opts.dot_cfg_after_color);
1984 Nodes[It->second].setCommon(BD);
1986 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1987 E = BD.getData().end();
1988 Sink != E; ++Sink) {
1989 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1990 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1991 auto [It, Inserted] = EdgesMap.try_emplace(Key, Opts.dot_cfg_after_color);
1993 It->second = Opts.dot_cfg_common_color;
1998 for (
auto &
E : EdgesMap) {
2001 auto SP1 = S.
rsplit(
' ');
2002 auto &SourceSink = SP1.first;
2003 auto SP2 = SourceSink.split(
' ');
2008 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2009 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2010 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2011 unsigned SinkNode = NodePosition[Sink];
2015 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2017 It->getValue() = colourize(
Value.str(), Colour);
2020 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2021 Colour = Opts.dot_cfg_common_color;
2022 It->getValue() =
NV;
2024 SourceNode.addEdge(SinkNode,
Value, Colour);
2026 for (
auto &
I : Nodes)
2030DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2032 assert(NodePosition.count(EntryNodeName) == 1 &&
2033 "Expected to find entry block in map.");
2034 unsigned Entry = NodePosition[EntryNodeName];
2035 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2036 DotCfgDiffDisplayGraph
G(Title.
str());
2038 std::map<const unsigned, unsigned> NodeMap;
2040 int EntryIndex = -1;
2042 for (
auto &
I : Nodes) {
2043 if (
I.getIndex() == Entry)
2045 G.createNode(
I.getBodyContent(),
I.getColour());
2046 NodeMap.insert({
I.getIndex(),
Index++});
2048 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2049 G.setEntryNode(EntryIndex);
2051 for (
auto &
I : NodeMap) {
2052 unsigned SourceNode =
I.first;
2053 unsigned DisplayNode =
I.second;
2054 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2059void DotCfgDiffNode::createDisplayEdges(
2060 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2061 std::map<const unsigned, unsigned> &NodeMap)
const {
2063 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2065 for (
auto I : Edges) {
2066 unsigned SinkNodeIndex =
I;
2067 StringRef Colour = getEdgeColour(SinkNodeIndex);
2068 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2070 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2071 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2072 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2074 SourceDisplayNode.createEdgeMap();
2077void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2078 for (
auto E : EdgesMap) {
2080 Edges.emplace_back(
E.first);
2096 return G->getEntryNode();
2099 return N->children_begin();
2103 return G->nodes_begin();
2106 return G->nodes_end();
2109 return N->edges_begin();
2113 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2123 return DiffData->getGraphName();
2127 return "\tsize=\"190, 190\";\n";
2130 const DotCfgDiffDisplayGraph *DiffData) {
2131 return DiffData->getNodeLabel(*
Node);
2134 const DotCfgDiffDisplayGraph *DiffData) {
2135 return DiffData->getNodeAttributes(*
Node);
2138 DisplayNode::ChildIterator &To) {
2139 return From->getEdgeSourceLabel(**To);
2142 DisplayNode::ChildIterator &To,
2143 const DotCfgDiffDisplayGraph *DiffData) {
2144 return DiffData->getEdgeColorAttr(*From, **To);
2152void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
2154 raw_fd_ostream OutStream(DotFile, EC);
2156 errs() <<
"Error: " <<
EC.message() <<
"\n";
2177 for (
auto &
C : Sw->cases()) {
2178 assert(
C.getCaseValue() &&
"Expected to find case value.");
2199 assert(
HTML &&
"Expected outstream to be set");
2204 Extender =
formatv(
"{0}_{1}",
N, Minor);
2213 std::string DotFile =
Twine(SV).
str();
2221 DotCfgDiff Diff(
Text, Before, After);
2224 if (EntryBlockName ==
"")
2226 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2228 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2229 DG.generateDotFile(DotFile);
2234 errs() <<
"Error: " << EC.message() <<
"\n";
2239 const PassesOptions &Opts = PassesOptions::Global;
2245 return "Unable to find dot executable.";
2247 StringRef Args[] = {Opts.print_changed_dot_path,
"-Tpdf",
"-o", PDFFile,
2251 return "Error executing system dot.";
2255 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2260 assert(
HTML &&
"Expected outstream to be set");
2261 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2262 <<
"Initial IR (by function)</button>\n"
2263 <<
"<div class=\"content\">\n"
2272 [&](
bool InModule,
unsigned Minor,
2276 Minor, Before, After);
2290 assert(
HTML &&
"Expected outstream to be set");
2292 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2293 N, makeHTMLReady(
PassID), Name);
2302 assert(
HTML &&
"Expected outstream to be set");
2305 [&](
bool InModule,
unsigned Minor,
2309 Minor, Before, After);
2311 *
HTML <<
" </p></div>\n";
2316 assert(
HTML &&
"Expected outstream to be set");
2318 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(
PassID));
2324 assert(
HTML &&
"Expected outstream to be set");
2326 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2327 makeHTMLReady(
PassID), Name);
2333 assert(
HTML &&
"Expected outstream to be set");
2335 makeHTMLReady(
PassID), Name);
2342 HTML = std::make_unique<raw_fd_ostream>(
OutputDir +
"/passes.html", EC);
2348 *
HTML <<
"<!doctype html>"
2351 <<
"<style>.collapsible { "
2352 <<
"background-color: #777;"
2354 <<
" cursor: pointer;"
2355 <<
" padding: 18px;"
2358 <<
" text-align: left;"
2359 <<
" outline: none;"
2360 <<
" font-size: 15px;"
2361 <<
"} .active, .collapsible:hover {"
2362 <<
" background-color: #555;"
2364 <<
" padding: 0 18px;"
2365 <<
" display: none;"
2366 <<
" overflow: hidden;"
2367 <<
" background-color: #f1f1f1;"
2370 <<
"<title>passes.html</title>"
2380 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2382 <<
"for (i = 0; i < coll.length; i++) {"
2383 <<
"coll[i].addEventListener(\"click\", function() {"
2384 <<
" this.classList.toggle(\"active\");"
2385 <<
" var content = this.nextElementSibling;"
2386 <<
" if (content.style.display === \"block\"){"
2387 <<
" content.style.display = \"none\";"
2390 <<
" content.style.display= \"block\";"
2408 assert(!Dir.
empty() &&
"expected output dir to be non-empty");
2414 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2419 LLVMContext &Context,
bool DebugLogging,
bool VerifyEach,
2421 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2422 OptPassGate(Context),
2429 Verify(DebugLogging),
2430 DroppedStatsIR(PassesOptions::
Global.dropped_variable_stats),
2431 VerifyEach(VerifyEach) {}
2437 const PassesOptions &Opts = PassesOptions::Global;
2438 if (!Opts.print_on_crash_path.empty()) {
2449void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2455 assert((PassesOptions::Global.print_on_crash ||
2456 !PassesOptions::Global.print_on_crash_path.empty()) &&
2457 "Did not expect to get here without option set.");
2465 assert((PassesOptions::Global.print_on_crash ||
2466 !PassesOptions::Global.print_on_crash_path.empty()) &&
2467 "Did not expect to get here without option set.");
2468 CrashReporter =
nullptr;
2473 const PassesOptions &Opts = PassesOptions::Global;
2474 if ((!Opts.print_on_crash && Opts.print_on_crash_path.empty()) ||
2479 CrashReporter =
this;
2481 PIC.registerBeforeNonSkippedPassCallback(
2485 OS <<
formatv(
"; *** Dump of {0}IR Before Last Pass {1}",
2488 OS <<
" Filtered Out ***\n";
2491 OS <<
" Started ***\n";
2492 unwrapAndPrint(OS,
IR);
2499 if (PassesOptions::Global.instnamer_after_each_pass)
2501 PrintIR.registerCallbacks(
PIC, IRContext);
2502 PrintPass.registerCallbacks(
PIC, IRContext);
2503 TimePasses.registerCallbacks(
PIC);
2504 OptNone.registerCallbacks(
PIC, IRContext);
2505 OptPassGate.registerCallbacks(
PIC, IRContext);
2506 PrintChangedIR.registerCallbacks(
PIC);
2507 PseudoProbeVerification.registerCallbacks(
PIC);
2509 Verify.registerCallbacks(
PIC,
MAM);
2510 PrintChangedDiff.registerCallbacks(
PIC);
2511 WebsiteChangeReporter.registerCallbacks(
PIC);
2512 ChangeTester.registerCallbacks(
PIC);
2513 PrintCrashIR.registerCallbacks(
PIC);
2514 DroppedStatsIR.registerCallbacks(
PIC);
2516 PreservedCFGChecker.registerCallbacks(
PIC, *
MAM);
2524 TimeProfilingPasses.registerCallbacks(
PIC, IRContext);
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::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 SmallVector< Function *, 1 > GetFunctions(IRUnitRef IR)
static void printBBName(raw_ostream &out, const BasicBlock *BB)
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 void writeIRFileDisplayName(raw_ostream &ResultStream, IRUnitRef IR)
static std::string getIRFileDisplayName(IRUnitRef IR)
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 generateIRRepresentation(IRUnitRef IR, StringRef PassID, std::string &Output)=0
virtual void handleIgnored(StringRef PassID, std::string &Name)=0
ExtendedIRContext * context
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
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
std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName) const
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, ExtendedIRContext *IRContext=nullptr)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ExtendedIRContext *IRContext=nullptr)
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, ExtendedIRContext *IRContext=nullptr)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ExtendedIRContext *IRContext=nullptr)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr, ExtendedIRContext *IRContext=nullptr)
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 TimeProfilingPassesHandler()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ExtendedIRContext *IRContext=nullptr)
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.
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.
@ Global
Append to llvm.global_dtors.
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.
constexpr bool valueOr(BoolOrDefault X, bool Default)
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)
static LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, uint64_t &NextID)
Register callbacks to name unnamed values around new-PM passes.
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.