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 "RequireAnalysisPass",
"InvalidateAnalysisPass"});
276 S.append(Clean.
str());
280 S.append(SR[0] ==
'<' ?
"<" :
">");
291 return C->begin()->getFunction().getParent();
303 return isInterestingFunction(*
F);
329 if (!Before.IsInteresting)
341 std::string Name = getIRName(
IR,
context);
349 if (!Before.IsInteresting && !AfterIsInteresting) {
354 if (AfterIsInteresting)
358 if (Before.Data == After) {
384 PIC.registerBeforeNonSkippedPassCallback(
389 PIC.registerAfterPassCallback(
393 PIC.registerAfterPassInvalidatedCallback(
407 auto *M = unwrapModule(
IR,
true);
408 assert(M &&
"Expected module to be unwrapped when forced.");
409 Out <<
"*** IR Dump At Start ***\n";
410 M->print(
Out,
nullptr);
415 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
428 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n",
PassID, Name);
446 std::string &Output) {
448 unwrapAndPrint(OS,
IR);
453 const std::string &Before,
456 if (
Opts.print_before_changed)
457 Out <<
"*** IR Dump Before " <<
PassID <<
" on " << Name <<
" ***\n"
463 Out <<
"*** IR Deleted After " <<
PassID <<
" on " << Name <<
" ***\n";
467 Out <<
"*** IR Dump After " <<
PassID <<
" on " << Name <<
" ***\n" << After;
473 if (
Opts.exec_on_ir_change !=
"")
483 dbgs() <<
"Unable to create temporary file.";
489 dbgs() <<
"Unable to find test-changed executable.";
496 dbgs() <<
"Error executing test-changed executable.";
501 dbgs() <<
"Unable to remove temporary file.";
517 const std::string &Before,
526 const auto &BFD = Before.
getData();
527 const auto &AFD = After.
getData();
528 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
529 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
530 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
531 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
533 auto HandlePotentiallyRemovedData = [&](std::string S) {
537 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
540 auto HandleNewData = [&](std::vector<const T *> &Q) {
542 for (
const T *NBI : Q)
543 HandlePair(
nullptr, NBI);
556 std::vector<const T *> NewDataQueue;
558 if (!BFD.count(*AI)) {
561 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
570 while (BI != BE && *BI != *AI) {
571 HandlePotentiallyRemovedData(*BI);
575 HandleNewData(NewDataQueue);
577 const T &AData = AFD.find(*AI)->getValue();
578 const T &BData = BFD.find(*AI)->getValue();
579 HandlePair(&BData, &AData);
587 HandlePotentiallyRemovedData(*BI);
591 HandleNewData(NewDataQueue);
597 std::function<
void(
bool InModule,
unsigned Minor,
600 if (!CompareModule) {
603 (!
Before.getData().empty() || !
After.getData().empty()) &&
604 "Expected one function in at least one IR unit.");
607 Before.getData().empty() ? Missing
608 :
Before.getData().begin()->getValue();
610 After.getData().empty() ? Missing :
After.getData().begin()->getValue();
611 CompareFunc(
false, 0, BeforeFunction, AfterFunction);
619 assert((
B ||
A) &&
"Both functions cannot be missing.");
624 CompareFunc(
true, Minor++, *
B, *
A);
630 if (
const Module *M = getModuleForComparison(
IR)) {
643 auto *
F = L->getHeader()->getParent();
665 if (SourceLocFilterEmpty)
676template <
typename FunctionT>
681 for (
const auto &
B :
F) {
682 std::string BBName =
B.getName().str();
683 if (BBName.empty()) {
690 Data.getOrder().emplace_back(
F.getName());
691 Data.getData().insert({
F.getName(), FD});
698 assert(PassRunDescriptorStack.empty() &&
699 "PassRunDescriptorStack is not empty at exit");
703 const Module *M = unwrapModule(
IR,
true);
704 assert(M &&
"should have unwrapped module");
706 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
709 ResultStream <<
"-module";
711 ResultStream <<
"-function-";
716 ResultStream <<
"-scc-";
720 ResultStream <<
"-loop-";
724 ResultStream <<
"-machine-function-";
740StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
741 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
743 return FileSuffixes[
static_cast<size_t>(
Type)];
746std::string PrintIRInstrumentation::fetchDumpFilename(
748 IRDumpFileSuffixType SuffixType) {
749 assert(!Opts.ir_dump_directory.empty() &&
750 "The flag -ir-dump-directory must be passed to dump IR to files");
753 raw_svector_ostream FilenameStream(
Filename);
754 FilenameStream << PassNumber;
755 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
757 FilenameStream << getFileSuffix(SuffixType);
759 SmallString<128> ResultPath;
761 return std::string(ResultPath);
764void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
766 unsigned PassNumber) {
769 getIRName(
IR, IRContext), PassID);
772PrintIRInstrumentation::PassRunDescriptor
773PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
774 assert(!PassRunDescriptorStack.empty() &&
"empty PassRunDescriptorStack");
775 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();
776 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
784 if (!ParentPath.empty()) {
788 " to support -ir-dump-directory: " + EC.message());
795 " to support -ir-dump-directory: " + EC.message());
800 if (isIgnored(PassID))
807 if (shouldPrintAfterPass(PassID))
808 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
810 if (!shouldPrintIR(
IR))
815 if (shouldPrintPassNumbers())
816 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID <<
" on "
817 << getIRName(
IR, IRContext) <<
"\n";
819 if (shouldPrintAfterCurrentPassNumber())
820 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
822 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
825 auto WriteIRToStream = [&](raw_ostream &Stream) {
826 Stream <<
"; *** IR Dump Before ";
827 if (shouldPrintBeforeSomePassNumber())
828 Stream << CurrentPassNumber <<
"-";
829 Stream << PassID <<
" on " << getIRName(
IR, IRContext) <<
" ***\n";
830 unwrapAndPrint(Stream,
IR);
833 if (!Opts.ir_dump_directory.empty()) {
834 std::string DumpIRFilename =
836 IRDumpFileSuffixType::Before);
837 llvm::raw_fd_ostream DumpIRFileStream{
839 WriteIRToStream(DumpIRFileStream);
841 WriteIRToStream(
dbgs());
846 if (isIgnored(PassID))
849 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
852 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
853 popPassRunDescriptor(PassID);
854 assert(StoredPassID == PassID &&
"mismatched PassID");
856 if (!shouldPrintIR(
IR) ||
857 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
860 auto WriteIRToStream = [&](raw_ostream &Stream,
const StringRef IRName) {
861 Stream <<
"; *** IR Dump After ";
862 if (shouldPrintAfterSomePassNumber())
863 Stream << CurrentPassNumber <<
"-";
864 Stream << StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
865 unwrapAndPrint(Stream,
IR);
868 if (!Opts.ir_dump_directory.empty()) {
869 std::string DumpIRFilename =
871 IRDumpFileSuffixType::After);
872 llvm::raw_fd_ostream DumpIRFileStream{
875 WriteIRToStream(DumpIRFileStream, IRName);
877 WriteIRToStream(
dbgs(), IRName);
881void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
882 if (isIgnored(PassID))
885 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
888 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
889 popPassRunDescriptor(PassID);
890 assert(StoredPassID == PassID &&
"mismatched PassID");
894 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
897 auto WriteIRToStream = [&](raw_ostream &Stream,
const Module *
M,
898 const StringRef IRName) {
899 SmallString<20> Banner;
900 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
902 Stream << Banner <<
"\n";
906 if (!Opts.ir_dump_directory.empty()) {
907 std::string DumpIRFilename =
908 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
909 IRDumpFileSuffixType::Invalidated);
910 llvm::raw_fd_ostream DumpIRFileStream{
913 WriteIRToStream(DumpIRFileStream, M, IRName);
915 WriteIRToStream(
dbgs(), M, IRName);
919bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
923 StringRef
PassName = PIC->getPassNameForClassName(PassID);
927bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
931 StringRef
PassName = PIC->getPassNameForClassName(PassID);
935bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
936 return shouldPrintBeforeSomePassNumber() &&
940bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
941 return shouldPrintAfterSomePassNumber() &&
945bool PrintIRInstrumentation::shouldPrintPassNumbers() {
946 return Opts.print_pass_numbers;
949bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
953bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
959 this->IRContext = IRContext;
965 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
972 PIC.registerAfterPassCallback(
974 this->printAfterPass(
P,
IR);
976 PIC.registerAfterPassInvalidatedCallback(
978 this->printAfterPassInvalidated(
P);
985 this->IRContext = IRContext;
986 PIC.registerShouldRunOptionalPassCallback(
991 bool ShouldRun =
true;
993 ShouldRun = !
F->hasOptNone();
995 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
999 if (!ShouldRun && DebugLogging) {
1000 errs() <<
"Skipping pass " <<
PassID <<
" on " << getIRName(
IR, IRContext)
1001 <<
" due to optnone attribute\n";
1012 FuncName =
F->getName();
1014 FuncName = L->getHeader()->getParent()->getName();
1018 bool ShouldRun = Context.getOptPassGate().shouldRunPass(
1019 PassName, getIRName(
IR, IRContext), FuncName);
1020 if (!ShouldRun && !this->HasWrittenIR &&
1021 !Opts.opt_bisect_print_ir_path.empty()) {
1024 this->HasWrittenIR =
true;
1025 const Module *M = unwrapModule(
IR,
true);
1026 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1031 M->print(OS,
nullptr);
1038 this->IRContext = IRContext;
1039 const OptPassGate &PassGate = Context.getOptPassGate();
1043 PIC.registerShouldRunOptionalPassCallback(
1062 this->IRContext = IRContext;
1066 std::vector<StringRef> SpecialPasses;
1067 if (!Opts.Verbose) {
1068 SpecialPasses.emplace_back(
"PassManager");
1069 SpecialPasses.emplace_back(
"PassAdaptor");
1075 "Unexpectedly skipping special pass");
1077 print() <<
"Skipping pass: " <<
PassID <<
" on "
1078 << getIRName(
IR, this->IRContext) <<
"\n";
1080 PIC.registerBeforeNonSkippedPassCallback(
1086 OS <<
"Running pass: " <<
PassID <<
" on "
1087 << getIRName(
IR, this->IRContext);
1089 unsigned Count =
F->getInstructionCount();
1090 OS <<
" (" <<
Count <<
" instruction";
1096 OS <<
" (" <<
Count <<
" node";
1104 PIC.registerAfterPassCallback(
1112 PIC.registerAfterPassInvalidatedCallback(
1120 if (!Opts.SkipAnalyses) {
1122 print() <<
"Running analysis: " <<
PassID <<
" on "
1123 << getIRName(
IR, this->IRContext) <<
"\n";
1126 PIC.registerAfterAnalysisCallback(
1128 PIC.registerAnalysisInvalidatedCallback(
1130 print() <<
"Invalidating analysis: " <<
PassID <<
" on "
1131 << getIRName(
IR, this->IRContext) <<
"\n";
1133 PIC.registerAnalysesClearedCallback([
this](
StringRef IRName) {
1134 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1140 bool TrackBBLifetime) {
1141 if (TrackBBLifetime)
1143 for (
const auto &BB : *
F) {
1145 BBGuards->try_emplace(intptr_t(&BB), &BB);
1149 BBGuards->try_emplace(intptr_t(Succ), Succ);
1156 out << BB->
getName() <<
"<" << BB <<
">";
1161 out <<
"unnamed_removed<" << BB <<
">";
1167 <<
"<" << BB <<
">";
1171 unsigned FuncOrderBlockNum = 0;
1175 FuncOrderBlockNum++;
1177 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1185 out <<
"Some blocks were deleted\n";
1190 if (Before.
Graph.size() != After.
Graph.size())
1191 out <<
"Different number of non-leaf basic blocks: before="
1192 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1194 for (
auto &BB : Before.
Graph) {
1195 auto BA = After.
Graph.find(BB.first);
1196 if (BA == After.
Graph.end()) {
1197 out <<
"Non-leaf block ";
1199 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1203 for (
auto &BA : After.
Graph) {
1204 auto BB = Before.
Graph.find(BA.first);
1205 if (BB == Before.
Graph.end()) {
1206 out <<
"Non-leaf block ";
1208 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1212 if (BB->second == BA.second)
1215 out <<
"Different successors of block ";
1217 out <<
" (unordered):\n";
1218 out <<
"- before (" << BB->second.size() <<
"): ";
1219 for (
auto &SuccB : BB->second) {
1221 if (SuccB.second != 1)
1222 out <<
"(" << SuccB.second <<
"), ";
1227 out <<
"- after (" << BA.second.size() <<
"): ";
1228 for (
auto &SuccA : BA.second) {
1230 if (SuccA.second != 1)
1231 out <<
"(" << SuccA.second <<
"), ";
1302 FunctionAnalysisManager::Invalidator &) {
1312 Functions.push_back(
const_cast<Function *
>(MaybeF));
1315 Functions.push_back(&
F);
1322#ifdef EXPENSIVE_CHECKS
1323 constexpr bool VerifyByDefault =
true;
1325 constexpr bool VerifyByDefault =
false;
1327 if (!
valueOr(Opts.verify_analysis_invalidation, VerifyByDefault))
1330 bool Registered =
false;
1331 PIC.registerBeforeNonSkippedPassCallback([
this, &
MAM,
1334#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1335 assert(&PassStack.emplace_back(
P));
1340 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1356 auto &M = *
const_cast<Module *
>(MPtr);
1361 PIC.registerAfterPassInvalidatedCallback(
1363#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1364 assert(PassStack.pop_back_val() ==
P &&
1365 "Before and After callbacks must correspond");
1372#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1373 assert(PassStack.pop_back_val() ==
P &&
1374 "Before and After callbacks must correspond");
1382 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1386 if (
auto *HashBefore =
1390 "Function @{0} changed by {1} without invalidating analyses",
1396 const CFG &GraphBefore,
const CFG &GraphAfter) {
1397 if (GraphAfter == GraphBefore)
1401 <<
"Error: " <<
Pass
1402 <<
" does not invalidate CFG analyses but CFG changes detected in "
1404 << FuncName <<
":\n";
1409 if (
auto *GraphBefore =
1411 CheckCFG(
P,
F->getName(), *GraphBefore,
1415 auto &M = *
const_cast<Module *
>(MPtr);
1416 if (
auto *HashBefore =
1420 "Module changed by {0} without invalidating analyses",
P));
1429 PIC.registerAfterPassCallback(
1431 if (isIgnored(
P) ||
P ==
"VerifierPass")
1436 F = L->getHeader()->getParent();
1441 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1445 "\"{0}\", compilation aborted!",
1451 M =
C->begin()->getFunction().getParent();
1456 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1460 "\"{0}\", compilation aborted!",
1466 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1467 std::string Banner =
1468 formatv(
"Broken machine function found after pass "
1469 "\"{0}\", compilation aborted!",
1499 formatv(
"*** IR Dump After {0} on {1} ***\n",
PassID, Name);
1503 [&](
bool InModule,
unsigned Minor,
1507 Minor, Before, After);
1518 Out <<
"\n*** IR for function " << Name <<
" ***\n";
1525 const std::string Removed =
1526 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1527 const std::string Added =
UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1528 const std::string NoChange =
" %l\n";
1545 this->IRContext = IRContext;
1548 PIC.registerBeforeNonSkippedPassCallback(
1550 PIC.registerAfterPassCallback(
1552 this->runAfterPass();
1555 PIC.registerAfterPassInvalidatedCallback(
1558 PIC.registerBeforeAnalysisCallback(
1560 PIC.registerAfterAnalysisCallback(
1573class DotCfgDiffDisplayGraph;
1576class DisplayElement {
1579 StringRef getColour()
const {
return Colour; }
1582 DisplayElement(StringRef Colour) : Colour(Colour) {}
1583 const StringRef Colour;
1588class DisplayEdge :
public DisplayElement {
1590 DisplayEdge(std::string
Value, DisplayNode &Node, StringRef Colour)
1595 const DisplayNode &getDestinationNode()
const {
return Node; }
1599 const DisplayNode &
Node;
1603class DisplayNode :
public DisplayElement {
1607 DisplayNode(std::string Content, StringRef Colour)
1608 : DisplayElement(Colour), Content(Content) {}
1611 using ChildIterator = SmallPtrSet<DisplayNode *, 0>::const_iterator;
1612 ChildIterator children_begin()
const {
return Children.begin(); }
1613 ChildIterator children_end()
const {
return Children.end(); }
1616 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1617 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1618 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1621 void createEdge(StringRef
Value, DisplayNode &Node, StringRef Colour);
1624 std::string getContent()
const {
return Content; }
1627 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1628 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1629 return *EdgeMap.find(&To)->second;
1634 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1635 return getEdge(Sink).getValue();
1638 void createEdgeMap();
1641 const std::string Content;
1646 std::vector<DisplayEdge> Edges;
1648 std::vector<DisplayEdge *> EdgePtrs;
1649 SmallPtrSet<DisplayNode *, 0>
Children;
1650 DenseMap<const DisplayNode *, const DisplayEdge *> EdgeMap;
1653 bool AllEdgesCreated =
false;
1657class DotCfgDiffDisplayGraph {
1659 DotCfgDiffDisplayGraph(std::string Name) : GraphName(
Name) {}
1662 void generateDotFile(StringRef DotFile);
1665 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1666 NodeIterator nodes_begin()
const {
1667 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1668 return NodePtrs.cbegin();
1670 NodeIterator nodes_end()
const {
1671 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1672 return NodePtrs.cend();
1677 void setEntryNode(
unsigned N) {
1679 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1680 NodeGenerationComplete =
true;
1681 for (
auto &
N : Nodes)
1682 NodePtrs.emplace_back(&
N);
1684 EntryNode = NodePtrs[
N];
1688 void createNode(std::string
C, StringRef Colour) {
1689 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1690 Nodes.emplace_back(
C, Colour);
1694 assert(
N < Nodes.size() &&
"Node is out of bounds");
1697 unsigned size()
const {
1698 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1699 return Nodes.size();
1703 std::string getGraphName()
const {
return GraphName; }
1707 std::string
getNodeLabel(
const DisplayNode &Node)
const {
1708 return Node.getContent();
1712 std::string getNodeAttributes(
const DisplayNode &Node)
const {
1713 return attribute(
Node.getColour());
1717 std::string getEdgeColorAttr(
const DisplayNode &From,
1718 const DisplayNode &To)
const {
1719 return attribute(From.getEdge(To).getColour());
1723 DisplayNode *getEntryNode()
const {
1724 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1730 std::string attribute(StringRef Colour)
const {
1731 return "color=" + Colour.
str();
1734 bool NodeGenerationComplete =
false;
1735 const std::string GraphName;
1736 std::vector<DisplayNode> Nodes;
1737 std::vector<DisplayNode *> NodePtrs;
1738 DisplayNode *EntryNode =
nullptr;
1741void DisplayNode::createEdge(StringRef
Value, DisplayNode &Node,
1743 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1744 Edges.emplace_back(
Value.str(), Node, Colour);
1748void DisplayNode::createEdgeMap() {
1751 AllEdgesCreated =
true;
1752 for (
auto &
E : Edges)
1753 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1756class DotCfgDiffNode;
1760class DotCfgDiffNode {
1762 DotCfgDiffNode() =
delete;
1766 DotCfgDiffNode(
const PassesOptions &Opts, DotCfgDiff &
G,
unsigned N,
1767 const BlockDataT<DCData> &BD, StringRef Colour)
1768 : Opts(Opts),
Graph(
G),
N(
N),
Data{&BD, nullptr}, Colour(Colour) {}
1769 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1774 unsigned getIndex()
const {
return N; }
1777 StringRef getLabel()
const {
1778 assert(
Data[0] &&
"Expected Data[0] to be set.");
1779 return Data[0]->getLabel();
1782 StringRef getColour()
const {
return Colour; }
1785 void setCommon(
const BlockDataT<DCData> &
Other) {
1786 assert(!
Data[1] &&
"Expected only one block datum");
1788 Colour = Opts.dot_cfg_common_color;
1791 void addEdge(
unsigned E, StringRef
Value, StringRef Colour) {
1793 assert((EdgesMap.count(
E) == 0 || Colour == Opts.dot_cfg_common_color) &&
1794 "Unexpected edge count and color.");
1795 EdgesMap[
E] = {
Value.str(), Colour};
1801 StringRef getEdgeColour(
const unsigned S)
const {
1802 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1803 return EdgesMap.at(S).second;
1807 std::string getBodyContent()
const;
1809 void createDisplayEdges(DotCfgDiffDisplayGraph &
Graph,
unsigned DisplayNode,
1810 std::map<const unsigned, unsigned> &NodeMap)
const;
1813 const PassesOptions &Opts;
1816 const BlockDataT<DCData> *
Data[2];
1818 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1820 std::vector<unsigned> Edges;
1830 DotCfgDiff(
const PassesOptions &Opts, StringRef Title,
1831 const FuncDataT<DCData> &Before,
const FuncDataT<DCData> &After);
1833 DotCfgDiff(
const DotCfgDiff &) =
delete;
1834 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1836 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,
1837 StringRef EntryNodeName);
1843 StringRef getEdgeSourceLabel(
const unsigned &Source,
1844 const unsigned &Sink)
const {
1846 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1847 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1848 return EdgeLabels.find(S)->getValue();
1852 unsigned size()
const {
return Nodes.size(); }
1854 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1855 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1861 std::string colourize(std::string S, StringRef Colour)
const;
1863 void createNode(StringRef Label,
const BlockDataT<DCData> &BD, StringRef
C) {
1864 unsigned Pos = Nodes.size();
1865 Nodes.emplace_back(Opts, *
this, Pos, BD,
C);
1866 NodePosition.insert({
Label, Pos});
1869 const PassesOptions &Opts;
1873 std::vector<DotCfgDiffNode> Nodes;
1874 StringMap<unsigned> NodePosition;
1875 const std::string GraphName;
1877 StringMap<std::string> EdgeLabels;
1880std::string DotCfgDiffNode::getBodyContent()
const {
1881 if (Colour == Opts.dot_cfg_common_color) {
1882 assert(
Data[1] &&
"Expected Data[1] to be set.");
1885 for (
unsigned I = 0;
I < 2; ++
I) {
1886 SR[
I] =
Data[
I]->getBody();
1890 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1893 SmallString<80> OldLineFormat =
1894 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1895 Opts.dot_cfg_before_color);
1896 SmallString<80> NewLineFormat =
1897 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1898 Opts.dot_cfg_after_color);
1899 SmallString<80> UnchangedLineFormat =
1900 formatv(
"<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
1901 Opts.dot_cfg_common_color);
1902 std::string Diff =
Data[0]->getLabel().str();
1903 Diff +=
":\n<BR align=\"left\"/>" +
1904 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1905 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1910 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1913 std::string S =
R.sub(
"", Diff, &
Error);
1924 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1925 std::string Body = makeHTMLReady(
Data[0]->getBody());
1926 const StringRef BS = Body;
1929 if (BS.
front() ==
'\n')
1934 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1936 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1939 while (BS1.
size()) {
1940 S.append(
"<BR align=\"left\"/>");
1942 S.append(
Line.str());
1945 S.append(
"<BR align=\"left\"/></FONT>");
1949std::string DotCfgDiff::colourize(std::string S, StringRef Colour)
const {
1950 if (S.length() == 0)
1952 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1955DotCfgDiff::DotCfgDiff(
const PassesOptions &Opts, StringRef Title,
1956 const FuncDataT<DCData> &Before,
1957 const FuncDataT<DCData> &After)
1958 : Opts(Opts), GraphName(Title.str()) {
1959 StringMap<StringRef> EdgesMap;
1963 StringRef Label = B.getKey();
1964 const BlockDataT<DCData> &BD = B.getValue();
1965 createNode(Label, BD, Opts.dot_cfg_before_color);
1969 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1970 E = BD.getData().end();
1971 Sink != E; ++Sink) {
1972 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1973 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1974 EdgesMap.insert({Key, Opts.dot_cfg_before_color});
1980 StringRef Label = A.getKey();
1981 const BlockDataT<DCData> &BD = A.getValue();
1982 auto It = NodePosition.find(Label);
1983 if (It == NodePosition.end())
1985 createNode(Label, BD, Opts.dot_cfg_after_color);
1987 Nodes[It->second].setCommon(BD);
1989 for (StringMap<std::string>::const_iterator Sink = BD.getData().begin(),
1990 E = BD.getData().end();
1991 Sink != E; ++Sink) {
1992 std::string Key = (Label +
" " + Sink->getKey().str()).str() +
" " +
1993 BD.getData().getSuccessorLabel(Sink->getKey()).str();
1994 auto [It, Inserted] = EdgesMap.try_emplace(Key, Opts.dot_cfg_after_color);
1996 It->second = Opts.dot_cfg_common_color;
2001 for (
auto &
E : EdgesMap) {
2004 auto SP1 = S.
rsplit(
' ');
2005 auto &SourceSink = SP1.first;
2006 auto SP2 = SourceSink.split(
' ');
2011 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2012 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2013 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2014 unsigned SinkNode = NodePosition[Sink];
2018 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2020 It->getValue() = colourize(
Value.str(), Colour);
2023 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2024 Colour = Opts.dot_cfg_common_color;
2025 It->getValue() =
NV;
2027 SourceNode.addEdge(SinkNode,
Value, Colour);
2029 for (
auto &
I : Nodes)
2033DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2035 assert(NodePosition.count(EntryNodeName) == 1 &&
2036 "Expected to find entry block in map.");
2037 unsigned Entry = NodePosition[EntryNodeName];
2038 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2039 DotCfgDiffDisplayGraph
G(Title.
str());
2041 std::map<const unsigned, unsigned> NodeMap;
2043 int EntryIndex = -1;
2045 for (
auto &
I : Nodes) {
2046 if (
I.getIndex() == Entry)
2048 G.createNode(
I.getBodyContent(),
I.getColour());
2049 NodeMap.insert({
I.getIndex(),
Index++});
2051 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2052 G.setEntryNode(EntryIndex);
2054 for (
auto &
I : NodeMap) {
2055 unsigned SourceNode =
I.first;
2056 unsigned DisplayNode =
I.second;
2057 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2062void DotCfgDiffNode::createDisplayEdges(
2063 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2064 std::map<const unsigned, unsigned> &NodeMap)
const {
2066 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2068 for (
auto I : Edges) {
2069 unsigned SinkNodeIndex =
I;
2070 StringRef Colour = getEdgeColour(SinkNodeIndex);
2071 const DotCfgDiffNode *SinkNode = &
Graph.getNode(SinkNodeIndex);
2074 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2075 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2077 SourceDisplayNode.createEdgeMap();
2080void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2081 for (
auto E : EdgesMap) {
2083 Edges.emplace_back(
E.first);
2099 return G->getEntryNode();
2102 return N->children_begin();
2106 return G->nodes_begin();
2109 return G->nodes_end();
2112 return N->edges_begin();
2116 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2126 return DiffData->getGraphName();
2130 return "\tsize=\"190, 190\";\n";
2133 const DotCfgDiffDisplayGraph *DiffData) {
2134 return DiffData->getNodeLabel(*
Node);
2137 const DotCfgDiffDisplayGraph *DiffData) {
2138 return DiffData->getNodeAttributes(*
Node);
2141 DisplayNode::ChildIterator &To) {
2142 return From->getEdgeSourceLabel(**To);
2145 DisplayNode::ChildIterator &To,
2146 const DotCfgDiffDisplayGraph *DiffData) {
2147 return DiffData->getEdgeColorAttr(*From, **To);
2155void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {
2157 raw_fd_ostream OutStream(DotFile, EC);
2159 errs() <<
"Error: " <<
EC.message() <<
"\n";
2180 for (
auto &
C : Sw->cases()) {
2181 assert(
C.getCaseValue() &&
"Expected to find case value.");
2203 assert(
HTML &&
"Expected outstream to be set");
2208 Extender =
formatv(
"{0}_{1}",
N, Minor);
2217 std::string DotFile =
Twine(SV).
str();
2225 DotCfgDiff Diff(
Opts,
Text, Before, After);
2228 if (EntryBlockName ==
"")
2230 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2232 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(
Text, EntryBlockName);
2233 DG.generateDotFile(DotFile);
2238 errs() <<
"Error: " << EC.message() <<
"\n";
2248 return "Unable to find dot executable.";
2250 StringRef Args[] = {
Opts.print_changed_dot_path,
"-Tpdf",
"-o", PDFFile,
2254 return "Error executing system dot.";
2258 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName,
Text);
2263 assert(
HTML &&
"Expected outstream to be set");
2264 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2265 <<
"Initial IR (by function)</button>\n"
2266 <<
"<div class=\"content\">\n"
2275 [&](
bool InModule,
unsigned Minor,
2279 Minor, Before, After);
2293 assert(
HTML &&
"Expected outstream to be set");
2295 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2296 N, makeHTMLReady(
PassID), Name);
2305 assert(
HTML &&
"Expected outstream to be set");
2308 [&](
bool InModule,
unsigned Minor,
2312 Minor, Before, After);
2314 *
HTML <<
" </p></div>\n";
2319 assert(
HTML &&
"Expected outstream to be set");
2321 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(
PassID));
2327 assert(
HTML &&
"Expected outstream to be set");
2329 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2330 makeHTMLReady(
PassID), Name);
2336 assert(
HTML &&
"Expected outstream to be set");
2338 makeHTMLReady(
PassID), Name);
2345 HTML = std::make_unique<raw_fd_ostream>(
OutputDir +
"/passes.html", EC);
2351 *
HTML <<
"<!doctype html>"
2354 <<
"<style>.collapsible { "
2355 <<
"background-color: #777;"
2357 <<
" cursor: pointer;"
2358 <<
" padding: 18px;"
2361 <<
" text-align: left;"
2362 <<
" outline: none;"
2363 <<
" font-size: 15px;"
2364 <<
"} .active, .collapsible:hover {"
2365 <<
" background-color: #555;"
2367 <<
" padding: 0 18px;"
2368 <<
" display: none;"
2369 <<
" overflow: hidden;"
2370 <<
" background-color: #f1f1f1;"
2373 <<
"<title>passes.html</title>"
2383 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2385 <<
"for (i = 0; i < coll.length; i++) {"
2386 <<
"coll[i].addEventListener(\"click\", function() {"
2387 <<
" this.classList.toggle(\"active\");"
2388 <<
" var content = this.nextElementSibling;"
2389 <<
" if (content.style.display === \"block\"){"
2390 <<
" content.style.display = \"none\";"
2393 <<
" content.style.display= \"block\";"
2411 assert(!Dir.
empty() &&
"expected output dir to be non-empty");
2417 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2422 LLVMContext &Context,
bool DebugLogging,
bool VerifyEach,
2425 PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2426 OptPassGate(Opts, Context), PreservedCFGChecker(Opts),
2433 PrintCrashIR(Opts), ChangeTester(Opts), Verify(DebugLogging),
2434 DroppedStatsIR(Opts.dropped_variable_stats), VerifyEach(VerifyEach) {}
2440 if (!
Opts.print_on_crash_path.empty()) {
2451void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2457 assert((CrashReporter->
Opts.print_on_crash ||
2458 !CrashReporter->
Opts.print_on_crash_path.empty()) &&
2459 "Did not expect to get here without option set.");
2467 assert((CrashReporter->Opts.print_on_crash ||
2468 !CrashReporter->Opts.print_on_crash_path.empty()) &&
2469 "Did not expect to get here without option set.");
2470 CrashReporter =
nullptr;
2475 if ((!
Opts.print_on_crash &&
Opts.print_on_crash_path.empty()) ||
2480 CrashReporter =
this;
2482 PIC.registerBeforeNonSkippedPassCallback(
2486 OS <<
formatv(
"; *** Dump of {0}IR Before Last Pass {1}",
2489 OS <<
" Filtered Out ***\n";
2492 OS <<
" Started ***\n";
2493 unwrapAndPrint(OS,
IR);
2500 if (Opts.instnamer_after_each_pass)
2502 PrintIR.registerCallbacks(
PIC, IRContext);
2503 PrintPass.registerCallbacks(
PIC, IRContext);
2504 TimePasses.registerCallbacks(
PIC);
2505 OptNone.registerCallbacks(
PIC, IRContext);
2506 OptPassGate.registerCallbacks(
PIC, IRContext);
2507 PrintChangedIR.registerCallbacks(
PIC);
2508 PseudoProbeVerification.registerCallbacks(
PIC);
2510 Verify.registerCallbacks(
PIC,
MAM);
2511 PrintChangedDiff.registerCallbacks(
PIC);
2512 WebsiteChangeReporter.registerCallbacks(
PIC);
2513 ChangeTester.registerCallbacks(
PIC);
2514 PrintCrashIR.registerCallbacks(
PIC);
2515 DroppedStatsIR.registerCallbacks(
PIC);
2517 PreservedCFGChecker.registerCallbacks(
PIC, *
MAM);
2525 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 handleInitialIR(IRUnitRef IR)=0
virtual void generateIRRepresentation(IRUnitRef IR, StringRef PassID, std::string &Output)=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 std::string &Before, const std::string &After, IRUnitRef)=0
virtual void handleInvalidated(StringRef PassID)=0
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
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)
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.
const PassesOptions & getPassesOptions(const LLVMContext &C)
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.