46#include <unordered_map>
47#include <unordered_set>
55#ifdef EXPENSIVE_CHECKS
67 cl::desc(
"Print before passes that change them"),
74 cl::desc(
"system dot used by change reporters"));
102 cl::desc(
"Generate dot files into specified directory for changed IRs"),
107 "print-on-crash-path",
108 cl::desc(
"Print the last form of the IR before crash to a file"),
113 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
117 "opt-bisect-print-ir-path",
122 cl::desc(
"Print pass names and their ordinals"));
126 cl::desc(
"Print IR before the pass with this number as "
127 "reported by print-pass-numbers"));
131 cl::desc(
"Print IR after the pass with this number as "
132 "reported by print-pass-numbers"));
136 cl::desc(
"If specified, IR printed using the "
137 "-print-[before|after]{-all} options will be dumped into "
138 "files in this directory rather than written to stderr"),
142 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&
IR);
143 return IRPtr ? *IRPtr :
nullptr;
157 cl::desc(
"exe called with module IR after each pass that "
162const Module *unwrapModule(
Any IR,
bool Force =
false) {
163 if (
const auto *M = unwrapIR<Module>(
IR))
166 if (
const auto *
F = unwrapIR<Function>(
IR)) {
170 return F->getParent();
173 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
177 return F.getParent();
180 assert(!Force &&
"Expected a module");
184 if (
const auto *L = unwrapIR<Loop>(
IR)) {
185 const Function *
F =
L->getHeader()->getParent();
188 return F->getParent();
191 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
194 return MF->getFunction().getParent();
208 M->print(
OS,
nullptr);
210 for (
const auto &
F : M->functions()) {
226 const Function *
F =
L->getHeader()->getParent();
238std::string getIRName(
Any IR) {
239 if (unwrapIR<Module>(
IR))
242 if (
const auto *
F = unwrapIR<Function>(
IR))
243 return F->getName().str();
245 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
248 if (
const auto *L = unwrapIR<Loop>(
IR))
249 return "loop %" + L->getName().str() +
" in function " +
250 L->getHeader()->getParent()->getName().str();
252 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
258bool moduleContainsFilterPrintFunc(
const Module &M) {
261 return isFunctionInPrintList(F.getName());
274bool shouldPrintIR(
Any IR) {
275 if (
const auto *M = unwrapIR<Module>(
IR))
276 return moduleContainsFilterPrintFunc(*M);
278 if (
const auto *
F = unwrapIR<Function>(
IR))
281 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
282 return sccContainsFilterPrintFunc(*
C);
284 if (
const auto *L = unwrapIR<Loop>(
IR))
287 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
295 if (!shouldPrintIR(
IR))
299 auto *
M = unwrapModule(
IR);
300 assert(M &&
"should have unwrapped module");
305 if (
const auto *M = unwrapIR<Module>(
IR)) {
310 if (
const auto *
F = unwrapIR<Function>(
IR)) {
315 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
320 if (
const auto *L = unwrapIR<Loop>(
IR)) {
325 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
335 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
336 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
337 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
338 "PrintMIRPreparePass"});
346 S.append(Clean.
str());
350 S.append(SR[0] ==
'<' ?
"<" :
">");
358 if (
const auto *M = unwrapIR<Module>(
IR))
360 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
361 return C->begin()->getFunction().getParent();
374 if (
const auto *
F = unwrapIR<Function>(
IR))
375 return isInterestingFunction(*
F);
382 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
398 BeforeStack.emplace_back();
404 T &Data = BeforeStack.back();
405 generateIRRepresentation(
IR, PassID, Data);
411 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
413 std::string
Name = getIRName(
IR);
415 if (isIgnored(PassID)) {
417 handleIgnored(PassID,
Name);
420 handleFiltered(PassID,
Name);
423 T &
Before = BeforeStack.back();
426 generateIRRepresentation(
IR, PassID,
After);
431 omitAfter(PassID,
Name);
435 BeforeStack.pop_back();
440 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
447 handleInvalidated(PassID);
448 BeforeStack.pop_back();
464 handleInvalidatedPass(
P);
475 auto *M = unwrapModule(
IR,
true);
476 assert(M &&
"Expected module to be unwrapped when forced.");
477 Out <<
"*** IR Dump At Start ***\n";
478 M->print(Out,
nullptr);
483 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
489 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
496 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
502 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
514 std::string &Output) {
516 unwrapAndPrint(
OS,
IR);
521 const std::string &
Before,
525 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
531 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
535 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" <<
After;
541 if (TestChanged !=
"")
551 dbgs() <<
"Unable to create temporary file.";
556 dbgs() <<
"Unable to find test-changed executable.";
560 StringRef Args[] = {TestChanged, FileName[0], PassID};
563 dbgs() <<
"Error executing test-changed executable.";
568 dbgs() <<
"Unable to remove temporary file.";
584 const std::string &
Before,
593 const auto &BFD =
Before.getData();
594 const auto &AFD =
After.getData();
595 std::vector<std::string>::const_iterator BI =
Before.getOrder().begin();
596 std::vector<std::string>::const_iterator BE =
Before.getOrder().end();
597 std::vector<std::string>::const_iterator AI =
After.getOrder().begin();
598 std::vector<std::string>::const_iterator AE =
After.getOrder().end();
600 auto HandlePotentiallyRemovedData = [&](std::string S) {
604 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
607 auto HandleNewData = [&](std::vector<const T *> &Q) {
609 for (
const T *NBI : Q)
610 HandlePair(
nullptr, NBI);
623 std::vector<const T *> NewDataQueue;
625 if (!BFD.count(*AI)) {
628 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
637 while (BI != BE && *BI != *AI) {
638 HandlePotentiallyRemovedData(*BI);
642 HandleNewData(NewDataQueue);
644 const T &AData = AFD.find(*AI)->getValue();
645 const T &BData = BFD.find(*AI)->getValue();
646 HandlePair(&BData, &AData);
654 HandlePotentiallyRemovedData(*BI);
658 HandleNewData(NewDataQueue);
664 std::function<
void(
bool InModule,
unsigned Minor,
667 if (!CompareModule) {
670 "Expected only one function.");
671 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
672 After.getData().begin()->getValue());
680 assert((
B ||
A) &&
"Both functions cannot be missing.");
685 CompareFunc(
true, Minor++, *
B, *
A);
690 if (
const Module *M = getModuleForComparison(
IR)) {
693 generateFunctionData(
Data,
F);
697 if (
const auto *
F = unwrapIR<Function>(
IR)) {
698 generateFunctionData(
Data, *
F);
702 if (
const auto *L = unwrapIR<Loop>(
IR)) {
703 auto *
F = L->getHeader()->getParent();
704 generateFunctionData(
Data, *
F);
708 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
709 generateFunctionData(
Data, *MF);
725template <
typename FunctionT>
730 for (
const auto &
B :
F) {
731 std::string BBName =
B.getName().str();
732 if (BBName.empty()) {
739 Data.getOrder().emplace_back(
F.getName());
740 Data.getData().insert({
F.getName(), FD});
748 "PassRunDescriptorStack is not empty at exit");
756 unsigned MaxHashWidth =
sizeof(
uint64_t) * 2;
758 if (unwrapIR<Module>(
IR)) {
759 ResultStream <<
"-module";
760 }
else if (
const auto *
F = unwrapIR<Function>(
IR)) {
761 ResultStream <<
"-function-";
765 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
766 ResultStream <<
"-scc-";
769 }
else if (
const auto *L = unwrapIR<Loop>(
IR)) {
770 ResultStream <<
"-loop-";
773 }
else if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
774 ResultStream <<
"-machine-function-";
788 "The flag -ir-dump-directory must be passed to dump IR to files");
790 ResultPath += RootDirectory;
793 FilenameStream << CurrentPassNumber;
794 FilenameStream <<
"-";
796 FilenameStream <<
"-";
799 return std::string(ResultPath);
809 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
811 return FileSuffixes[
static_cast<size_t>(
Type)];
814void PrintIRInstrumentation::pushPassRunDescriptor(
818 PassRunDescriptor(M, DumpIRFilename, getIRName(
IR), PassID));
821PrintIRInstrumentation::PassRunDescriptor
822PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
823 assert(!PassRunDescriptorStack.
empty() &&
"empty PassRunDescriptorStack");
824 PassRunDescriptor Descriptor = PassRunDescriptorStack.
pop_back_val();
825 assert(Descriptor.PassID == PassID &&
"malformed PassRunDescriptorStack");
833 if (!ParentPath.empty()) {
837 " to support -ir-dump-directory: " + EC.message());
844 " to support -ir-dump-directory: " + EC.message());
848void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
849 if (isIgnored(PassID))
852 std::string DumpIRFilename;
854 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID) ||
855 shouldPrintBeforeCurrentPassNumber() ||
856 shouldPrintAfterCurrentPassNumber()))
857 DumpIRFilename = fetchDumpFilename(PassID,
IR);
863 if (shouldPrintAfterPass(PassID))
864 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
866 if (!shouldPrintIR(
IR))
871 if (shouldPrintPassNumbers())
872 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
873 <<
" on " << getIRName(
IR) <<
"\n";
875 if (shouldPrintAfterCurrentPassNumber())
876 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
878 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
882 Stream <<
"; *** IR Dump Before ";
883 if (shouldPrintBeforeSomePassNumber())
884 Stream << CurrentPassNumber <<
"-";
885 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
886 unwrapAndPrint(Stream,
IR);
889 if (!DumpIRFilename.empty()) {
890 DumpIRFilename +=
getFileSuffix(IRDumpFileSuffixType::Before);
893 WriteIRToStream(DumpIRFileStream);
895 WriteIRToStream(
dbgs());
899void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
900 if (isIgnored(PassID))
903 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
906 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
907 assert(StoredPassID == PassID &&
"mismatched PassID");
909 if (!shouldPrintIR(
IR) ||
910 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
914 Stream <<
"; *** IR Dump After ";
915 if (shouldPrintAfterSomePassNumber())
916 Stream << CurrentPassNumber <<
"-";
917 Stream <<
StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
918 unwrapAndPrint(Stream,
IR);
922 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
923 "should be set in printBeforePass");
924 const std::string DumpIRFilenameWithSuffix =
929 WriteIRToStream(DumpIRFileStream, IRName);
931 WriteIRToStream(
dbgs(), IRName);
935void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
936 if (isIgnored(PassID))
939 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
942 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
943 assert(StoredPassID == PassID &&
"mismatched PassID");
947 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
953 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
955 Stream << Banner <<
"\n";
960 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
961 "should be set in printBeforePass");
962 const std::string DumpIRFilenameWithSuffix =
967 WriteIRToStream(DumpIRFileStream, M, IRName);
969 WriteIRToStream(
dbgs(), M, IRName);
973bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
981bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
989bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
990 return shouldPrintBeforeSomePassNumber() &&
994bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
995 return shouldPrintAfterSomePassNumber() &&
999bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1003bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1007bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1018 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1027 this->printAfterPass(
P,
IR);
1031 this->printAfterPassInvalidated(
P);
1042bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
1043 const auto *
F = unwrapIR<Function>(
IR);
1045 if (
const auto *L = unwrapIR<Loop>(
IR))
1046 F = L->getHeader()->getParent();
1048 bool ShouldRun = !(
F &&
F->hasOptNone());
1049 if (!ShouldRun && DebugLogging) {
1050 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
1051 <<
" due to optnone attribute\n";
1065 this->HasWrittenIR =
true;
1066 const Module *M = unwrapModule(
IR,
true);
1067 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1072 M->print(
OS,
nullptr);
1101 std::vector<StringRef> SpecialPasses;
1103 SpecialPasses.emplace_back(
"PassManager");
1104 SpecialPasses.emplace_back(
"PassAdaptor");
1110 "Unexpectedly skipping special pass");
1112 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1120 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1121 if (
const auto *
F = unwrapIR<Function>(
IR)) {
1122 unsigned Count =
F->getInstructionCount();
1123 OS <<
" (" << Count <<
" instruction";
1127 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
1128 int Count =
C->size();
1129 OS <<
" (" << Count <<
" node";
1155 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1162 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1166 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1172 bool TrackBBLifetime) {
1173 if (TrackBBLifetime)
1175 for (
const auto &BB : *
F) {
1177 BBGuards->try_emplace(intptr_t(&BB), &BB);
1181 BBGuards->try_emplace(intptr_t(Succ), Succ);
1188 out << BB->
getName() <<
"<" << BB <<
">";
1193 out <<
"unnamed_removed<" << BB <<
">";
1199 <<
"<" << BB <<
">";
1203 unsigned FuncOrderBlockNum = 0;
1207 FuncOrderBlockNum++;
1209 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1216 if (
Before.isPoisoned()) {
1217 out <<
"Some blocks were deleted\n";
1223 out <<
"Different number of non-leaf basic blocks: before="
1224 <<
Before.Graph.size() <<
", after=" <<
After.Graph.size() <<
"\n";
1226 for (
auto &BB :
Before.Graph) {
1227 auto BA =
After.Graph.find(BB.first);
1228 if (BA ==
After.Graph.end()) {
1229 out <<
"Non-leaf block ";
1231 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1235 for (
auto &BA :
After.Graph) {
1236 auto BB =
Before.Graph.find(BA.first);
1237 if (BB ==
Before.Graph.end()) {
1238 out <<
"Non-leaf block ";
1240 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1244 if (BB->second == BA.second)
1247 out <<
"Different successors of block ";
1249 out <<
" (unordered):\n";
1250 out <<
"- before (" << BB->second.size() <<
"): ";
1251 for (
auto &SuccB : BB->second) {
1253 if (SuccB.second != 1)
1254 out <<
"(" << SuccB.second <<
"), ";
1259 out <<
"- after (" << BA.second.size() <<
"): ";
1260 for (
auto &SuccA : BA.second) {
1262 if (SuccA.second != 1)
1263 out <<
"(" << SuccA.second <<
"), ";
1343 if (
const auto *MaybeF = unwrapIR<Function>(
IR)) {
1345 }
else if (
const auto *MaybeM = unwrapIR<Module>(
IR)) {
1357 bool Registered =
false;
1360#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1361 assert(&PassStack.emplace_back(
P));
1366 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1381 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1382 auto &M = *
const_cast<Module *
>(MPtr);
1389#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1390 assert(PassStack.pop_back_val() ==
P &&
1391 "Before and After callbacks must correspond");
1398#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1399 assert(PassStack.pop_back_val() ==
P &&
1400 "Before and After callbacks must correspond");
1408 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1412 if (
auto *HashBefore =
1416 "Function @{0} changed by {1} without invalidating analyses",
1422 const CFG &GraphBefore,
const CFG &GraphAfter) {
1423 if (GraphAfter == GraphBefore)
1427 <<
"Error: " <<
Pass
1428 <<
" does not invalidate CFG analyses but CFG changes detected in "
1430 << FuncName <<
":\n";
1435 if (
auto *GraphBefore =
1437 CheckCFG(
P,
F->getName(), *GraphBefore,
1440 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1441 auto &M = *
const_cast<Module *
>(MPtr);
1442 if (
auto *HashBefore =
1446 "Module changed by {0} without invalidating analyses",
P));
1457 if (isIgnored(
P) ||
P ==
"VerifierPass")
1459 const auto *
F = unwrapIR<Function>(
IR);
1461 if (
const auto *L = unwrapIR<Loop>(
IR))
1462 F = L->getHeader()->getParent();
1467 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1471 "\"{0}\", compilation aborted!",
1474 const auto *M = unwrapIR<Module>(
IR);
1476 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
1477 M =
C->begin()->getFunction().getParent();
1482 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1486 "\"{0}\", compilation aborted!",
1490 if (
auto *MF = unwrapIR<MachineFunction>(
IR)) {
1492 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1493 std::string Banner =
1494 formatv(
"Broken machine function found after pass "
1495 "\"{0}\", compilation aborted!",
1525 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1529 [&](
bool InModule,
unsigned Minor,
1532 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1544 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1551 const std::string Removed =
1552 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1553 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1554 const std::string NoChange =
" %l\n";
1555 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1577 this->runAfterPass();
1589void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1598class DotCfgDiffDisplayGraph;
1601class DisplayElement {
1604 StringRef getColour()
const {
return Colour; }
1607 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1613class DisplayEdge :
public DisplayElement {
1618 std::string getValue()
const {
return Value; }
1620 const DisplayNode &getDestinationNode()
const {
return Node; }
1624 const DisplayNode &
Node;
1628class DisplayNode :
public DisplayElement {
1636 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1637 ChildIterator children_begin()
const {
return Children.cbegin(); }
1638 ChildIterator children_end()
const {
return Children.cend(); }
1641 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1642 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1643 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1649 std::string getContent()
const {
return Content; }
1652 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1653 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1654 return *EdgeMap.find(&To)->second;
1659 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1660 return getEdge(Sink).getValue();
1663 void createEdgeMap();
1671 std::vector<DisplayEdge> Edges;
1673 std::vector<DisplayEdge *> EdgePtrs;
1674 std::unordered_set<DisplayNode *>
Children;
1675 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1678 bool AllEdgesCreated =
false;
1682class DotCfgDiffDisplayGraph {
1684 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1687 void generateDotFile(
StringRef DotFile);
1690 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1691 NodeIterator nodes_begin()
const {
1692 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1693 return NodePtrs.cbegin();
1695 NodeIterator nodes_end()
const {
1696 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1697 return NodePtrs.cend();
1702 void setEntryNode(
unsigned N) {
1704 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1705 NodeGenerationComplete =
true;
1706 for (
auto &
N : Nodes)
1707 NodePtrs.emplace_back(&
N);
1709 EntryNode = NodePtrs[
N];
1713 void createNode(std::string
C,
StringRef Colour) {
1714 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1715 Nodes.emplace_back(
C, Colour);
1719 assert(
N < Nodes.size() &&
"Node is out of bounds");
1722 unsigned size()
const {
1723 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1724 return Nodes.size();
1728 std::string getGraphName()
const {
return GraphName; }
1733 return Node.getContent();
1737 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1738 return attribute(
Node.getColour());
1742 std::string getEdgeColorAttr(
const DisplayNode &
From,
1743 const DisplayNode &To)
const {
1744 return attribute(
From.getEdge(To).getColour());
1748 DisplayNode *getEntryNode()
const {
1749 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1755 std::string attribute(
StringRef Colour)
const {
1756 return "color=" + Colour.
str();
1759 bool NodeGenerationComplete =
false;
1760 const std::string GraphName;
1761 std::vector<DisplayNode> Nodes;
1762 std::vector<DisplayNode *> NodePtrs;
1763 DisplayNode *EntryNode =
nullptr;
1768 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1769 Edges.emplace_back(
Value.str(),
Node, Colour);
1773void DisplayNode::createEdgeMap() {
1776 AllEdgesCreated =
true;
1777 for (
auto &E : Edges)
1778 EdgeMap.insert({&E.getDestinationNode(), &E});
1781class DotCfgDiffNode;
1785class DotCfgDiffNode {
1787 DotCfgDiffNode() =
delete;
1793 : Graph(
G),
N(
N), Data{&BD, nullptr}, Colour(Colour) {}
1794 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1795 : Graph(DN.Graph),
N(DN.
N), Data{DN.Data[0], DN.Data[1]},
1799 unsigned getIndex()
const {
return N; }
1803 assert(Data[0] &&
"Expected Data[0] to be set.");
1804 return Data[0]->getLabel();
1807 StringRef getColour()
const {
return Colour; }
1811 assert(!Data[1] &&
"Expected only one block datum");
1819 "Unexpected edge count and color.");
1820 EdgesMap[
E] = {
Value.str(), Colour};
1826 StringRef getEdgeColour(
const unsigned S)
const {
1827 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1828 return EdgesMap.at(S).second;
1832 std::string getBodyContent()
const;
1834 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1835 std::map<const unsigned, unsigned> &NodeMap)
const;
1842 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1844 std::vector<unsigned> Edges;
1857 DotCfgDiff(
const DotCfgDiff &) =
delete;
1858 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1860 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1867 StringRef getEdgeSourceLabel(
const unsigned &Source,
1868 const unsigned &Sink)
const {
1870 getNode(Source).getLabel().str() +
" " +
getNode(Sink).getLabel().str();
1871 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1872 return EdgeLabels.find(S)->getValue();
1876 unsigned size()
const {
return Nodes.size(); }
1878 const DotCfgDiffNode &
getNode(
unsigned N)
const {
1879 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1885 std::string colourize(std::string S,
StringRef Colour)
const;
1888 unsigned Pos = Nodes.size();
1889 Nodes.emplace_back(*
this, Pos, BD,
C);
1890 NodePosition.insert({
Label, Pos});
1896 std::vector<DotCfgDiffNode> Nodes;
1898 const std::string GraphName;
1903std::string DotCfgDiffNode::getBodyContent()
const {
1905 assert(
Data[1] &&
"Expected Data[1] to be set.");
1908 for (
unsigned I = 0;
I < 2; ++
I) {
1909 SR[
I] =
Data[
I]->getBody();
1913 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1917 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1919 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1921 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1922 std::string Diff =
Data[0]->getLabel().str();
1923 Diff +=
":\n<BR align=\"left\"/>" +
1924 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1925 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1930 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1933 std::string S =
R.sub(
"", Diff, &
Error);
1944 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1945 std::string Body = makeHTMLReady(
Data[0]->getBody());
1949 if (BS.
front() ==
'\n')
1954 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1956 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1959 while (BS1.
size()) {
1960 S.append(
"<BR align=\"left\"/>");
1962 S.append(
Line.str());
1965 S.append(
"<BR align=\"left\"/></FONT>");
1969std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1970 if (S.length() == 0)
1972 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1977 : GraphName(Title.str()) {
1981 for (
auto &
B :
Before.getData()) {
1990 Sink != E; ++Sink) {
1991 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1992 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1998 for (
auto &
A :
After.getData()) {
2001 unsigned C = NodePosition.count(Label);
2006 assert(
C == 1 &&
"Unexpected multiple nodes.");
2007 Nodes[NodePosition[
Label]].setCommon(BD);
2012 Sink != E; ++Sink) {
2013 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
2014 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2015 unsigned C = EdgesMap.
count(Key);
2025 for (
auto &E : EdgesMap) {
2028 auto SP1 = S.
rsplit(
' ');
2029 auto &SourceSink = SP1.first;
2030 auto SP2 = SourceSink.split(
' ');
2035 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2036 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2037 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2038 unsigned SinkNode = NodePosition[
Sink];
2042 if (EdgeLabels.count(SourceSink) == 0)
2043 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
2045 StringRef V = EdgeLabels.find(SourceSink)->getValue();
2046 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2048 EdgeLabels[SourceSink] =
NV;
2050 SourceNode.addEdge(SinkNode,
Value, Colour);
2052 for (
auto &
I : Nodes)
2056DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2058 assert(NodePosition.count(EntryNodeName) == 1 &&
2059 "Expected to find entry block in map.");
2060 unsigned Entry = NodePosition[EntryNodeName];
2061 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2062 DotCfgDiffDisplayGraph
G(Title.
str());
2064 std::map<const unsigned, unsigned> NodeMap;
2066 int EntryIndex = -1;
2068 for (
auto &
I : Nodes) {
2069 if (
I.getIndex() == Entry)
2071 G.createNode(
I.getBodyContent(),
I.getColour());
2072 NodeMap.insert({
I.getIndex(),
Index++});
2074 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2075 G.setEntryNode(EntryIndex);
2077 for (
auto &
I : NodeMap) {
2078 unsigned SourceNode =
I.first;
2079 unsigned DisplayNode =
I.second;
2080 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2085void DotCfgDiffNode::createDisplayEdges(
2086 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2087 std::map<const unsigned, unsigned> &NodeMap)
const {
2089 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2091 for (
auto I : Edges) {
2092 unsigned SinkNodeIndex =
I;
2093 StringRef Colour = getEdgeColour(SinkNodeIndex);
2094 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2096 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2097 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2098 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2100 SourceDisplayNode.createEdgeMap();
2103void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2104 for (
auto E : EdgesMap) {
2106 Edges.emplace_back(E.first);
2122 return G->getEntryNode();
2125 return N->children_begin();
2129 return G->nodes_begin();
2132 return G->nodes_end();
2135 return N->edges_begin();
2139 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2149 return DiffData->getGraphName();
2153 return "\tsize=\"190, 190\";\n";
2156 const DotCfgDiffDisplayGraph *DiffData) {
2157 return DiffData->getNodeLabel(*Node);
2160 const DotCfgDiffDisplayGraph *DiffData) {
2161 return DiffData->getNodeAttributes(*Node);
2164 DisplayNode::ChildIterator &To) {
2165 return From->getEdgeSourceLabel(**To);
2168 DisplayNode::ChildIterator &To,
2169 const DotCfgDiffDisplayGraph *DiffData) {
2170 return DiffData->getEdgeColorAttr(*
From, **To);
2178void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2182 errs() <<
"Error: " <<
EC.message() <<
"\n";
2197 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2198 if (Br->isUnconditional())
2204 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2207 for (
auto &
C : Sw->cases()) {
2208 assert(
C.getCaseValue() &&
"Expected to find case value.");
2229 assert(
HTML &&
"Expected outstream to be set");
2234 Extender =
formatv(
"{0}_{1}",
N, Minor);
2243 std::string DotFile =
Twine(SV).
str();
2248 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2252 std::string EntryBlockName =
After.getEntryBlockName();
2254 if (EntryBlockName ==
"")
2255 EntryBlockName =
Before.getEntryBlockName();
2256 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2258 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2259 DG.generateDotFile(DotFile);
2264 errs() <<
"Error: " << EC.message() <<
"\n";
2273 return "Unable to find dot executable.";
2278 return "Error executing system dot.";
2282 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2287 assert(
HTML &&
"Expected outstream to be set");
2288 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2289 <<
"Initial IR (by function)</button>\n"
2290 <<
"<div class=\"content\">\n"
2299 [&](
bool InModule,
unsigned Minor,
2316 assert(
HTML &&
"Expected outstream to be set");
2318 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2319 N, makeHTMLReady(PassID),
Name);
2327 assert(
HTML &&
"Expected outstream to be set");
2330 [&](
bool InModule,
unsigned Minor,
2336 *
HTML <<
" </p></div>\n";
2341 assert(
HTML &&
"Expected outstream to be set");
2343 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2349 assert(
HTML &&
"Expected outstream to be set");
2351 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2352 makeHTMLReady(PassID),
Name);
2358 assert(
HTML &&
"Expected outstream to be set");
2360 makeHTMLReady(PassID),
Name);
2367 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2373 *
HTML <<
"<!doctype html>"
2376 <<
"<style>.collapsible { "
2377 <<
"background-color: #777;"
2379 <<
" cursor: pointer;"
2380 <<
" padding: 18px;"
2383 <<
" text-align: left;"
2384 <<
" outline: none;"
2385 <<
" font-size: 15px;"
2386 <<
"} .active, .collapsible:hover {"
2387 <<
" background-color: #555;"
2389 <<
" padding: 0 18px;"
2390 <<
" display: none;"
2391 <<
" overflow: hidden;"
2392 <<
" background-color: #f1f1f1;"
2395 <<
"<title>passes.html</title>"
2405 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2407 <<
"for (i = 0; i < coll.length; i++) {"
2408 <<
"coll[i].addEventListener(\"click\", function() {"
2409 <<
" this.classList.toggle(\"active\");"
2410 <<
" var content = this.nextElementSibling;"
2411 <<
" if (content.style.display === \"block\"){"
2412 <<
" content.style.display = \"none\";"
2415 <<
" content.style.display= \"block\";"
2433 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2439 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2446 : PrintPass(DebugLogging, PrintPassOpts),
2447 OptNone(DebugLogging),
2472void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2479 "Did not expect to get here without option set.");
2488 "Did not expect to get here without option set.");
2489 CrashReporter =
nullptr;
2498 CrashReporter =
this;
2504 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2507 OS <<
" Filtered Out ***\n";
2510 OS <<
" Started ***\n";
2511 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
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)
Module.h This file contains the declarations for the Module class.
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 ...
This header defines various interfaces for pass management in LLVM.
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< 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
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
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()
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)
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)
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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.
bool shouldPrintAfterSomePass()
void verifyMachineFunction(const std::string &Banner, const MachineFunction &MF)
IRHash StructuralHash(const Function &F, bool DetailedHash=false)
Returns a hash of the function F.
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
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)
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.