48#include <unordered_map>
49#include <unordered_set>
57#ifdef EXPENSIVE_CHECKS
69 cl::desc(
"Print before passes that change them"),
76 cl::desc(
"system dot used by change reporters"));
104 cl::desc(
"Generate dot files into specified directory for changed IRs"),
109 "print-on-crash-path",
110 cl::desc(
"Print the last form of the IR before crash to a file"),
115 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
119 "opt-bisect-print-ir-path",
124 cl::desc(
"Print pass names and their ordinals"));
128 cl::desc(
"Print IR before the pass with this number as "
129 "reported by print-pass-numbers"));
133 cl::desc(
"Print IR after the pass with this number as "
134 "reported by print-pass-numbers"));
138 cl::desc(
"If specified, IR printed using the "
139 "-print-[before|after]{-all} options will be dumped into "
140 "files in this directory rather than written to stderr"),
145 cl::desc(
"Dump dropped debug variables stats"),
149 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&
IR);
150 return IRPtr ? *IRPtr :
nullptr;
164 cl::desc(
"exe called with module IR after each pass that "
169const Module *unwrapModule(
Any IR,
bool Force =
false) {
170 if (
const auto *M = unwrapIR<Module>(
IR))
173 if (
const auto *
F = unwrapIR<Function>(
IR)) {
177 return F->getParent();
180 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
184 return F.getParent();
187 assert(!Force &&
"Expected a module");
191 if (
const auto *L = unwrapIR<Loop>(
IR)) {
192 const Function *
F =
L->getHeader()->getParent();
195 return F->getParent();
198 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
201 return MF->getFunction().getParent();
215 M->print(
OS,
nullptr);
217 for (
const auto &
F : M->functions()) {
233 const Function *
F =
L->getHeader()->getParent();
245std::string getIRName(
Any IR) {
246 if (unwrapIR<Module>(
IR))
249 if (
const auto *
F = unwrapIR<Function>(
IR))
250 return F->getName().str();
252 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
255 if (
const auto *L = unwrapIR<Loop>(
IR))
256 return "loop %" + L->getName().str() +
" in function " +
257 L->getHeader()->getParent()->getName().str();
259 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
265bool moduleContainsFilterPrintFunc(
const Module &M) {
266 return any_of(M.functions(),
268 return isFunctionInPrintList(F.getName());
281bool shouldPrintIR(
Any IR) {
282 if (
const auto *M = unwrapIR<Module>(
IR))
283 return moduleContainsFilterPrintFunc(*M);
285 if (
const auto *
F = unwrapIR<Function>(
IR))
288 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
289 return sccContainsFilterPrintFunc(*
C);
291 if (
const auto *L = unwrapIR<Loop>(
IR))
294 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
302 if (!shouldPrintIR(
IR))
306 auto *
M = unwrapModule(
IR);
307 assert(M &&
"should have unwrapped module");
312 if (
const auto *M = unwrapIR<Module>(
IR)) {
317 if (
const auto *
F = unwrapIR<Function>(
IR)) {
322 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
327 if (
const auto *L = unwrapIR<Loop>(
IR)) {
332 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
342 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
343 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
344 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
345 "PrintMIRPreparePass"});
353 S.append(Clean.
str());
357 S.append(SR[0] ==
'<' ?
"<" :
">");
365 if (
const auto *M = unwrapIR<Module>(
IR))
367 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
368 return C->begin()->getFunction().getParent();
372bool isInterestingFunction(
const Function &
F) {
381 if (
const auto *
F = unwrapIR<Function>(
IR))
382 return isInterestingFunction(*
F);
389 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
405 BeforeStack.emplace_back();
411 T &Data = BeforeStack.back();
412 generateIRRepresentation(
IR, PassID, Data);
418 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
420 std::string
Name = getIRName(
IR);
422 if (isIgnored(PassID)) {
424 handleIgnored(PassID,
Name);
427 handleFiltered(PassID,
Name);
430 T &
Before = BeforeStack.back();
433 generateIRRepresentation(
IR, PassID,
After);
438 omitAfter(PassID,
Name);
442 BeforeStack.pop_back();
447 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
454 handleInvalidated(PassID);
455 BeforeStack.pop_back();
471 handleInvalidatedPass(
P);
482 auto *M = unwrapModule(
IR,
true);
483 assert(M &&
"Expected module to be unwrapped when forced.");
484 Out <<
"*** IR Dump At Start ***\n";
485 M->print(Out,
nullptr);
490 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
496 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
503 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
509 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
521 std::string &Output) {
523 unwrapAndPrint(
OS,
IR);
528 const std::string &
Before,
532 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
538 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
542 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" <<
After;
548 if (TestChanged !=
"")
558 dbgs() <<
"Unable to create temporary file.";
563 dbgs() <<
"Unable to find test-changed executable.";
567 StringRef Args[] = {TestChanged, FileName[0], PassID};
570 dbgs() <<
"Error executing test-changed executable.";
575 dbgs() <<
"Unable to remove temporary file.";
591 const std::string &
Before,
600 const auto &BFD =
Before.getData();
601 const auto &AFD =
After.getData();
602 std::vector<std::string>::const_iterator BI =
Before.getOrder().begin();
603 std::vector<std::string>::const_iterator BE =
Before.getOrder().end();
604 std::vector<std::string>::const_iterator AI =
After.getOrder().begin();
605 std::vector<std::string>::const_iterator AE =
After.getOrder().end();
607 auto HandlePotentiallyRemovedData = [&](std::string S) {
611 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
614 auto HandleNewData = [&](std::vector<const T *> &Q) {
616 for (
const T *NBI : Q)
617 HandlePair(
nullptr, NBI);
630 std::vector<const T *> NewDataQueue;
632 if (!BFD.count(*AI)) {
635 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
644 while (BI != BE && *BI != *AI) {
645 HandlePotentiallyRemovedData(*BI);
649 HandleNewData(NewDataQueue);
651 const T &AData = AFD.find(*AI)->getValue();
652 const T &BData = BFD.find(*AI)->getValue();
653 HandlePair(&BData, &AData);
661 HandlePotentiallyRemovedData(*BI);
665 HandleNewData(NewDataQueue);
671 std::function<
void(
bool InModule,
unsigned Minor,
674 if (!CompareModule) {
677 "Expected only one function.");
678 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
679 After.getData().begin()->getValue());
687 assert((
B ||
A) &&
"Both functions cannot be missing.");
692 CompareFunc(
true, Minor++, *
B, *
A);
697 if (
const Module *M = getModuleForComparison(
IR)) {
700 generateFunctionData(
Data,
F);
704 if (
const auto *
F = unwrapIR<Function>(
IR)) {
705 generateFunctionData(
Data, *
F);
709 if (
const auto *L = unwrapIR<Loop>(
IR)) {
710 auto *
F = L->getHeader()->getParent();
711 generateFunctionData(
Data, *
F);
715 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
716 generateFunctionData(
Data, *MF);
732template <
typename FunctionT>
737 for (
const auto &
B :
F) {
738 std::string BBName =
B.getName().str();
739 if (BBName.empty()) {
746 Data.getOrder().emplace_back(
F.getName());
747 Data.getData().insert({
F.getName(), FD});
755 "PassRunDescriptorStack is not empty at exit");
761 const Module *M = unwrapModule(
IR,
true);
762 assert(M &&
"should have unwrapped module");
764 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
766 if (unwrapIR<Module>(
IR)) {
767 ResultStream <<
"-module";
768 }
else if (
const auto *
F = unwrapIR<Function>(
IR)) {
769 ResultStream <<
"-function-";
773 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
774 ResultStream <<
"-scc-";
777 }
else if (
const auto *L = unwrapIR<Loop>(
IR)) {
778 ResultStream <<
"-loop-";
781 }
else if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
782 ResultStream <<
"-machine-function-";
796 "The flag -ir-dump-directory must be passed to dump IR to files");
798 ResultPath += RootDirectory;
801 FilenameStream << CurrentPassNumber;
802 FilenameStream <<
"-";
804 FilenameStream <<
"-";
807 return std::string(ResultPath);
817 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
819 return FileSuffixes[
static_cast<size_t>(
Type)];
822void PrintIRInstrumentation::pushPassRunDescriptor(
826 PassRunDescriptor(M, DumpIRFilename, getIRName(
IR), PassID));
829PrintIRInstrumentation::PassRunDescriptor
830PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
831 assert(!PassRunDescriptorStack.
empty() &&
"empty PassRunDescriptorStack");
832 PassRunDescriptor Descriptor = PassRunDescriptorStack.
pop_back_val();
833 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
841 if (!ParentPath.empty()) {
845 " to support -ir-dump-directory: " + EC.message());
852 " to support -ir-dump-directory: " + EC.message());
856void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
857 if (isIgnored(PassID))
860 std::string DumpIRFilename;
862 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID) ||
863 shouldPrintBeforeCurrentPassNumber() ||
864 shouldPrintAfterCurrentPassNumber()))
865 DumpIRFilename = fetchDumpFilename(PassID,
IR);
871 if (shouldPrintAfterPass(PassID))
872 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
874 if (!shouldPrintIR(
IR))
879 if (shouldPrintPassNumbers())
880 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
881 <<
" on " << getIRName(
IR) <<
"\n";
883 if (shouldPrintAfterCurrentPassNumber())
884 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
886 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
890 Stream <<
"; *** IR Dump Before ";
891 if (shouldPrintBeforeSomePassNumber())
892 Stream << CurrentPassNumber <<
"-";
893 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
894 unwrapAndPrint(Stream,
IR);
897 if (!DumpIRFilename.empty()) {
898 DumpIRFilename +=
getFileSuffix(IRDumpFileSuffixType::Before);
901 WriteIRToStream(DumpIRFileStream);
903 WriteIRToStream(
dbgs());
907void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
908 if (isIgnored(PassID))
911 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
914 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
915 assert(StoredPassID == PassID &&
"mismatched PassID");
917 if (!shouldPrintIR(
IR) ||
918 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
922 Stream <<
"; *** IR Dump After ";
923 if (shouldPrintAfterSomePassNumber())
924 Stream << CurrentPassNumber <<
"-";
925 Stream <<
StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
926 unwrapAndPrint(Stream,
IR);
930 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
931 "should be set in printBeforePass");
932 const std::string DumpIRFilenameWithSuffix =
937 WriteIRToStream(DumpIRFileStream, IRName);
939 WriteIRToStream(
dbgs(), IRName);
943void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
944 if (isIgnored(PassID))
947 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
950 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
951 assert(StoredPassID == PassID &&
"mismatched PassID");
955 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
961 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
963 Stream << Banner <<
"\n";
968 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
969 "should be set in printBeforePass");
970 const std::string DumpIRFilenameWithSuffix =
975 WriteIRToStream(DumpIRFileStream, M, IRName);
977 WriteIRToStream(
dbgs(), M, IRName);
981bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
989bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
997bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
998 return shouldPrintBeforeSomePassNumber() &&
1002bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
1003 return shouldPrintAfterSomePassNumber() &&
1007bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1011bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1015bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1026 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1035 this->printAfterPass(
P,
IR);
1039 this->printAfterPassInvalidated(
P);
1050bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
1051 bool ShouldRun =
true;
1052 if (
const auto *
F = unwrapIR<Function>(
IR))
1053 ShouldRun = !
F->hasOptNone();
1054 else if (
const auto *L = unwrapIR<Loop>(
IR))
1055 ShouldRun = !L->getHeader()->getParent()->hasOptNone();
1056 else if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
1059 if (!ShouldRun && DebugLogging) {
1060 errs() <<
"Skipping pass " << PassID <<
" on " << getIRName(
IR)
1061 <<
" due to optnone attribute\n";
1075 this->HasWrittenIR =
true;
1076 const Module *M = unwrapModule(
IR,
true);
1077 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1082 M->print(
OS,
nullptr);
1111 std::vector<StringRef> SpecialPasses;
1113 SpecialPasses.emplace_back(
"PassManager");
1114 SpecialPasses.emplace_back(
"PassAdaptor");
1120 "Unexpectedly skipping special pass");
1122 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1130 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1131 if (
const auto *
F = unwrapIR<Function>(
IR)) {
1132 unsigned Count =
F->getInstructionCount();
1133 OS <<
" (" << Count <<
" instruction";
1137 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
1138 int Count =
C->size();
1139 OS <<
" (" << Count <<
" node";
1165 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1172 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1176 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1182 bool TrackBBLifetime) {
1183 if (TrackBBLifetime)
1185 for (
const auto &BB : *
F) {
1187 BBGuards->try_emplace(intptr_t(&BB), &BB);
1191 BBGuards->try_emplace(intptr_t(Succ), Succ);
1198 out << BB->
getName() <<
"<" << BB <<
">";
1203 out <<
"unnamed_removed<" << BB <<
">";
1209 <<
"<" << BB <<
">";
1213 unsigned FuncOrderBlockNum = 0;
1217 FuncOrderBlockNum++;
1219 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1226 if (
Before.isPoisoned()) {
1227 out <<
"Some blocks were deleted\n";
1233 out <<
"Different number of non-leaf basic blocks: before="
1234 <<
Before.Graph.size() <<
", after=" <<
After.Graph.size() <<
"\n";
1236 for (
auto &BB :
Before.Graph) {
1237 auto BA =
After.Graph.find(BB.first);
1238 if (BA ==
After.Graph.end()) {
1239 out <<
"Non-leaf block ";
1241 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1245 for (
auto &BA :
After.Graph) {
1246 auto BB =
Before.Graph.find(BA.first);
1247 if (BB ==
Before.Graph.end()) {
1248 out <<
"Non-leaf block ";
1250 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1254 if (BB->second == BA.second)
1257 out <<
"Different successors of block ";
1259 out <<
" (unordered):\n";
1260 out <<
"- before (" << BB->second.size() <<
"): ";
1261 for (
auto &SuccB : BB->second) {
1263 if (SuccB.second != 1)
1264 out <<
"(" << SuccB.second <<
"), ";
1269 out <<
"- after (" << BA.second.size() <<
"): ";
1270 for (
auto &SuccA : BA.second) {
1272 if (SuccA.second != 1)
1273 out <<
"(" << SuccA.second <<
"), ";
1353 if (
const auto *MaybeF = unwrapIR<Function>(
IR)) {
1355 }
else if (
const auto *MaybeM = unwrapIR<Module>(
IR)) {
1367 bool Registered =
false;
1370#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1371 assert(&PassStack.emplace_back(
P));
1376 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1391 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1392 auto &M = *
const_cast<Module *
>(MPtr);
1399#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1400 assert(PassStack.pop_back_val() ==
P &&
1401 "Before and After callbacks must correspond");
1408#if LLVM_ENABLE_ABI_BREAKING_CHECKS
1409 assert(PassStack.pop_back_val() ==
P &&
1410 "Before and After callbacks must correspond");
1418 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1422 if (
auto *HashBefore =
1426 "Function @{0} changed by {1} without invalidating analyses",
1432 const CFG &GraphBefore,
const CFG &GraphAfter) {
1433 if (GraphAfter == GraphBefore)
1437 <<
"Error: " <<
Pass
1438 <<
" does not invalidate CFG analyses but CFG changes detected in "
1440 << FuncName <<
":\n";
1445 if (
auto *GraphBefore =
1447 CheckCFG(
P,
F->getName(), *GraphBefore,
1450 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1451 auto &M = *
const_cast<Module *
>(MPtr);
1452 if (
auto *HashBefore =
1456 "Module changed by {0} without invalidating analyses",
P));
1467 if (isIgnored(
P) ||
P ==
"VerifierPass")
1469 const auto *
F = unwrapIR<Function>(
IR);
1471 if (
const auto *L = unwrapIR<Loop>(
IR))
1472 F = L->getHeader()->getParent();
1477 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1481 "\"{0}\", compilation aborted!",
1484 const auto *M = unwrapIR<Module>(
IR);
1486 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
1487 M =
C->begin()->getFunction().getParent();
1492 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1496 "\"{0}\", compilation aborted!",
1500 if (
auto *MF = unwrapIR<MachineFunction>(
IR)) {
1502 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1503 std::string Banner =
1504 formatv(
"Broken machine function found after pass "
1505 "\"{0}\", compilation aborted!",
1535 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1539 [&](
bool InModule,
unsigned Minor,
1542 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1554 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1561 const std::string Removed =
1562 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1563 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1564 const std::string NoChange =
" %l\n";
1565 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1587 this->runAfterPass();
1599void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1608class DotCfgDiffDisplayGraph;
1611class DisplayElement {
1614 StringRef getColour()
const {
return Colour; }
1617 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1623class DisplayEdge :
public DisplayElement {
1628 std::string getValue()
const {
return Value; }
1630 const DisplayNode &getDestinationNode()
const {
return Node; }
1634 const DisplayNode &
Node;
1638class DisplayNode :
public DisplayElement {
1646 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1647 ChildIterator children_begin()
const {
return Children.cbegin(); }
1648 ChildIterator children_end()
const {
return Children.cend(); }
1651 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1652 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1653 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1659 std::string getContent()
const {
return Content; }
1662 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1663 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1664 return *EdgeMap.find(&To)->second;
1669 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1670 return getEdge(Sink).getValue();
1673 void createEdgeMap();
1681 std::vector<DisplayEdge> Edges;
1683 std::vector<DisplayEdge *> EdgePtrs;
1684 std::unordered_set<DisplayNode *>
Children;
1685 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1688 bool AllEdgesCreated =
false;
1692class DotCfgDiffDisplayGraph {
1694 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1697 void generateDotFile(
StringRef DotFile);
1700 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1701 NodeIterator nodes_begin()
const {
1702 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1703 return NodePtrs.cbegin();
1705 NodeIterator nodes_end()
const {
1706 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1707 return NodePtrs.cend();
1712 void setEntryNode(
unsigned N) {
1714 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1715 NodeGenerationComplete =
true;
1716 for (
auto &
N : Nodes)
1717 NodePtrs.emplace_back(&
N);
1719 EntryNode = NodePtrs[
N];
1723 void createNode(std::string
C,
StringRef Colour) {
1724 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1725 Nodes.emplace_back(
C, Colour);
1729 assert(
N < Nodes.size() &&
"Node is out of bounds");
1732 unsigned size()
const {
1733 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1734 return Nodes.size();
1738 std::string getGraphName()
const {
return GraphName; }
1743 return Node.getContent();
1747 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1748 return attribute(
Node.getColour());
1752 std::string getEdgeColorAttr(
const DisplayNode &
From,
1753 const DisplayNode &To)
const {
1754 return attribute(
From.getEdge(To).getColour());
1758 DisplayNode *getEntryNode()
const {
1759 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1765 std::string attribute(
StringRef Colour)
const {
1766 return "color=" + Colour.
str();
1769 bool NodeGenerationComplete =
false;
1770 const std::string GraphName;
1771 std::vector<DisplayNode> Nodes;
1772 std::vector<DisplayNode *> NodePtrs;
1773 DisplayNode *EntryNode =
nullptr;
1778 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1779 Edges.emplace_back(
Value.str(),
Node, Colour);
1783void DisplayNode::createEdgeMap() {
1786 AllEdgesCreated =
true;
1787 for (
auto &E : Edges)
1788 EdgeMap.insert({&E.getDestinationNode(), &E});
1791class DotCfgDiffNode;
1795class DotCfgDiffNode {
1797 DotCfgDiffNode() =
delete;
1803 : Graph(
G),
N(
N), Data{&BD, nullptr}, Colour(Colour) {}
1804 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1805 : Graph(DN.Graph),
N(DN.
N), Data{DN.Data[0], DN.Data[1]},
1809 unsigned getIndex()
const {
return N; }
1813 assert(Data[0] &&
"Expected Data[0] to be set.");
1814 return Data[0]->getLabel();
1817 StringRef getColour()
const {
return Colour; }
1821 assert(!Data[1] &&
"Expected only one block datum");
1829 "Unexpected edge count and color.");
1830 EdgesMap[
E] = {
Value.str(), Colour};
1836 StringRef getEdgeColour(
const unsigned S)
const {
1837 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1838 return EdgesMap.at(S).second;
1842 std::string getBodyContent()
const;
1844 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1845 std::map<const unsigned, unsigned> &NodeMap)
const;
1852 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1854 std::vector<unsigned> Edges;
1867 DotCfgDiff(
const DotCfgDiff &) =
delete;
1868 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1870 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1877 StringRef getEdgeSourceLabel(
const unsigned &Source,
1878 const unsigned &Sink)
const {
1880 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1881 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1882 return EdgeLabels.find(S)->getValue();
1886 unsigned size()
const {
return Nodes.size(); }
1888 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1889 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1895 std::string colourize(std::string S,
StringRef Colour)
const;
1898 unsigned Pos = Nodes.size();
1899 Nodes.emplace_back(*
this, Pos, BD,
C);
1900 NodePosition.insert({
Label, Pos});
1906 std::vector<DotCfgDiffNode> Nodes;
1908 const std::string GraphName;
1913std::string DotCfgDiffNode::getBodyContent()
const {
1915 assert(
Data[1] &&
"Expected Data[1] to be set.");
1918 for (
unsigned I = 0;
I < 2; ++
I) {
1919 SR[
I] =
Data[
I]->getBody();
1923 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1927 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1929 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1931 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1932 std::string Diff =
Data[0]->getLabel().str();
1933 Diff +=
":\n<BR align=\"left\"/>" +
1934 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1935 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1940 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1943 std::string S =
R.sub(
"", Diff, &
Error);
1954 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1955 std::string Body = makeHTMLReady(
Data[0]->getBody());
1959 if (BS.
front() ==
'\n')
1964 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1966 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1969 while (BS1.
size()) {
1970 S.append(
"<BR align=\"left\"/>");
1972 S.append(
Line.str());
1975 S.append(
"<BR align=\"left\"/></FONT>");
1979std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1980 if (S.length() == 0)
1982 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1987 : GraphName(Title.str()) {
1991 for (
auto &
B :
Before.getData()) {
2000 Sink != E; ++Sink) {
2001 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
2002 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2008 for (
auto &
A :
After.getData()) {
2011 unsigned C = NodePosition.count(Label);
2016 assert(
C == 1 &&
"Unexpected multiple nodes.");
2017 Nodes[NodePosition[
Label]].setCommon(BD);
2022 Sink != E; ++Sink) {
2023 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
2024 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2025 unsigned C = EdgesMap.
count(Key);
2035 for (
auto &E : EdgesMap) {
2038 auto SP1 = S.
rsplit(
' ');
2039 auto &SourceSink = SP1.first;
2040 auto SP2 = SourceSink.split(
' ');
2045 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2046 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2047 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2048 unsigned SinkNode = NodePosition[
Sink];
2052 auto [It,
Inserted] = EdgeLabels.try_emplace(SourceSink);
2054 It->getValue() = colourize(
Value.str(), Colour);
2057 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2059 It->getValue() =
NV;
2061 SourceNode.addEdge(SinkNode,
Value, Colour);
2063 for (
auto &
I : Nodes)
2067DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2069 assert(NodePosition.count(EntryNodeName) == 1 &&
2070 "Expected to find entry block in map.");
2071 unsigned Entry = NodePosition[EntryNodeName];
2072 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2073 DotCfgDiffDisplayGraph
G(Title.
str());
2075 std::map<const unsigned, unsigned> NodeMap;
2077 int EntryIndex = -1;
2079 for (
auto &
I : Nodes) {
2080 if (
I.getIndex() == Entry)
2082 G.createNode(
I.getBodyContent(),
I.getColour());
2083 NodeMap.insert({
I.getIndex(), Index++});
2085 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2086 G.setEntryNode(EntryIndex);
2088 for (
auto &
I : NodeMap) {
2089 unsigned SourceNode =
I.first;
2090 unsigned DisplayNode =
I.second;
2091 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2096void DotCfgDiffNode::createDisplayEdges(
2097 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2098 std::map<const unsigned, unsigned> &NodeMap)
const {
2100 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2102 for (
auto I : Edges) {
2103 unsigned SinkNodeIndex =
I;
2104 StringRef Colour = getEdgeColour(SinkNodeIndex);
2105 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2107 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2108 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2109 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2111 SourceDisplayNode.createEdgeMap();
2114void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2115 for (
auto E : EdgesMap) {
2117 Edges.emplace_back(E.first);
2133 return G->getEntryNode();
2136 return N->children_begin();
2140 return G->nodes_begin();
2143 return G->nodes_end();
2146 return N->edges_begin();
2150 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2160 return DiffData->getGraphName();
2164 return "\tsize=\"190, 190\";\n";
2167 const DotCfgDiffDisplayGraph *DiffData) {
2168 return DiffData->getNodeLabel(*Node);
2171 const DotCfgDiffDisplayGraph *DiffData) {
2172 return DiffData->getNodeAttributes(*Node);
2175 DisplayNode::ChildIterator &To) {
2176 return From->getEdgeSourceLabel(**To);
2179 DisplayNode::ChildIterator &To,
2180 const DotCfgDiffDisplayGraph *DiffData) {
2181 return DiffData->getEdgeColorAttr(*
From, **To);
2189void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2193 errs() <<
"Error: " <<
EC.message() <<
"\n";
2208 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2209 if (Br->isUnconditional())
2215 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2218 for (
auto &
C : Sw->cases()) {
2219 assert(
C.getCaseValue() &&
"Expected to find case value.");
2240 assert(
HTML &&
"Expected outstream to be set");
2245 Extender =
formatv(
"{0}_{1}",
N, Minor);
2254 std::string DotFile =
Twine(SV).
str();
2259 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2263 std::string EntryBlockName =
After.getEntryBlockName();
2265 if (EntryBlockName ==
"")
2266 EntryBlockName =
Before.getEntryBlockName();
2267 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2269 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2270 DG.generateDotFile(DotFile);
2275 errs() <<
"Error: " << EC.message() <<
"\n";
2284 return "Unable to find dot executable.";
2289 return "Error executing system dot.";
2293 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2298 assert(
HTML &&
"Expected outstream to be set");
2299 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2300 <<
"Initial IR (by function)</button>\n"
2301 <<
"<div class=\"content\">\n"
2310 [&](
bool InModule,
unsigned Minor,
2327 assert(
HTML &&
"Expected outstream to be set");
2329 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2330 N, makeHTMLReady(PassID),
Name);
2338 assert(
HTML &&
"Expected outstream to be set");
2341 [&](
bool InModule,
unsigned Minor,
2347 *
HTML <<
" </p></div>\n";
2352 assert(
HTML &&
"Expected outstream to be set");
2354 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2360 assert(
HTML &&
"Expected outstream to be set");
2362 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2363 makeHTMLReady(PassID),
Name);
2369 assert(
HTML &&
"Expected outstream to be set");
2371 makeHTMLReady(PassID),
Name);
2378 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2384 *
HTML <<
"<!doctype html>"
2387 <<
"<style>.collapsible { "
2388 <<
"background-color: #777;"
2390 <<
" cursor: pointer;"
2391 <<
" padding: 18px;"
2394 <<
" text-align: left;"
2395 <<
" outline: none;"
2396 <<
" font-size: 15px;"
2397 <<
"} .active, .collapsible:hover {"
2398 <<
" background-color: #555;"
2400 <<
" padding: 0 18px;"
2401 <<
" display: none;"
2402 <<
" overflow: hidden;"
2403 <<
" background-color: #f1f1f1;"
2406 <<
"<title>passes.html</title>"
2416 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2418 <<
"for (i = 0; i < coll.length; i++) {"
2419 <<
"coll[i].addEventListener(\"click\", function() {"
2420 <<
" this.classList.toggle(\"active\");"
2421 <<
" var content = this.nextElementSibling;"
2422 <<
" if (content.style.display === \"block\"){"
2423 <<
" content.style.display = \"none\";"
2426 <<
" content.style.display= \"block\";"
2444 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2450 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2457 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),
2483void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2490 "Did not expect to get here without option set.");
2499 "Did not expect to get here without option set.");
2500 CrashReporter =
nullptr;
2509 CrashReporter =
this;
2515 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2518 OS <<
" Filtered Out ***\n";
2521 OS <<
" Started ***\n";
2522 unwrapAndPrint(
OS,
IR);
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 ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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< unsigned > PrintAfterPassNumber("print-after-pass-number", cl::init(0), cl::Hidden, cl::desc("Print IR after the pass with this number as " "reported by print-pass-numbers"))
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::opt< bool > VerifyAnalysisInvalidation("verify-analysis-invalidation", cl::Hidden, cl::init(false))
static cl::opt< unsigned > PrintBeforePassNumber("print-before-pass-number", cl::init(0), cl::Hidden, cl::desc("Print IR before the pass with this number as " "reported by print-pass-numbers"))
static cl::opt< std::string > CommonColour("dot-cfg-common-color", cl::desc("Color for dot-cfg common elements"), cl::Hidden, cl::init("black"))
static StringRef getFileSuffix(IRDumpFileSuffixType Type)
static SmallString< 32 > getIRFileDisplayName(Any IR)
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 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)
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.
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)
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.
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.
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.
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
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(const StringRef PassName, StringRef IRDescription)
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.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)
~PrintCrashIRInstrumentation()
void registerCallbacks(PassInstrumentationCallbacks &PIC)
~PrintIRInstrumentation()
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
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.
void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)
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",...
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
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.
constexpr bool empty() const
empty - Check if the string is empty.
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
void registerCallbacks(PassInstrumentationCallbacks &PIC)
void registerCallbacks(PassInstrumentationCallbacks &PIC)
TimeProfilingPassesHandler()
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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.
StringRef getName() const
Return a constant reference to the value's name.
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)
DiagnosticInfoOptimizationBase::Argument NV
void make_absolute(const Twine ¤t_directory, SmallVectorImpl< char > &path)
Make path an absolute path.
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...
void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)
Create a potentially unique file name but does not create it.
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.
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
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.
ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})
Find the first executable file Name in Paths.
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()
uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
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)
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
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()
void verifyMachineFunction(const std::string &Banner, const MachineFunction &MF)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isFunctionInPrintList(StringRef FunctionName)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool isPassInPrintList(StringRef PassName)
bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)
void timeTraceProfilerEnd()
Manually end the last time section.
std::error_code cleanUpTempFiles(ArrayRef< std::string > FileName)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
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
stable_hash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
void printLoop(Loop &L, raw_ostream &OS, const std::string &Banner="")
Function to print a loop's contents as LLVM's text IR assembly.
bool verifyModule(const Module &M, raw_ostream *OS=nullptr, bool *BrokenDebugInfo=nullptr)
Check a module for errors.
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)
StringRef getPassNameForClassName(StringRef ClassName)
Get the pass name for a given pass class name.
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 void printDiff(raw_ostream &out, const CFG &Before, const CFG &After)
CFG(const Function *F, bool TrackBBLifetime)
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.