43#include <unordered_map>
44#include <unordered_set>
52#ifdef EXPENSIVE_CHECKS
64 cl::desc(
"Print before passes that change them"),
71 cl::desc(
"system dot used by change reporters"));
99 cl::desc(
"Generate dot files into specified directory for changed IRs"),
104 "print-on-crash-path",
105 cl::desc(
"Print the last form of the IR before crash to a file"),
110 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
114 "opt-bisect-print-ir-path",
119 cl::desc(
"Print pass names and their ordinals"));
123 cl::desc(
"Print IR before the passes with specified numbers as "
124 "reported by print-pass-numbers"));
128 cl::desc(
"Print IR after the passes with specified numbers as "
129 "reported by print-pass-numbers"));
133 cl::desc(
"If specified, IR printed using the "
134 "-print-[before|after]{-all} options will be dumped into "
135 "files in this directory rather than written to stderr"),
140 cl::desc(
"Dump dropped debug variables stats"),
144 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&
IR);
145 return IRPtr ? *IRPtr :
nullptr;
159 cl::desc(
"exe called with module IR after each pass that "
164const Module *unwrapModule(
Any IR,
bool Force =
false) {
165 if (
const auto *M = unwrapIR<Module>(
IR))
168 if (
const auto *
F = unwrapIR<Function>(
IR)) {
172 return F->getParent();
175 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
179 return F.getParent();
182 assert(!Force &&
"Expected a module");
186 if (
const auto *L = unwrapIR<Loop>(
IR)) {
187 const Function *
F =
L->getHeader()->getParent();
190 return F->getParent();
193 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
196 return MF->getFunction().getParent();
210 M->print(
OS,
nullptr);
212 for (
const auto &
F :
M->functions()) {
228 const Function *
F = L->getHeader()->getParent();
240std::string getIRName(
Any IR) {
241 if (unwrapIR<Module>(
IR))
244 if (
const auto *
F = unwrapIR<Function>(
IR))
245 return F->getName().str();
247 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
250 if (
const auto *L = unwrapIR<Loop>(
IR))
251 return "loop %" + L->getName().str() +
" in function " +
252 L->getHeader()->getParent()->getName().str();
254 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
260bool moduleContainsFilterPrintFunc(
const Module &M) {
263 return isFunctionInPrintList(F.getName());
276bool shouldPrintIR(
Any IR) {
277 if (
const auto *M = unwrapIR<Module>(
IR))
278 return moduleContainsFilterPrintFunc(*M);
280 if (
const auto *
F = unwrapIR<Function>(
IR))
283 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
284 return sccContainsFilterPrintFunc(*
C);
286 if (
const auto *L = unwrapIR<Loop>(
IR))
289 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
297 if (!shouldPrintIR(
IR))
301 auto *M = unwrapModule(
IR);
302 assert(M &&
"should have unwrapped module");
307 if (
const auto *M = unwrapIR<Module>(
IR)) {
312 if (
const auto *
F = unwrapIR<Function>(
IR)) {
317 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
322 if (
const auto *L = unwrapIR<Loop>(
IR)) {
327 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
337 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
338 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
339 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
340 "PrintMIRPreparePass"});
348 S.append(Clean.
str());
352 S.append(SR[0] ==
'<' ?
"<" :
">");
360 if (
const auto *M = unwrapIR<Module>(
IR))
362 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
363 return C->begin()->getFunction().getParent();
367bool isInterestingFunction(
const Function &
F) {
376 if (
const auto *
F = unwrapIR<Function>(
IR))
377 return isInterestingFunction(*
F);
384 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
400 BeforeStack.emplace_back();
406 T &Data = BeforeStack.back();
407 generateIRRepresentation(
IR, PassID, Data);
413 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
415 std::string
Name = getIRName(
IR);
417 if (isIgnored(PassID)) {
419 handleIgnored(PassID,
Name);
422 handleFiltered(PassID,
Name);
425 T &Before = BeforeStack.back();
428 generateIRRepresentation(
IR, PassID, After);
431 if (Before == After) {
433 omitAfter(PassID,
Name);
435 handleAfter(PassID,
Name, Before, After,
IR);
437 BeforeStack.pop_back();
442 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
449 handleInvalidated(PassID);
450 BeforeStack.pop_back();
466 handleInvalidatedPass(
P);
477 auto *M = unwrapModule(
IR,
true);
478 assert(M &&
"Expected module to be unwrapped when forced.");
479 Out <<
"*** IR Dump At Start ***\n";
480 M->print(Out,
nullptr);
485 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
491 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
498 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
504 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
516 std::string &Output) {
518 unwrapAndPrint(
OS,
IR);
523 const std::string &Before,
524 const std::string &After,
Any) {
527 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
533 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
537 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" << After;
543 if (TestChanged !=
"")
553 dbgs() <<
"Unable to create temporary file.";
558 dbgs() <<
"Unable to find test-changed executable.";
562 StringRef Args[] = {TestChanged, FileName[0], PassID};
565 dbgs() <<
"Error executing test-changed executable.";
570 dbgs() <<
"Unable to remove temporary file.";
586 const std::string &Before,
587 const std::string &After,
Any) {
595 const auto &BFD = Before.
getData();
596 const auto &AFD = After.
getData();
597 std::vector<std::string>::const_iterator BI = Before.
getOrder().begin();
598 std::vector<std::string>::const_iterator BE = Before.
getOrder().end();
599 std::vector<std::string>::const_iterator AI = After.
getOrder().begin();
600 std::vector<std::string>::const_iterator AE = After.
getOrder().end();
602 auto HandlePotentiallyRemovedData = [&](std::string S) {
606 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
609 auto HandleNewData = [&](std::vector<const T *> &Q) {
611 for (
const T *NBI : Q)
612 HandlePair(
nullptr, NBI);
625 std::vector<const T *> NewDataQueue;
627 if (!BFD.count(*AI)) {
630 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
639 while (BI != BE && *BI != *AI) {
640 HandlePotentiallyRemovedData(*BI);
644 HandleNewData(NewDataQueue);
646 const T &AData = AFD.find(*AI)->getValue();
647 const T &BData = BFD.find(*AI)->getValue();
648 HandlePair(&BData, &AData);
656 HandlePotentiallyRemovedData(*BI);
660 HandleNewData(NewDataQueue);
666 std::function<
void(
bool InModule,
unsigned Minor,
669 if (!CompareModule) {
672 "Expected only one function.");
673 CompareFunc(
false, 0, Before.
getData().
begin()->getValue(),
682 assert((
B ||
A) &&
"Both functions cannot be missing.");
687 CompareFunc(
true, Minor++, *
B, *
A);
692 if (
const Module *M = getModuleForComparison(
IR)) {
695 generateFunctionData(
Data,
F);
699 if (
const auto *
F = unwrapIR<Function>(
IR)) {
700 generateFunctionData(
Data, *
F);
704 if (
const auto *L = unwrapIR<Loop>(
IR)) {
705 auto *
F = L->getHeader()->getParent();
706 generateFunctionData(
Data, *
F);
710 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
711 generateFunctionData(
Data, *MF);
727template <
typename FunctionT>
732 for (
const auto &
B :
F) {
733 std::string BBName =
B.getName().str();
734 if (BBName.empty()) {
741 Data.getOrder().emplace_back(
F.getName());
742 Data.getData().insert({
F.getName(), FD});
750 "PassRunDescriptorStack is not empty at exit");
754 const Module *M = unwrapModule(
IR,
true);
755 assert(M &&
"should have unwrapped module");
757 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
759 if (unwrapIR<Module>(
IR)) {
760 ResultStream <<
"-module";
761 }
else if (
const auto *
F = unwrapIR<Function>(
IR)) {
762 ResultStream <<
"-function-";
766 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
767 ResultStream <<
"-scc-";
770 }
else if (
const auto *L = unwrapIR<Loop>(
IR)) {
771 ResultStream <<
"-loop-";
774 }
else if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
775 ResultStream <<
"-machine-function-";
791StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType
Type) {
792 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
794 return FileSuffixes[
static_cast<size_t>(
Type)];
797std::string PrintIRInstrumentation::fetchDumpFilename(
799 IRDumpFileSuffixType SuffixType) {
801 "The flag -ir-dump-directory must be passed to dump IR to files");
805 FilenameStream << PassNumber;
806 FilenameStream <<
'-' << IRFileDisplayName <<
'-';
808 FilenameStream << getFileSuffix(SuffixType);
812 return std::string(ResultPath);
815void PrintIRInstrumentation::pushPassRunDescriptor(
StringRef PassID,
Any IR,
816 unsigned PassNumber) {
819 getIRName(
IR), PassID);
822PrintIRInstrumentation::PassRunDescriptor
823PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
824 assert(!PassRunDescriptorStack.
empty() &&
"empty PassRunDescriptorStack");
825 PassRunDescriptor Descriptor = PassRunDescriptorStack.
pop_back_val();
826 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
834 if (!ParentPath.empty()) {
838 " to support -ir-dump-directory: " + EC.message());
845 " to support -ir-dump-directory: " + EC.message());
849void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
850 if (isIgnored(PassID))
857 if (shouldPrintAfterPass(PassID))
858 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
860 if (!shouldPrintIR(
IR))
865 if (shouldPrintPassNumbers())
866 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
867 <<
" on " << getIRName(
IR) <<
"\n";
869 if (shouldPrintAfterCurrentPassNumber())
870 pushPassRunDescriptor(PassID,
IR, CurrentPassNumber);
872 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
876 Stream <<
"; *** IR Dump Before ";
877 if (shouldPrintBeforeSomePassNumber())
878 Stream << CurrentPassNumber <<
"-";
879 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
880 unwrapAndPrint(Stream,
IR);
884 std::string DumpIRFilename =
886 IRDumpFileSuffixType::Before);
889 WriteIRToStream(DumpIRFileStream);
891 WriteIRToStream(
dbgs());
895void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
896 if (isIgnored(PassID))
899 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
902 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
903 popPassRunDescriptor(PassID);
904 assert(StoredPassID == PassID &&
"mismatched PassID");
906 if (!shouldPrintIR(
IR) ||
907 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
911 Stream <<
"; *** IR Dump After ";
912 if (shouldPrintAfterSomePassNumber())
913 Stream << CurrentPassNumber <<
"-";
914 Stream <<
StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
915 unwrapAndPrint(Stream,
IR);
919 std::string DumpIRFilename =
921 IRDumpFileSuffixType::After);
925 WriteIRToStream(DumpIRFileStream, IRName);
927 WriteIRToStream(
dbgs(), IRName);
931void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
932 if (isIgnored(PassID))
935 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
938 auto [
M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =
939 popPassRunDescriptor(PassID);
940 assert(StoredPassID == PassID &&
"mismatched PassID");
944 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
950 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
952 Stream << Banner <<
"\n";
957 std::string DumpIRFilename =
958 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,
959 IRDumpFileSuffixType::Invalidated);
963 WriteIRToStream(DumpIRFileStream, M, IRName);
965 WriteIRToStream(
dbgs(), M, IRName);
969bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
977bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
985bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
986 return shouldPrintBeforeSomePassNumber() &&
990bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
991 return shouldPrintAfterSomePassNumber() &&
995bool PrintIRInstrumentation::shouldPrintPassNumbers() {
999bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1003bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1014 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1023 this->printAfterPass(
P,
IR);
1027 this->printAfterPassInvalidated(
P);
1038bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
1039 bool ShouldRun =
true;
1040 if (
const auto *
F = unwrapIR<Function>(
IR))
1041 ShouldRun = !
F->hasOptNone();
1042 else if (
const auto *L = unwrapIR<Loop>(
IR))
1043 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1044 else if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
1047 if (!ShouldRun && DebugLogging) {
1048 errs() <<
"Skipping pass " << PassID <<
" on " << getIRName(
IR)
1049 <<
" due to optnone attribute\n";
1063 this->HasWrittenIR =
true;
1064 const Module *M = unwrapModule(
IR,
true);
1065 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1070 M->print(
OS,
nullptr);
1085 return this->shouldRun(ClassName,
IR);
1103 std::vector<StringRef> SpecialPasses;
1105 SpecialPasses.emplace_back(
"PassManager");
1106 SpecialPasses.emplace_back(
"PassAdaptor");
1112 "Unexpectedly skipping special pass");
1114 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1122 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1123 if (
const auto *
F = unwrapIR<Function>(
IR)) {
1124 unsigned Count =
F->getInstructionCount();
1125 OS <<
" (" << Count <<
" instruction";
1129 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
1130 int Count =
C->size();
1131 OS <<
" (" << Count <<
" node";
1157 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1164 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1168 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1174 bool TrackBBLifetime) {
1175 if (TrackBBLifetime)
1177 for (
const auto &BB : *
F) {
1179 BBGuards->try_emplace(intptr_t(&BB), &BB);
1183 BBGuards->try_emplace(intptr_t(Succ), Succ);
1190 out << BB->
getName() <<
"<" << BB <<
">";
1195 out <<
"unnamed_removed<" << BB <<
">";
1201 <<
"<" << BB <<
">";
1205 unsigned FuncOrderBlockNum = 0;
1209 FuncOrderBlockNum++;
1211 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1219 out <<
"Some blocks were deleted\n";
1224 if (Before.
Graph.size() != After.
Graph.size())
1225 out <<
"Different number of non-leaf basic blocks: before="
1226 << Before.
Graph.size() <<
", after=" << After.
Graph.size() <<
"\n";
1228 for (
auto &BB : Before.
Graph) {
1229 auto BA = After.
Graph.find(BB.first);
1230 if (BA == After.
Graph.end()) {
1231 out <<
"Non-leaf block ";
1233 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1237 for (
auto &BA : After.
Graph) {
1238 auto BB = Before.
Graph.find(BA.first);
1239 if (BB == Before.
Graph.end()) {
1240 out <<
"Non-leaf block ";
1242 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1246 if (BB->second == BA.second)
1249 out <<
"Different successors of block ";
1251 out <<
" (unordered):\n";
1252 out <<
"- before (" << BB->second.size() <<
"): ";
1253 for (
auto &SuccB : BB->second) {
1255 if (SuccB.second != 1)
1256 out <<
"(" << SuccB.second <<
"), ";
1261 out <<
"- after (" << BA.second.size() <<
"): ";
1262 for (
auto &SuccA : BA.second) {
1264 if (SuccA.second != 1)
1265 out <<
"(" << SuccA.second <<
"), ";
1345 if (
const auto *MaybeF = unwrapIR<Function>(
IR)) {
1347 }
else if (
const auto *MaybeM = unwrapIR<Module>(
IR)) {
1359 bool Registered =
false;
1362#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1363 assert(&PassStack.emplace_back(
P));
1368 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1383 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1384 auto &M = *
const_cast<Module *
>(MPtr);
1391#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1392 assert(PassStack.pop_back_val() ==
P &&
1393 "Before and After callbacks must correspond");
1400#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1401 assert(PassStack.pop_back_val() ==
P &&
1402 "Before and After callbacks must correspond");
1410 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1414 if (
auto *HashBefore =
1418 "Function @{0} changed by {1} without invalidating analyses",
1424 const CFG &GraphBefore,
const CFG &GraphAfter) {
1425 if (GraphAfter == GraphBefore)
1429 <<
"Error: " <<
Pass
1430 <<
" does not invalidate CFG analyses but CFG changes detected in "
1432 << FuncName <<
":\n";
1437 if (
auto *GraphBefore =
1439 CheckCFG(
P,
F->getName(), *GraphBefore,
1442 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1443 auto &M = *
const_cast<Module *
>(MPtr);
1444 if (
auto *HashBefore =
1448 "Module changed by {0} without invalidating analyses",
P));
1459 if (isIgnored(
P) ||
P ==
"VerifierPass")
1461 const auto *
F = unwrapIR<Function>(
IR);
1463 if (
const auto *L = unwrapIR<Loop>(
IR))
1464 F = L->getHeader()->getParent();
1469 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1473 "\"{0}\", compilation aborted!",
1476 const auto *M = unwrapIR<Module>(
IR);
1478 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
1479 M =
C->begin()->getFunction().getParent();
1484 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1488 "\"{0}\", compilation aborted!",
1492 if (
auto *MF = unwrapIR<MachineFunction>(
IR)) {
1494 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1495 std::string Banner =
1496 formatv(
"Broken machine function found after pass "
1497 "\"{0}\", compilation aborted!",
1527 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1531 [&](
bool InModule,
unsigned Minor,
1534 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1535 Minor, Before, After);
1546 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1553 const std::string Removed =
1554 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1555 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1556 const std::string NoChange =
" %l\n";
1557 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1579 this->runAfterPass();
1591void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1600class DotCfgDiffDisplayGraph;
1603class DisplayElement {
1606 StringRef getColour()
const {
return Colour; }
1609 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1615class DisplayEdge :
public DisplayElement {
1620 std::string getValue()
const {
return Value; }
1622 const DisplayNode &getDestinationNode()
const {
return Node; }
1626 const DisplayNode &
Node;
1630class DisplayNode :
public DisplayElement {
1638 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1639 ChildIterator children_begin()
const {
return Children.cbegin(); }
1640 ChildIterator children_end()
const {
return Children.cend(); }
1643 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1644 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1645 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1651 std::string getContent()
const {
return Content; }
1654 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1655 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1656 return *EdgeMap.find(&To)->second;
1661 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1662 return getEdge(Sink).getValue();
1665 void createEdgeMap();
1673 std::vector<DisplayEdge> Edges;
1675 std::vector<DisplayEdge *> EdgePtrs;
1676 std::unordered_set<DisplayNode *>
Children;
1677 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1680 bool AllEdgesCreated =
false;
1684class DotCfgDiffDisplayGraph {
1686 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1689 void generateDotFile(
StringRef DotFile);
1692 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1693 NodeIterator nodes_begin()
const {
1694 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1695 return NodePtrs.cbegin();
1697 NodeIterator nodes_end()
const {
1698 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1699 return NodePtrs.cend();
1704 void setEntryNode(
unsigned N) {
1706 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1707 NodeGenerationComplete =
true;
1708 for (
auto &
N : Nodes)
1709 NodePtrs.emplace_back(&
N);
1711 EntryNode = NodePtrs[
N];
1716 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1717 Nodes.emplace_back(
C, Colour);
1721 assert(
N < Nodes.size() &&
"Node is out of bounds");
1724 unsigned size()
const {
1725 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1726 return Nodes.size();
1730 std::string getGraphName()
const {
return GraphName; }
1735 return Node.getContent();
1739 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1740 return attribute(
Node.getColour());
1744 std::string getEdgeColorAttr(
const DisplayNode &
From,
1745 const DisplayNode &To)
const {
1746 return attribute(
From.getEdge(To).getColour());
1750 DisplayNode *getEntryNode()
const {
1751 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1757 std::string attribute(
StringRef Colour)
const {
1758 return "color=" + Colour.
str();
1761 bool NodeGenerationComplete =
false;
1762 const std::string GraphName;
1763 std::vector<DisplayNode> Nodes;
1764 std::vector<DisplayNode *> NodePtrs;
1765 DisplayNode *EntryNode =
nullptr;
1770 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1771 Edges.emplace_back(
Value.str(),
Node, Colour);
1775void DisplayNode::createEdgeMap() {
1778 AllEdgesCreated =
true;
1779 for (
auto &E : Edges)
1780 EdgeMap.insert({&E.getDestinationNode(), &E});
1783class DotCfgDiffNode;
1787class DotCfgDiffNode {
1789 DotCfgDiffNode() =
delete;
1795 : Graph(
G),
N(
N), Data{&BD, nullptr}, Colour(Colour) {}
1796 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1797 : Graph(DN.Graph),
N(DN.
N), Data{DN.Data[0], DN.Data[1]},
1801 unsigned getIndex()
const {
return N; }
1805 assert(Data[0] &&
"Expected Data[0] to be set.");
1806 return Data[0]->getLabel();
1809 StringRef getColour()
const {
return Colour; }
1813 assert(!Data[1] &&
"Expected only one block datum");
1821 "Unexpected edge count and color.");
1822 EdgesMap[
E] = {
Value.str(), Colour};
1828 StringRef getEdgeColour(
const unsigned S)
const {
1829 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1830 return EdgesMap.at(S).second;
1834 std::string getBodyContent()
const;
1836 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1837 std::map<const unsigned, unsigned> &NodeMap)
const;
1844 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1846 std::vector<unsigned> Edges;
1859 DotCfgDiff(
const DotCfgDiff &) =
delete;
1860 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1862 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1869 StringRef getEdgeSourceLabel(
const unsigned &Source,
1870 const unsigned &Sink)
const {
1872 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1873 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1874 return EdgeLabels.find(S)->getValue();
1878 unsigned size()
const {
return Nodes.size(); }
1880 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1881 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1887 std::string colourize(std::string S,
StringRef Colour)
const;
1890 unsigned Pos = Nodes.size();
1891 Nodes.emplace_back(*
this, Pos, BD,
C);
1892 NodePosition.insert({
Label, Pos});
1898 std::vector<DotCfgDiffNode> Nodes;
1900 const std::string GraphName;
1905std::string DotCfgDiffNode::getBodyContent()
const {
1907 assert(
Data[1] &&
"Expected Data[1] to be set.");
1910 for (
unsigned I = 0;
I < 2; ++
I) {
1911 SR[
I] =
Data[
I]->getBody();
1915 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1919 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1921 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1923 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1924 std::string Diff =
Data[0]->getLabel().str();
1925 Diff +=
":\n<BR align=\"left\"/>" +
1926 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1927 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1932 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1935 std::string S =
R.sub(
"", Diff, &
Error);
1946 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1947 std::string Body = makeHTMLReady(
Data[0]->getBody());
1951 if (BS.
front() ==
'\n')
1956 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1958 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1961 while (BS1.
size()) {
1962 S.append(
"<BR align=\"left\"/>");
1964 S.append(
Line.str());
1967 S.append(
"<BR align=\"left\"/></FONT>");
1971std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1972 if (S.length() == 0)
1974 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1979 : GraphName(Title.str()) {
1992 Sink != E; ++Sink) {
1993 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1994 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2003 auto It = NodePosition.find(Label);
2004 if (It == NodePosition.end())
2008 Nodes[It->second].setCommon(BD);
2013 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
2014 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2022 for (
auto &E : EdgesMap) {
2025 auto SP1 = S.
rsplit(
' ');
2026 auto &SourceSink = SP1.first;
2027 auto SP2 = SourceSink.split(
' ');
2032 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2033 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2034 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2035 unsigned SinkNode = NodePosition[
Sink];
2039 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2041 It->getValue() = colourize(
Value.str(), Colour);
2044 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2046 It->getValue() =
NV;
2048 SourceNode.addEdge(SinkNode,
Value, Colour);
2050 for (
auto &
I : Nodes)
2054DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2056 assert(NodePosition.count(EntryNodeName) == 1 &&
2057 "Expected to find entry block in map.");
2058 unsigned Entry = NodePosition[EntryNodeName];
2059 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2060 DotCfgDiffDisplayGraph
G(Title.
str());
2062 std::map<const unsigned, unsigned> NodeMap;
2064 int EntryIndex = -1;
2066 for (
auto &
I : Nodes) {
2067 if (
I.getIndex() == Entry)
2069 G.createNode(
I.getBodyContent(),
I.getColour());
2070 NodeMap.insert({
I.getIndex(), Index++});
2072 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2073 G.setEntryNode(EntryIndex);
2075 for (
auto &
I : NodeMap) {
2076 unsigned SourceNode =
I.first;
2077 unsigned DisplayNode =
I.second;
2078 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2083void DotCfgDiffNode::createDisplayEdges(
2084 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2085 std::map<const unsigned, unsigned> &NodeMap)
const {
2087 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2089 for (
auto I : Edges) {
2090 unsigned SinkNodeIndex =
I;
2091 StringRef Colour = getEdgeColour(SinkNodeIndex);
2092 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2094 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2095 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2096 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2098 SourceDisplayNode.createEdgeMap();
2101void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2102 for (
auto E : EdgesMap) {
2104 Edges.emplace_back(E.first);
2120 return G->getEntryNode();
2123 return N->children_begin();
2127 return G->nodes_begin();
2130 return G->nodes_end();
2133 return N->edges_begin();
2137 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2147 return DiffData->getGraphName();
2151 return "\tsize=\"190, 190\";\n";
2154 const DotCfgDiffDisplayGraph *DiffData) {
2155 return DiffData->getNodeLabel(*Node);
2158 const DotCfgDiffDisplayGraph *DiffData) {
2159 return DiffData->getNodeAttributes(*Node);
2162 DisplayNode::ChildIterator &To) {
2163 return From->getEdgeSourceLabel(**To);
2166 DisplayNode::ChildIterator &To,
2167 const DotCfgDiffDisplayGraph *DiffData) {
2168 return DiffData->getEdgeColorAttr(*
From, **To);
2176void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2180 errs() <<
"Error: " <<
EC.message() <<
"\n";
2195 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2196 if (Br->isUnconditional())
2202 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2205 for (
auto &
C : Sw->cases()) {
2206 assert(
C.getCaseValue() &&
"Expected to find case value.");
2227 assert(
HTML &&
"Expected outstream to be set");
2232 Extender =
formatv(
"{0}_{1}",
N, Minor);
2241 std::string DotFile =
Twine(SV).
str();
2246 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2249 DotCfgDiff Diff(Text, Before, After);
2252 if (EntryBlockName ==
"")
2254 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2256 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2257 DG.generateDotFile(DotFile);
2262 errs() <<
"Error: " << EC.message() <<
"\n";
2271 return "Unable to find dot executable.";
2276 return "Error executing system dot.";
2280 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2285 assert(
HTML &&
"Expected outstream to be set");
2286 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2287 <<
"Initial IR (by function)</button>\n"
2288 <<
"<div class=\"content\">\n"
2297 [&](
bool InModule,
unsigned Minor,
2301 Minor, Before, After);
2314 assert(
HTML &&
"Expected outstream to be set");
2316 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2317 N, makeHTMLReady(PassID),
Name);
2325 assert(
HTML &&
"Expected outstream to be set");
2328 [&](
bool InModule,
unsigned Minor,
2332 Minor, Before, After);
2334 *
HTML <<
" </p></div>\n";
2339 assert(
HTML &&
"Expected outstream to be set");
2341 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2347 assert(
HTML &&
"Expected outstream to be set");
2349 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2350 makeHTMLReady(PassID),
Name);
2356 assert(
HTML &&
"Expected outstream to be set");
2358 makeHTMLReady(PassID),
Name);
2365 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2371 *
HTML <<
"<!doctype html>"
2374 <<
"<style>.collapsible { "
2375 <<
"background-color: #777;"
2377 <<
" cursor: pointer;"
2378 <<
" padding: 18px;"
2381 <<
" text-align: left;"
2382 <<
" outline: none;"
2383 <<
" font-size: 15px;"
2384 <<
"} .active, .collapsible:hover {"
2385 <<
" background-color: #555;"
2387 <<
" padding: 0 18px;"
2388 <<
" display: none;"
2389 <<
" overflow: hidden;"
2390 <<
" background-color: #f1f1f1;"
2393 <<
"<title>passes.html</title>"
2403 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2405 <<
"for (i = 0; i < coll.length; i++) {"
2406 <<
"coll[i].addEventListener(\"click\", function() {"
2407 <<
" this.classList.toggle(\"active\");"
2408 <<
" var content = this.nextElementSibling;"
2409 <<
" if (content.style.display === \"block\"){"
2410 <<
" content.style.display = \"none\";"
2413 <<
" content.style.display= \"block\";"
2431 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2437 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2444 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2470void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2477 "Did not expect to get here without option set.");
2486 "Did not expect to get here without option set.");
2487 CrashReporter =
nullptr;
2496 CrashReporter =
this;
2502 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2505 OS <<
" Filtered Out ***\n";
2508 OS <<
" Started ***\n";
2509 unwrapAndPrint(
OS,
IR);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
This file provides Any, a non-template class modeled in the spirit of std::any.
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::optional< std::vector< StOtherPiece > > Other
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 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)
ppc ctr loops PowerPC CTR Loops Verify
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
static cl::opt< std::string > BeforeColour("dot-cfg-before-color", cl::desc("Color for dot-cfg before elements"), cl::Hidden, cl::init("red"))
static cl::opt< std::string > IRDumpDirectory("ir-dump-directory", cl::desc("If specified, IR printed using the " "-print-[before|after]{-all} options will be dumped into " "files in this directory rather than written to stderr"), cl::Hidden, cl::value_desc("filename"))
static cl::opt< bool > DroppedVarStats("dropped-variable-stats", cl::Hidden, cl::desc("Dump dropped debug variables stats"), cl::init(false))
static cl::opt< std::string > OptBisectPrintIRPath("opt-bisect-print-ir-path", cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden)
static cl::opt< bool > PrintChangedBefore("print-before-changed", cl::desc("Print before passes that change them"), cl::init(false), cl::Hidden)
static cl::opt< std::string > DotCfgDir("dot-cfg-dir", cl::desc("Generate dot files into specified directory for changed IRs"), cl::Hidden, cl::init("./"))
static cl::list< unsigned > PrintBeforePassNumber("print-before-pass-number", cl::CommaSeparated, cl::Hidden, cl::desc("Print IR before the passes with specified numbers as " "reported by print-pass-numbers"))
static cl::opt< bool > VerifyAnalysisInvalidation("verify-analysis-invalidation", cl::Hidden, cl::init(false))
static std::string getIRFileDisplayName(Any IR)
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
static SmallVector< Function *, 1 > GetFunctions(Any IR)
static void printBBName(raw_ostream &out, const BasicBlock *BB)
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
static bool shouldGenerateData(const Function &F)
static cl::list< unsigned > PrintAfterPassNumber("print-after-pass-number", cl::CommaSeparated, cl::Hidden, cl::desc("Print IR after the passes with specified numbers as " "reported by print-pass-numbers"))
static int prepareDumpIRFileDescriptor(const StringRef DumpIRFilename)
static const IRUnitT * unwrapIR(Any IR)
static cl::opt< std::string > AfterColour("dot-cfg-after-color", cl::desc("Color for dot-cfg after elements"), cl::Hidden, cl::init("forestgreen"))
static cl::opt< bool > PrintOnCrash("print-on-crash", cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"), cl::Hidden)
static cl::opt< bool > PrintPassNumbers("print-pass-numbers", cl::init(false), cl::Hidden, cl::desc("Print pass names and their ordinals"))
static cl::opt< std::string > PrintOnCrashPath("print-on-crash-path", cl::desc("Print the last form of the IR before crash to a file"), cl::Hidden)
static void writeIRFileDisplayName(raw_ostream &ResultStream, Any 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 <a particular IR unit>" (e....
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
LLVM_ABI bool isEntryBlock() const
Return true if this is the entry block of the containing function.
const Function * getParent() const
Return the enclosing method, or null if none.
const T & getData() const
Conditional or Unconditional Branch instruction.
Represents analyses that only rely on functions' control flow.
void saveIRBeforePass(Any IR, StringRef PassID, StringRef PassName)
void handleIRAfterPass(Any IR, StringRef PassID, StringRef PassName)
void registerRequiredCallbacks(PassInstrumentationCallbacks &PIC)
void handleInvalidatedPass(StringRef PassID)
virtual ~ChangeReporter()
void addSuccessorLabel(StringRef Succ, StringRef Label)
LLVM_ABI DCData(const BasicBlock &B)
std::unique_ptr< raw_fd_ostream > HTML
void handleInvalidated(StringRef PassID) override
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< DCData > &Output) override
static std::string genHTML(StringRef Text, StringRef DotFile, StringRef PDFFileName)
void handleInitialIR(Any IR) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< DCData > &Before, const FuncDataT< DCData > &After)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
DotCfgChangeReporter(bool Verbose)
void handleIgnored(StringRef PassID, std::string &Name) override
~DotCfgChangeReporter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< DCData > &Before, const IRDataT< DCData > &After, Any) override
void handleFiltered(StringRef PassID, std::string &Name) override
void omitAfter(StringRef PassID, std::string &Name) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
std::string getEntryBlockName() const
bool hasOptNone() const
Do not optimize this function (-O0).
Module * getParent()
Get the module that this global value is contained inside of...
~IRChangedPrinter() override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override
void omitAfter(StringRef PassID, std::string &Name) override
void handleInvalidated(StringRef PassID) override
void handleIR(const std::string &IR, StringRef PassID)
void handleInitialIR(Any IR) override
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void handleFiltered(StringRef PassID, std::string &Name) override
~IRChangedTester() override
static bool generateFunctionData(IRDataT< T > &Data, const FunctionT &F)
static void analyzeIR(Any IR, IRDataT< T > &Data)
void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~InLineChangePrinter() override
void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, Any) override
void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< EmptyData > &Output) override
void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
This is an important class for using LLVM in a threaded context.
LLVM_ABI OptPassGate & getOptPassGate() const
Access the object which can disable optional passes and individual optimizations at compile time.
A node in the call graph.
An SCC of the call graph.
Represents a single loop in the control flow graph.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI bool shouldRun(StringRef PassName, Any IR)
Extensions to this class implement mechanisms to disable passes and individual optimizations at compi...
virtual bool isEnabled() const
isEnabled() should return true before calling shouldRunPass().
virtual bool shouldRunPass(StringRef PassName, StringRef IRDescription) const
IRDescription is a textual description of the IR unit the pass is running over.
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()
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
LLVM_ABI void reportCrashIR()
LLVM_ABI ~PrintCrashIRInstrumentation()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI ~PrintIRInstrumentation()
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)
LLVM_ABI StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - 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
size - Get the string size.
char front() const
front - Get the first character in the string.
bool consume_front(StringRef Prefix)
Returns true if this StringRef has the given prefix and removes that prefix.
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.
void handleInitialIR(Any IR) override
void handleInvalidated(StringRef PassID) override
TextChangeReporter(bool Verbose)
void omitAfter(StringRef PassID, std::string &Name) override
void handleIgnored(StringRef PassID, std::string &Name) override
void handleFiltered(StringRef PassID, std::string &Name) override
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC)
LLVM_ABI TimeProfilingPassesHandler()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM)
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to a file descriptor.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
AstPtr createNode(ASTNode::Type T, Accessor A, ASTNode *Parent, llvm::StringMap< AstPtr > &Partials, llvm::StringMap< Lambda > &Lambdas, llvm::StringMap< SectionLambda > &SectionLambdas, EscapeMap &Escapes)
DiagnosticInfoOptimizationBase::Argument NV
LLVM_ABI void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
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 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 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.
LLVM_ABI void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
This is an optimization pass for GlobalISel generic memory operations.
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.
bool forcePrintModuleIR()
std::vector< std::string > printAfterPasses()
LLVM_ABI uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
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)
bool shouldPrintBeforeAll()
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool shouldPrintAfterAll()
cl::opt< ChangePrinter > PrintChanged
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.
std::vector< std::string > printBeforePasses()
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)
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.
bool isFunctionInPrintList(StringRef FunctionName)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isPassInPrintList(StringRef PassName)
LLVM_ABI bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
LLVM_ABI void timeTraceProfilerEnd()
Manually end the last time section.
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.
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
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.
std::array< uint32_t, 5 > ModuleHash
160 bits SHA1
LLVM_ABI stable_hash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
LLVM_ABI void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
LLVM_ABI bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
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.
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)
DOTGraphTraits - Template class that can be specialized to customize how graphs are converted to 'dot...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
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)
This class manages callbacks registration, as well as provides a way for PassInstrumentation to pass ...
void registerAnalysesClearedCallback(CallableT C)
void registerBeforeAnalysisCallback(CallableT C)
void registerAfterPassInvalidatedCallback(CallableT C, bool ToFront=false)
void registerAnalysisInvalidatedCallback(CallableT C)
LLVM_ABI StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name. Empty if no match found.
void registerAfterAnalysisCallback(CallableT C, bool ToFront=false)
void registerBeforeNonSkippedPassCallback(CallableT C)
void registerBeforeSkippedPassCallback(CallableT C)
void registerShouldRunOptionalPassCallback(CallableT C)
void registerAfterPassCallback(CallableT C, bool ToFront=false)
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 SkipAnalyses
Don't print information for analyses.
bool Verbose
Print adaptors and pass managers.
bool Indent
Indent based on hierarchy.