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"});
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 (
Opts.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 (
Opts.exec_on_ir_change !=
"")
484 dbgs() <<
"Unable to create temporary file.";
490 dbgs() <<
"Unable to find test-changed executable.";
497 dbgs() <<
"Error executing test-changed executable.";
502 dbgs() <<
"Unable to remove temporary file.";
518 const std::string &Before,
527 const auto &BFD = Before.
getData();
528 const auto &AFD = After.
getData();
529 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
530 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
531 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
532 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
534 auto HandlePotentiallyRemovedData = [&](std::string S) {
538 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
541 auto HandleNewData = [&](std::vector<const T *> &Q) {
543 for (
const T *NBI : Q)
544 HandlePair(
nullptr, NBI);
557 std::vector<const T *> NewDataQueue;
559 if (!BFD.count(*AI)) {
562 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
571 while (BI != BE && *BI != *AI) {
572 HandlePotentiallyRemovedData(*BI);
576 HandleNewData(NewDataQueue);
578 const T &AData = AFD.find(*AI)->getValue();
579 const T &BData = BFD.find(*AI)->getValue();
580 HandlePair(&BData, &AData);
588 HandlePotentiallyRemovedData(*BI);
592 HandleNewData(NewDataQueue);
598 std::function<
void(
bool InModule,
unsigned Minor,
601 if (!CompareModule) {
604 (!
Before.getData().empty() || !
After.getData().empty()) &&
605 "Expected one function in at least one IR unit.");
608 Before.getData().empty() ? Missing
609 :
Before.getData().begin()->getValue();
611 After.getData().empty() ? Missing :
After.getData().begin()->getValue();
612 CompareFunc(
false, 0, BeforeFunction, AfterFunction);
620 assert((
B ||
A) &&
"Both functions cannot be missing.");
625 CompareFunc(
true, Minor++, *
B, *
A);
631 if (
const Module *M = getModuleForComparison(
IR)) {
644 auto *
F = L->getHeader()->getParent();
666 if (SourceLocFilterEmpty)
677template <
typename FunctionT>
682 for (
const auto &
B :
F) {
683 std::string BBName =
B.getName().str();
684 if (BBName.empty()) {
691 Data.getOrder().emplace_back(
F.getName());
692 Data.getData().insert({
F.getName(), FD});
699 assert(PassRunDescriptorStack.empty() &&
700 "PassRunDescriptorStack is not empty at exit");
704 const Module *M = unwrapModule(
IR,
true);
705 assert(M &&
"should have unwrapped module");
707 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
710 ResultStream <<
"-module";
712 ResultStream <<
"-function-";
717 ResultStream <<
"-scc-";
721 ResultStream <<
"-loop-";
725 ResultStream <<
"-machine-function-";
741StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
742 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
744 return FileSuffixes[
static_cast<size_t>(
Type)];
747std::string PrintIRInstrumentation::fetchDumpFilename(
749 IRDumpFileSuffixType SuffixType) {
750 assert(!Opts.ir_dump_directory.empty() &&
751 "The flag -ir-dump-directory must be passed to dump IR to files");
754 raw_svector_ostream FilenameStream(
Filename);
755 FilenameStream << PassNumber;
756 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
758 FilenameStream << getFileSuffix(SuffixType);
760 SmallString<128> ResultPath;
762 return std::string(ResultPath);
765void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
767 unsigned PassNumber) {
770 getIRName(
IR, IRContext), PassID);
773PrintIRInstrumentation::PassRunDescriptor
774PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
775 assert(!PassRunDescriptorStack.empty() &&
"empty PassRunDescriptorStack");
776 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
777 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
785 if (!ParentPath.empty()) {
789 " to support -ir-dump-directory: " + EC.message());
796 " to support -ir-dump-directory: " + EC.message());
801 if (isIgnored(PassID))
808 if (shouldPrintAfterPass(PassID))
809 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
811 if (!shouldPrintIR(
IR))
816 if (shouldPrintPassNumbers())
817 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID <<
" on "
818 << getIRName(
IR, IRContext) <<
"\n";
820 if (shouldPrintAfterCurrentPassNumber())
821 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
823 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
826 auto WriteIRToStream = [&](raw_ostream &Stream) {
827 Stream <<
"; *** IR Dump Before ";
828 if (shouldPrintBeforeSomePassNumber())
829 Stream << CurrentPassNumber <<
"-";
830 Stream << PassID <<
" on " << getIRName(
IR, IRContext) <<
" ***\n";
831 unwrapAndPrint(Stream,
IR);
834 if (!Opts.ir_dump_directory.empty()) {
835 std::string DumpIRFilename =
837 IRDumpFileSuffixType::Before);
838 llvm::raw_fd_ostream DumpIRFileStream{
840 WriteIRToStream(DumpIRFileStream);
842 WriteIRToStream(
dbgs());
847 if (isIgnored(PassID))
850 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
853 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
854 popPassRunDescriptor(PassID);
855 assert(StoredPassID == PassID &&
"mismatched PassID");
857 if (!shouldPrintIR(
IR) ||
858 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
861 auto WriteIRToStream = [&](raw_ostream &Stream,
const StringRef IRName) {
862 Stream <<
"; *** IR Dump After ";
863 if (shouldPrintAfterSomePassNumber())
864 Stream << CurrentPassNumber <<
"-";
865 Stream << StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
866 unwrapAndPrint(Stream,
IR);
869 if (!Opts.ir_dump_directory.empty()) {
870 std::string DumpIRFilename =
872 IRDumpFileSuffixType::After);
873 llvm::raw_fd_ostream DumpIRFileStream{
876 WriteIRToStream(DumpIRFileStream, IRName);
878 WriteIRToStream(
dbgs(), IRName);
882void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
883 if (isIgnored(PassID))
886 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
889 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
890 popPassRunDescriptor(PassID);
891 assert(StoredPassID == PassID &&
"mismatched PassID");
895 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
898 auto WriteIRToStream = [&](raw_ostream &Stream,
const Module *
M,
899 const StringRef IRName) {
900 SmallString<20> Banner;
901 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
903 Stream << Banner <<
"\n";
907 if (!Opts.ir_dump_directory.empty()) {
908 std::string DumpIRFilename =
909 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
910 IRDumpFileSuffixType::Invalidated);
911 llvm::raw_fd_ostream DumpIRFileStream{
914 WriteIRToStream(DumpIRFileStream, M, IRName);
916 WriteIRToStream(
dbgs(), M, IRName);
920bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
924 StringRef
PassName = PIC->getPassNameForClassName(PassID);
928bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
932 StringRef
PassName = PIC->getPassNameForClassName(PassID);
936bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
937 return shouldPrintBeforeSomePassNumber() &&
941bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
942 return shouldPrintAfterSomePassNumber() &&
946bool PrintIRInstrumentation::shouldPrintPassNumbers() {
947 return Opts.print_pass_numbers;
950bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
954bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
960 this->IRContext = IRContext;
966 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
973 PIC.registerAfterPassCallback(
975 this->printAfterPass(
P,
IR);
977 PIC.registerAfterPassInvalidatedCallback(
979 this->printAfterPassInvalidated(
P);
986 this->IRContext = IRContext;
987 PIC.registerShouldRunOptionalPassCallback(
992 bool ShouldRun =
true;
994 ShouldRun = !
F->hasOptNone();
996 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1000 if (!ShouldRun && DebugLogging) {
1001 errs() <<
"Skipping pass " <<
PassID <<
" on " << getIRName(
IR, IRContext)
1002 <<
" due to optnone attribute\n";
1013 FuncName =
F->getName();
1015 FuncName = L->getHeader()->getParent()->getName();
1019 bool ShouldRun = Context.getOptPassGate().shouldRunPass(
1020 PassName, getIRName(
IR, IRContext), FuncName);
1021 if (!ShouldRun && !this->HasWrittenIR &&
1022 !Opts.opt_bisect_print_ir_path.empty()) {
1025 this->HasWrittenIR =
true;
1026 const Module *M = unwrapModule(
IR,
true);
1027 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1032 M->print(OS,
nullptr);
1039 this->IRContext = IRContext;
1040 const OptPassGate &PassGate = Context.getOptPassGate();
1044 PIC.registerShouldRunOptionalPassCallback(
1063 this->IRContext = IRContext;
1067 std::vector<StringRef> SpecialPasses;
1068 if (!Opts.Verbose) {
1069 SpecialPasses.emplace_back(
"PassManager");
1070 SpecialPasses.emplace_back(
"PassAdaptor");
1076 "Unexpectedly skipping special pass");
1078 print() <<
"Skipping pass: " <<
PassID <<
" on "
1079 << getIRName(
IR, this->IRContext) <<
"\n";
1081 PIC.registerBeforeNonSkippedPassCallback(
1087 OS <<
"Running pass: " <<
PassID <<
" on "
1088 << getIRName(
IR, this->IRContext);
1090 unsigned Count =
F->getInstructionCount();
1091 OS <<
" (" <<
Count <<
" instruction";
1097 OS <<
" (" <<
Count <<
" node";
1105 PIC.registerAfterPassCallback(
1113 PIC.registerAfterPassInvalidatedCallback(
1121 if (!Opts.SkipAnalyses) {
1123 print() <<
"Running analysis: " <<
PassID <<
" on "
1124 << getIRName(
IR, this->IRContext) <<
"\n";
1127 PIC.registerAfterAnalysisCallback(
1129 PIC.registerAnalysisInvalidatedCallback(
1131 print() <<
"Invalidating analysis: " <<
PassID <<
" on "
1132 << getIRName(
IR, this->IRContext) <<
"\n";
1134 PIC.registerAnalysesClearedCallback([
this](
StringRef IRName) {
1135 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1141 bool TrackBBLifetime) {
1142 if (TrackBBLifetime)
1144 for (
const auto &BB : *
F) {
1146 BBGuards->try_emplace(intptr_t(&BB), &BB);
1150 BBGuards->try_emplace(intptr_t(Succ), Succ);
1157 out << BB->
getName() <<
"<" << BB <<
">";
1162 out <<
"unnamed_removed<" << BB <<
">";
1168 <<
"<" << BB <<
">";
1172 unsigned FuncOrderBlockNum = 0;
1176 FuncOrderBlockNum++;
1178 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1186 out <<
"Some blocks were deleted\n";
1191 if (Before.
Graph.size() != After.
Graph.size())
1192 out <<
"Different number of non-leaf basic blocks: before="
1193 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1195 for (
auto &BB : Before.
Graph) {
1196 auto BA = After.
Graph.find(BB.first);
1197 if (BA == After.
Graph.end()) {
1198 out <<
"Non-leaf block ";
1200 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1204 for (
auto &BA : After.
Graph) {
1205 auto BB = Before.
Graph.find(BA.first);
1206 if (BB == Before.
Graph.end()) {
1207 out <<
"Non-leaf block ";
1209 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1213 if (BB->second == BA.second)
1216 out <<
"Different successors of block ";
1218 out <<
" (unordered):\n";
1219 out <<
"- before (" << BB->second.size() <<
"): ";
1220 for (
auto &SuccB : BB->second) {
1222 if (SuccB.second != 1)
1223 out <<
"(" << SuccB.second <<
"), ";
1228 out <<
"- after (" << BA.second.size() <<
"): ";
1229 for (
auto &SuccA : BA.second) {
1231 if (SuccA.second != 1)
1232 out <<
"(" << SuccA.second <<
"), ";
1303 FunctionAnalysisManager::Invalidator &) {
1313 Functions.push_back(
const_cast<Function *
>(MaybeF));
1316 Functions.push_back(&
F);
1323#ifdef EXPENSIVE_CHECKS
1324 constexpr bool VerifyByDefault =
true;
1326 constexpr bool VerifyByDefault =
false;
1328 if (!
valueOr(Opts.verify_analysis_invalidation, VerifyByDefault))
1331 bool Registered =
false;
1332 PIC.registerBeforeNonSkippedPassCallback([
this, &
MAM,
1335#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1336 assert(&PassStack.emplace_back(
P));
1341 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1357 auto &M = *
const_cast<Module *
>(MPtr);
1362 PIC.registerAfterPassInvalidatedCallback(
1364#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1365 assert(PassStack.pop_back_val() ==
P &&
1366 "Before and After callbacks must correspond");
1373#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1374 assert(PassStack.pop_back_val() ==
P &&
1375 "Before and After callbacks must correspond");
1383 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1387 if (
auto *HashBefore =
1391 "Function @{0} changed by {1} without invalidating analyses",
1397 const CFG &GraphBefore,
const CFG &GraphAfter) {
1398 if (GraphAfter == GraphBefore)
1402 <<
"Error: " <<
Pass
1403 <<
" does not invalidate CFG analyses but CFG changes detected in "
1405 << FuncName <<
":\n";
1410 if (
auto *GraphBefore =
1412 CheckCFG(
P,
F->getName(), *GraphBefore,
1416 auto &M = *
const_cast<Module *
>(MPtr);
1417 if (
auto *HashBefore =
1421 "Module changed by {0} without invalidating analyses",
P));
1430 PIC.registerAfterPassCallback(
1432 if (isIgnored(
P) ||
P ==
"VerifierPass")
1437 F = L->getHeader()->getParent();
1442 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1446 "\"{0}\", compilation aborted!",
1452 M =
C->begin()->getFunction().getParent();
1457 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1461 "\"{0}\", compilation aborted!",
1467 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1468 std::string Banner =
1469 formatv(
"Broken machine function found after pass "
1470 "\"{0}\", compilation aborted!",
1500 formatv(
"*** IR Dump After {0} on {1} ***\n",
PassID, Name);
1504 [&](
bool InModule,
unsigned Minor,
1508 Minor, Before, After);
1519 Out <<
"\n*** IR for function " << Name <<
" ***\n";
1526 const std::string Removed =
1527 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1528 const std::string Added =
UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1529 const std::string NoChange =
" %l\n";
1546 this->IRContext = IRContext;
1549 PIC.registerBeforeNonSkippedPassCallback(
1551 PIC.registerAfterPassCallback(
1553 this->runAfterPass();
1556 PIC.registerAfterPassInvalidatedCallback(
1559 PIC.registerBeforeAnalysisCallback(
1561 PIC.registerAfterAnalysisCallback(
1574class DotCfgDiffDisplayGraph;
1577class DisplayElement {
1580 StringRef getColour()
const {
return Colour; }
1583 DisplayElement(StringRef Colour) : Colour(Colour) {}
1584 const StringRef Colour;
1589class DisplayEdge :
public DisplayElement {
1591 DisplayEdge(std::string
Value, DisplayNode &Node, StringRef Colour)
1596 const DisplayNode &getDestinationNode()
const {
return Node; }
1600 const DisplayNode &
Node;
1604class DisplayNode :
public DisplayElement {
1608 DisplayNode(std::string Content, StringRef Colour)
1609 : DisplayElement(Colour), Content(Content) {}
1612 using ChildIterator = SmallPtrSet<DisplayNode *, 0>::const_iterator;
1613 ChildIterator children_begin()
const {
return Children.begin(); }
1614 ChildIterator children_end()
const {
return Children.end(); }
1617 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1618 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1619 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1622 void createEdge(StringRef
Value, DisplayNode &Node, StringRef Colour);
1625 std::string getContent()
const {
return Content; }
1628 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1629 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1630 return *EdgeMap.find(&To)->second;
1635 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1636 return getEdge(Sink).getValue();
1639 void createEdgeMap();
1642 const std::string Content;
1647 std::vector<DisplayEdge> Edges;
1649 std::vector<DisplayEdge *> EdgePtrs;
1650 SmallPtrSet<DisplayNode *, 0>
Children;
1651 DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
1654 bool AllEdgesCreated =
false;
1658class DotCfgDiffDisplayGraph {
1660 DotCfgDiffDisplayGraph(std::string Name) : GraphName(
Name) {}
1663 void generateDotFile(StringRef DotFile);
1666 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1667 NodeIterator nodes_begin()
const {
1668 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1669 return NodePtrs.cbegin();
1671 NodeIterator nodes_end()
const {
1672 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1673 return NodePtrs.cend();
1678 void setEntryNode(
unsigned N) {
1680 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1681 NodeGenerationComplete =
true;
1682 for (
auto &
N : Nodes)
1683 NodePtrs.emplace_back(&
N);
1685 EntryNode = NodePtrs[
N];
1689 void createNode(std::string
C, StringRef Colour) {
1690 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1691 Nodes.emplace_back(
C, Colour);
1695 assert(
N < Nodes.size() &&
"Node is out of bounds");
1698 unsigned size()
const {
1699 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1700 return Nodes.size();
1704 std::string getGraphName()
const {
return GraphName; }
1708 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1709 return Node.getContent();
1713 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1714 return attribute(
Node.getColour());
1718 std::string getEdgeColorAttr(
const DisplayNode &From,
1719 const DisplayNode &To)
const {
1720 return attribute(From.getEdge(To).getColour());
1724 DisplayNode *getEntryNode()
const {
1725 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1731 std::string attribute(StringRef Colour)
const {
1732 return "color=" + Colour.
str();
1735 bool NodeGenerationComplete =
false;
1736 const std::string GraphName;
1737 std::vector<DisplayNode> Nodes;
1738 std::vector<DisplayNode *> NodePtrs;
1739 DisplayNode *EntryNode =
nullptr;
1742void DisplayNode::createEdge(StringRef
Value, DisplayNode &Node,
1744 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1745 Edges.emplace_back(
Value.str(), Node, Colour);
1749void DisplayNode::createEdgeMap() {
1752 AllEdgesCreated =
true;
1753 for (
auto &
E : Edges)
1754 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1757class DotCfgDiffNode;
1761class DotCfgDiffNode {
1763 DotCfgDiffNode() =
delete;
1767 DotCfgDiffNode(
const PassesOptions &Opts, DotCfgDiff &
G,
unsigned N,
1768 const BlockDataT<DCData> &BD, StringRef Colour)
1769 : Opts(Opts), Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1770 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1771 : Opts(DN.Opts), Graph(DN.Graph),
N(DN.
N),
Data{DN.
Data[0], DN.
Data[1]},
1775 unsigned getIndex()
const {
return N; }
1778 StringRef getLabel()
const {
1779 assert(
Data[0] &&
"Expected Data[0] to be set.");
1780 return Data[0]->getLabel();
1783 StringRef getColour()
const {
return Colour; }
1786 void setCommon(
const BlockDataT<DCData> &
Other) {
1787 assert(!
Data[1] &&
"Expected only one block datum");
1789 Colour = Opts.dot_cfg_common_color;
1792 void addEdge(
unsigned E, StringRef
Value, StringRef Colour) {
1794 assert((EdgesMap.count(
E) == 0 || Colour == Opts.dot_cfg_common_color) &&
1795 "Unexpected edge count and color.");
1796 EdgesMap[
E] = {
Value.str(), Colour};
1802 StringRef getEdgeColour(
const unsigned S)
const {
1803 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1804 return EdgesMap.at(S).second;
1808 std::string getBodyContent()
const;
1810 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1811 std::map<const unsigned, unsigned> &NodeMap)
const;
1814 const PassesOptions &Opts;
1817 const BlockDataT<DCData> *
Data[2];
1819 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1821 std::vector<unsigned> Edges;
1831 DotCfgDiff(
const PassesOptions &Opts, StringRef Title,
1832 const FuncDataT<DCData> &Before,
const FuncDataT<DCData> &After);
1834 DotCfgDiff(
const DotCfgDiff &) =
delete;
1835 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1837 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1838 StringRef EntryNodeName);
1844 StringRef getEdgeSourceLabel(
const unsigned &Source,
1845 const unsigned &Sink)
const {
1847 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1848 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1849 return EdgeLabels.find(S)->getValue();
1853 unsigned size()
const {
return Nodes.size(); }
1855 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1856 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1862 std::string colourize(std::string S, StringRef Colour)
const;
1864 void createNode(StringRef Label,
const BlockDataT<DCData> &BD, StringRef
C) {
1865 unsigned Pos = Nodes.size();
1866 Nodes.emplace_back(Opts, *
this, Pos, BD,
C);
1867 NodePosition.insert({
Label, Pos});
1870 const PassesOptions &Opts;
1874 std::vector<DotCfgDiffNode> Nodes;
1875 StringMap<unsigned> NodePosition;
1876 const std::string GraphName;
1878 StringMap<std::string> EdgeLabels;
1881std::string DotCfgDiffNode::getBodyContent()
const {
1882 if (Colour == Opts.dot_cfg_common_color) {
1883 assert(
Data[1] &&
"Expected Data[1] to be set.");
1886 for (
unsigned I = 0;
I < 2; ++
I) {
1887 SR[
I] =
Data[
I]->getBody();
1891 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1894 SmallString<80> OldLineFormat =
1895 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1896 Opts.dot_cfg_before_color);
1897 SmallString<80> NewLineFormat =
1898 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1899 Opts.dot_cfg_after_color);
1900 SmallString<80> UnchangedLineFormat =
1901 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1902 Opts.dot_cfg_common_color);
1903 std::string Diff =
Data[0]->getLabel().str();
1904 Diff +=
":\n<BR align=\"left\"/>" +
1905 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1906 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1911 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1914 std::string S =
R.sub(
"", Diff, &
Error);
1925 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1926 std::string Body = makeHTMLReady(
Data[0]->getBody());
1927 const StringRef BS = Body;
1930 if (BS.
front() ==
'\n')
1935 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1937 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1940 while (BS1.
size()) {
1941 S.append(
"<BR align=\"left\"/>");
1943 S.append(
Line.str());
1946 S.append(
"<BR align=\"left\"/></FONT>");
1950std::string DotCfgDiff::colourize(std::string S, StringRef Colour)
const {
1951 if (S.length() == 0)
1953 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1956DotCfgDiff::DotCfgDiff(
const PassesOptions &Opts, StringRef Title,
1957 const FuncDataT<DCData> &Before,
1958 const FuncDataT<DCData> &After)
1959 : Opts(Opts), GraphName(Title.str()) {
1960 StringMap<StringRef> EdgesMap;
1964 StringRef Label = B.getKey();
1965 const BlockDataT<DCData> &BD = B.getValue();
1966 createNode(Label, BD, Opts.dot_cfg_before_color);
1970 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1971 E = BD.getData().end();
1972 Sink != E; ++Sink) {
1973 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1974 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1975 EdgesMap.insert({Key, Opts.dot_cfg_before_color});
1981 StringRef Label = A.getKey();
1982 const BlockDataT<DCData> &BD = A.getValue();
1983 auto It = NodePosition.find(Label);
1984 if (It == NodePosition.end())
1986 createNode(Label, BD, Opts.dot_cfg_after_color);
1988 Nodes[It->second].setCommon(BD);
1990 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1991 E = BD.getData().end();
1992 Sink != E; ++Sink) {
1993 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1994 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1995 auto [It, Inserted] = EdgesMap.try_emplace(Key, Opts.dot_cfg_after_color);
1997 It->second = Opts.dot_cfg_common_color;
2002 for (
auto &
E : EdgesMap) {
2005 auto SP1 = S.
rsplit(
' ');
2006 auto &SourceSink = SP1.first;
2007 auto SP2 = SourceSink.split(
' ');
2012 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2013 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2014 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2015 unsigned SinkNode = NodePosition[Sink];
2019 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2021 It->getValue() = colourize(
Value.str(), Colour);
2024 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2025 Colour = Opts.dot_cfg_common_color;
2026 It->getValue() =
NV;
2028 SourceNode.addEdge(SinkNode,
Value, Colour);
2030 for (
auto &
I : Nodes)
2034DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2036 assert(NodePosition.count(EntryNodeName) == 1 &&
2037 "Expected to find entry block in map.");
2038 unsigned Entry = NodePosition[EntryNodeName];
2039 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2040 DotCfgDiffDisplayGraph
G(Title.
str());
2042 std::map<const unsigned, unsigned> NodeMap;
2044 int EntryIndex = -1;
2046 for (
auto &
I : Nodes) {
2047 if (
I.getIndex() == Entry)
2049 G.createNode(
I.getBodyContent(),
I.getColour());
2050 NodeMap.insert({
I.getIndex(),
Index++});
2052 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2053 G.setEntryNode(EntryIndex);
2055 for (
auto &
I : NodeMap) {
2056 unsigned SourceNode =
I.first;
2057 unsigned DisplayNode =
I.second;
2058 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2063void DotCfgDiffNode::createDisplayEdges(
2064 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2065 std::map<const unsigned, unsigned> &NodeMap)
const {
2067 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2069 for (
auto I : Edges) {
2070 unsigned SinkNodeIndex =
I;
2071 StringRef Colour = getEdgeColour(SinkNodeIndex);
2072 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2074 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2075 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2076 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2078 SourceDisplayNode.createEdgeMap();
2081void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2082 for (
auto E : EdgesMap) {
2084 Edges.emplace_back(
E.first);
2100 return G->getEntryNode();
2103 return N->children_begin();
2107 return G->nodes_begin();
2110 return G->nodes_end();
2113 return N->edges_begin();
2117 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2127 return DiffData->getGraphName();
2131 return "\tsize=\"190, 190\";\n";
2134 const DotCfgDiffDisplayGraph *DiffData) {
2135 return DiffData->getNodeLabel(*
Node);
2138 const DotCfgDiffDisplayGraph *DiffData) {
2139 return DiffData->getNodeAttributes(*
Node);
2142 DisplayNode::ChildIterator &To) {
2143 return From->getEdgeSourceLabel(**To);
2146 DisplayNode::ChildIterator &To,
2147 const DotCfgDiffDisplayGraph *DiffData) {
2148 return DiffData->getEdgeColorAttr(*From, **To);
2156void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
2158 raw_fd_ostream OutStream(DotFile, EC);
2160 errs() <<
"Error: " <<
EC.message() <<
"\n";
2181 for (
auto &
C : Sw->cases()) {
2182 assert(
C.getCaseValue() &&
"Expected to find case value.");
2204 assert(
HTML &&
"Expected outstream to be set");
2209 Extender =
formatv(
"{0}_{1}",
N, Minor);
2218 std::string DotFile =
Twine(SV).
str();
2226 DotCfgDiff Diff(
Opts,
Text, Before, After);
2229 if (EntryBlockName ==
"")
2231 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2233 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2234 DG.generateDotFile(DotFile);
2239 errs() <<
"Error: " << EC.message() <<
"\n";
2249 return "Unable to find dot executable.";
2251 StringRef Args[] = {
Opts.print_changed_dot_path,
"-Tpdf",
"-o", PDFFile,
2255 return "Error executing system dot.";
2259 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2264 assert(
HTML &&
"Expected outstream to be set");
2265 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2266 <<
"Initial IR (by function)</button>\n"
2267 <<
"<div class=\"content\">\n"
2276 [&](
bool InModule,
unsigned Minor,
2280 Minor, Before, After);
2294 assert(
HTML &&
"Expected outstream to be set");
2296 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2297 N, makeHTMLReady(
PassID), Name);
2306 assert(
HTML &&
"Expected outstream to be set");
2309 [&](
bool InModule,
unsigned Minor,
2313 Minor, Before, After);
2315 *
HTML <<
" </p></div>\n";
2320 assert(
HTML &&
"Expected outstream to be set");
2322 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(
PassID));
2328 assert(
HTML &&
"Expected outstream to be set");
2330 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2331 makeHTMLReady(
PassID), Name);
2337 assert(
HTML &&
"Expected outstream to be set");
2339 makeHTMLReady(
PassID), Name);
2346 HTML = std::make_unique<raw_fd_ostream>(
OutputDir +
"/passes.html", EC);
2352 *
HTML <<
"<!doctype html>"
2355 <<
"<style>.collapsible { "
2356 <<
"background-color: #777;"
2358 <<
" cursor: pointer;"
2359 <<
" padding: 18px;"
2362 <<
" text-align: left;"
2363 <<
" outline: none;"
2364 <<
" font-size: 15px;"
2365 <<
"} .active, .collapsible:hover {"
2366 <<
" background-color: #555;"
2368 <<
" padding: 0 18px;"
2369 <<
" display: none;"
2370 <<
" overflow: hidden;"
2371 <<
" background-color: #f1f1f1;"
2374 <<
"<title>passes.html</title>"
2384 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2386 <<
"for (i = 0; i < coll.length; i++) {"
2387 <<
"coll[i].addEventListener(\"click\", function() {"
2388 <<
" this.classList.toggle(\"active\");"
2389 <<
" var content = this.nextElementSibling;"
2390 <<
" if (content.style.display === \"block\"){"
2391 <<
" content.style.display = \"none\";"
2394 <<
" content.style.display= \"block\";"
2412 assert(!Dir.
empty() &&
"expected output dir to be non-empty");
2418 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2423 LLVMContext &Context,
bool DebugLogging,
bool VerifyEach,
2425 : Opts(Context.getLibraryOptions().
get<PassesOptions>()), PrintIR(Opts),
2426 PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2427 OptPassGate(Opts, Context), PreservedCFGChecker(Opts),
2434 PrintCrashIR(Opts), ChangeTester(Opts), Verify(DebugLogging),
2435 DroppedStatsIR(Opts.dropped_variable_stats), VerifyEach(VerifyEach) {}
2441 if (!
Opts.print_on_crash_path.empty()) {
2452void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2458 assert((CrashReporter->
Opts.print_on_crash ||
2459 !CrashReporter->
Opts.print_on_crash_path.empty()) &&
2460 "Did not expect to get here without option set.");
2468 assert((CrashReporter->Opts.print_on_crash ||
2469 !CrashReporter->Opts.print_on_crash_path.empty()) &&
2470 "Did not expect to get here without option set.");
2471 CrashReporter =
nullptr;
2476 if ((!
Opts.print_on_crash &&
Opts.print_on_crash_path.empty()) ||
2481 CrashReporter =
this;
2483 PIC.registerBeforeNonSkippedPassCallback(
2487 OS <<
formatv(
"; *** Dump of {0}IR Before Last Pass {1}",
2490 OS <<
" Filtered Out ***\n";
2493 OS <<
" Started ***\n";
2494 unwrapAndPrint(OS,
IR);
2501 if (Opts.instnamer_after_each_pass)
2503 PrintIR.registerCallbacks(
PIC, IRContext);
2504 PrintPass.registerCallbacks(
PIC, IRContext);
2505 TimePasses.registerCallbacks(
PIC);
2506 OptNone.registerCallbacks(
PIC, IRContext);
2507 OptPassGate.registerCallbacks(
PIC, IRContext);
2508 PrintChangedIR.registerCallbacks(
PIC);
2509 PseudoProbeVerification.registerCallbacks(
PIC);
2511 Verify.registerCallbacks(
PIC,
MAM);
2512 PrintChangedDiff.registerCallbacks(
PIC);
2513 WebsiteChangeReporter.registerCallbacks(
PIC);
2514 ChangeTester.registerCallbacks(
PIC);
2515 PrintCrashIR.registerCallbacks(
PIC);
2516 DroppedStatsIR.registerCallbacks(
PIC);
2518 PreservedCFGChecker.registerCallbacks(
PIC, *
MAM);
2526 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 handleInitialIR(IRUnitRef IR)=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
DotCfgChangeReporter(const PassesOptions &Opts, bool Verbose)
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)
void handleIgnored(StringRef PassID, std::string &Name) override
~DotCfgChangeReporter() override
std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName) const
const PassesOptions & Opts
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
const PassesOptions & Opts
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()
const PassesOptions & Opts
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)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI bool isFunctionInPrintList(StringRef FunctionName)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI bool isPassInPrintList(StringRef PassName)
LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
LLVM_ABI bool isSourceLocFilterEmpty()
LLVM_ABI void timeTraceProfilerEnd()
Manually end the last time section.
LLVM_ABI bool shouldPrintFunction(const Function &F)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI std::error_code cleanUpTempFiles(ArrayRef< std::string > FileName)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
InnerAnalysisManagerProxy< MachineFunctionAnalysisManager, Module > MachineFunctionAnalysisManagerModuleProxy
LLVM_ABI void printLoop(const Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
LLVM_ABI std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
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.