45#include <unordered_map>
46#include <unordered_set>
54#ifdef EXPENSIVE_CHECKS
66 cl::desc(
"Print before passes that change them"),
73 cl::desc(
"system dot used by change reporters"));
101 cl::desc(
"Generate dot files into specified directory for changed IRs"),
106 "print-on-crash-path",
107 cl::desc(
"Print the last form of the IR before crash to a file"),
112 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
116 "opt-bisect-print-ir-path",
121 cl::desc(
"Print pass names and their ordinals"));
125 cl::desc(
"Print IR before the pass with this number as "
126 "reported by print-pass-numbers"));
130 cl::desc(
"Print IR after the pass with this number as "
131 "reported by print-pass-numbers"));
135 cl::desc(
"If specified, IR printed using the "
136 "-print-[before|after]{-all} options will be dumped into "
137 "files in this directory rather than written to stderr"),
141 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&
IR);
142 return IRPtr ? *IRPtr :
nullptr;
156 cl::desc(
"exe called with module IR after each pass that "
161const Module *unwrapModule(
Any IR,
bool Force =
false) {
162 if (
const auto *M = unwrapIR<Module>(
IR))
165 if (
const auto *
F = unwrapIR<Function>(
IR)) {
169 return F->getParent();
172 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
176 return F.getParent();
179 assert(!Force &&
"Expected a module");
183 if (
const auto *L = unwrapIR<Loop>(
IR)) {
184 const Function *
F =
L->getHeader()->getParent();
187 return F->getParent();
190 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
193 return MF->getFunction().getParent();
207 M->print(
OS,
nullptr);
209 for (
const auto &
F : M->functions()) {
225 const Function *
F = L->getHeader()->getParent();
237std::string getIRName(
Any IR) {
238 if (unwrapIR<Module>(
IR))
241 if (
const auto *
F = unwrapIR<Function>(
IR))
242 return F->getName().str();
244 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
247 if (
const auto *L = unwrapIR<Loop>(
IR))
248 return "loop %" + L->getName().str() +
" in function " +
249 L->getHeader()->getParent()->getName().str();
251 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
257bool moduleContainsFilterPrintFunc(
const Module &M) {
258 return any_of(M.functions(),
260 return isFunctionInPrintList(F.getName());
273bool shouldPrintIR(
Any IR) {
274 if (
const auto *M = unwrapIR<Module>(
IR))
275 return moduleContainsFilterPrintFunc(*M);
277 if (
const auto *
F = unwrapIR<Function>(
IR))
280 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
281 return sccContainsFilterPrintFunc(*
C);
283 if (
const auto *L = unwrapIR<Loop>(
IR))
286 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
294 if (!shouldPrintIR(
IR))
298 auto *
M = unwrapModule(
IR);
299 assert(M &&
"should have unwrapped module");
304 if (
const auto *M = unwrapIR<Module>(
IR)) {
309 if (
const auto *
F = unwrapIR<Function>(
IR)) {
314 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
319 if (
const auto *L = unwrapIR<Loop>(
IR)) {
324 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
334 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
335 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
336 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
337 "PrintMIRPreparePass"});
345 S.append(Clean.
str());
349 S.append(SR[0] ==
'<' ?
"<" :
">");
357 if (
const auto *M = unwrapIR<Module>(
IR))
359 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
360 return C->begin()->getFunction().getParent();
364bool isInterestingFunction(
const Function &
F) {
373 if (
const auto *
F = unwrapIR<Function>(
IR))
374 return isInterestingFunction(*
F);
381 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
397 BeforeStack.emplace_back();
403 T &Data = BeforeStack.back();
404 generateIRRepresentation(
IR, PassID, Data);
410 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
412 std::string
Name = getIRName(
IR);
414 if (isIgnored(PassID)) {
416 handleIgnored(PassID,
Name);
419 handleFiltered(PassID,
Name);
422 T &
Before = BeforeStack.back();
425 generateIRRepresentation(
IR, PassID,
After);
430 omitAfter(PassID,
Name);
434 BeforeStack.pop_back();
439 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
446 handleInvalidated(PassID);
447 BeforeStack.pop_back();
463 handleInvalidatedPass(
P);
474 auto *M = unwrapModule(
IR,
true);
475 assert(M &&
"Expected module to be unwrapped when forced.");
476 Out <<
"*** IR Dump At Start ***\n";
477 M->print(Out,
nullptr);
482 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
488 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
495 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
501 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
513 std::string &Output) {
515 unwrapAndPrint(
OS,
IR);
520 const std::string &
Before,
524 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
530 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
534 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" <<
After;
540 if (TestChanged !=
"")
550 dbgs() <<
"Unable to create temporary file.";
555 dbgs() <<
"Unable to find test-changed executable.";
559 StringRef Args[] = {TestChanged, FileName[0], PassID};
562 dbgs() <<
"Error executing test-changed executable.";
567 dbgs() <<
"Unable to remove temporary file.";
583 const std::string &
Before,
592 const auto &BFD =
Before.getData();
593 const auto &AFD =
After.getData();
594 std::vector<std::string>::const_iterator BI =
Before.getOrder().begin();
595 std::vector<std::string>::const_iterator BE =
Before.getOrder().end();
596 std::vector<std::string>::const_iterator AI =
After.getOrder().begin();
597 std::vector<std::string>::const_iterator AE =
After.getOrder().end();
599 auto HandlePotentiallyRemovedData = [&](std::string S) {
603 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
606 auto HandleNewData = [&](std::vector<const T *> &Q) {
608 for (
const T *NBI : Q)
609 HandlePair(
nullptr, NBI);
622 std::vector<const T *> NewDataQueue;
624 if (!BFD.count(*AI)) {
627 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
636 while (BI != BE && *BI != *AI) {
637 HandlePotentiallyRemovedData(*BI);
641 HandleNewData(NewDataQueue);
643 const T &AData = AFD.find(*AI)->getValue();
644 const T &BData = BFD.find(*AI)->getValue();
645 HandlePair(&BData, &AData);
653 HandlePotentiallyRemovedData(*BI);
657 HandleNewData(NewDataQueue);
663 std::function<
void(
bool InModule,
unsigned Minor,
666 if (!CompareModule) {
669 "Expected only one function.");
670 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
671 After.getData().begin()->getValue());
679 assert((
B ||
A) &&
"Both functions cannot be missing.");
684 CompareFunc(
true, Minor++, *
B, *
A);
689 if (
const Module *M = getModuleForComparison(
IR)) {
692 generateFunctionData(
Data,
F);
696 if (
const auto *
F = unwrapIR<Function>(
IR)) {
697 generateFunctionData(
Data, *
F);
701 if (
const auto *L = unwrapIR<Loop>(
IR)) {
702 auto *
F = L->getHeader()->getParent();
703 generateFunctionData(
Data, *
F);
707 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
708 generateFunctionData(
Data, *MF);
724template <
typename FunctionT>
729 for (
const auto &
B :
F) {
730 std::string BBName =
B.getName().str();
731 if (BBName.empty()) {
738 Data.getOrder().emplace_back(
F.getName());
739 Data.getData().insert({
F.getName(), FD});
747 "PassRunDescriptorStack is not empty at exit");
755 unsigned int MaxHashWidth =
sizeof(
stable_hash) * 8 / 4;
757 if (unwrapIR<Module>(
IR)) {
758 ResultStream <<
"-module";
759 }
else if (
const auto *
F = unwrapIR<Function>(
IR)) {
760 ResultStream <<
"-function-";
764 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
765 ResultStream <<
"-scc-";
768 }
else if (
const auto *L = unwrapIR<Loop>(
IR)) {
769 ResultStream <<
"-loop-";
772 }
else if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
773 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.equals(PassID) &&
826 "malformed PassRunDescriptorStack");
834 if (!ParentPath.empty()) {
838 " to support -ir-dump-directory: " + EC.message());
845 " to support -ir-dump-directory: " + EC.message());
849void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
850 if (isIgnored(PassID))
853 std::string DumpIRFilename;
855 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID) ||
856 shouldPrintBeforeCurrentPassNumber() ||
857 shouldPrintAfterCurrentPassNumber()))
858 DumpIRFilename = fetchDumpFilename(PassID,
IR);
864 if (shouldPrintAfterPass(PassID))
865 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
867 if (!shouldPrintIR(
IR))
872 if (shouldPrintPassNumbers())
873 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
874 <<
" on " << getIRName(
IR) <<
"\n";
876 if (shouldPrintAfterCurrentPassNumber())
877 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
879 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
883 Stream <<
"; *** IR Dump Before ";
884 if (shouldPrintBeforeSomePassNumber())
885 Stream << CurrentPassNumber <<
"-";
886 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
887 unwrapAndPrint(Stream,
IR);
890 if (!DumpIRFilename.empty()) {
891 DumpIRFilename +=
getFileSuffix(IRDumpFileSuffixType::Before);
894 WriteIRToStream(DumpIRFileStream);
896 WriteIRToStream(
dbgs());
900void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
901 if (isIgnored(PassID))
904 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
907 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
908 assert(StoredPassID == PassID &&
"mismatched PassID");
910 if (!shouldPrintIR(
IR) ||
911 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
915 Stream <<
"; *** IR Dump After ";
916 if (shouldPrintAfterSomePassNumber())
917 Stream << CurrentPassNumber <<
"-";
918 Stream <<
StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
919 unwrapAndPrint(Stream,
IR);
923 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
924 "should be set in printBeforePass");
925 const std::string DumpIRFilenameWithSuffix =
930 WriteIRToStream(DumpIRFileStream, IRName);
932 WriteIRToStream(
dbgs(), IRName);
936void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
937 if (isIgnored(PassID))
940 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
943 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
944 assert(StoredPassID == PassID &&
"mismatched PassID");
948 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
954 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
956 Stream << Banner <<
"\n";
961 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
962 "should be set in printBeforePass");
963 const std::string DumpIRFilenameWithSuffix =
968 WriteIRToStream(DumpIRFileStream, M, IRName);
970 WriteIRToStream(
dbgs(), M, IRName);
974bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
982bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
990bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
991 return shouldPrintBeforeSomePassNumber() &&
995bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
996 return shouldPrintAfterSomePassNumber() &&
1000bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1004bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1008bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1019 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1028 this->printAfterPass(
P,
IR);
1032 this->printAfterPassInvalidated(
P);
1043bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
1044 const auto *
F = unwrapIR<Function>(
IR);
1046 if (
const auto *L = unwrapIR<Loop>(
IR))
1047 F = L->getHeader()->getParent();
1049 bool ShouldRun = !(
F &&
F->hasOptNone());
1050 if (!ShouldRun && DebugLogging) {
1051 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
1052 <<
" due to optnone attribute\n";
1066 this->HasWrittenIR =
true;
1067 const Module *M = unwrapModule(
IR,
true);
1068 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1073 M->print(
OS,
nullptr);
1102 std::vector<StringRef> SpecialPasses;
1104 SpecialPasses.emplace_back(
"PassManager");
1105 SpecialPasses.emplace_back(
"PassAdaptor");
1111 "Unexpectedly skipping special pass");
1113 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1121 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1122 if (
const auto *
F = unwrapIR<Function>(
IR)) {
1123 unsigned Count =
F->getInstructionCount();
1124 OS <<
" (" << Count <<
" instruction";
1128 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
1129 int Count =
C->size();
1130 OS <<
" (" << Count <<
" node";
1156 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1163 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1167 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1173 bool TrackBBLifetime) {
1174 if (TrackBBLifetime)
1176 for (
const auto &BB : *
F) {
1178 BBGuards->try_emplace(intptr_t(&BB), &BB);
1182 BBGuards->try_emplace(intptr_t(Succ), Succ);
1189 out << BB->
getName() <<
"<" << BB <<
">";
1194 out <<
"unnamed_removed<" << BB <<
">";
1200 <<
"<" << BB <<
">";
1204 unsigned FuncOrderBlockNum = 0;
1208 FuncOrderBlockNum++;
1210 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1217 if (
Before.isPoisoned()) {
1218 out <<
"Some blocks were deleted\n";
1224 out <<
"Different number of non-leaf basic blocks: before="
1225 <<
Before.Graph.size() <<
", after=" <<
After.Graph.size() <<
"\n";
1227 for (
auto &BB :
Before.Graph) {
1228 auto BA =
After.Graph.find(BB.first);
1229 if (BA ==
After.Graph.end()) {
1230 out <<
"Non-leaf block ";
1232 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1236 for (
auto &BA :
After.Graph) {
1237 auto BB =
Before.Graph.find(BA.first);
1238 if (BB ==
Before.Graph.end()) {
1239 out <<
"Non-leaf block ";
1241 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1245 if (BB->second == BA.second)
1248 out <<
"Different successors of block ";
1250 out <<
" (unordered):\n";
1251 out <<
"- before (" << BB->second.size() <<
"): ";
1252 for (
auto &SuccB : BB->second) {
1254 if (SuccB.second != 1)
1255 out <<
"(" << SuccB.second <<
"), ";
1260 out <<
"- after (" << BA.second.size() <<
"): ";
1261 for (
auto &SuccA : BA.second) {
1263 if (SuccA.second != 1)
1264 out <<
"(" << SuccA.second <<
"), ";
1344 if (
const auto *MaybeF = unwrapIR<Function>(
IR)) {
1346 }
else if (
const auto *MaybeM = unwrapIR<Module>(
IR)) {
1358 bool Registered =
false;
1361#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1362 assert(&PassStack.emplace_back(
P));
1367 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1382 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1383 auto &M = *
const_cast<Module *
>(MPtr);
1390#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1391 assert(PassStack.pop_back_val() ==
P &&
1392 "Before and After callbacks must correspond");
1399#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1400 assert(PassStack.pop_back_val() ==
P &&
1401 "Before and After callbacks must correspond");
1409 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1413 if (
auto *HashBefore =
1417 "Function @{0} changed by {1} without invalidating analyses",
1423 const CFG &GraphBefore,
const CFG &GraphAfter) {
1424 if (GraphAfter == GraphBefore)
1428 <<
"Error: " <<
Pass
1429 <<
" does not invalidate CFG analyses but CFG changes detected in "
1431 << FuncName <<
":\n";
1436 if (
auto *GraphBefore =
1438 CheckCFG(
P,
F->getName(), *GraphBefore,
1441 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1442 auto &M = *
const_cast<Module *
>(MPtr);
1443 if (
auto *HashBefore =
1447 "Module changed by {0} without invalidating analyses",
P));
1458 if (isIgnored(
P) ||
P ==
"VerifierPass")
1460 const auto *
F = unwrapIR<Function>(
IR);
1462 if (
const auto *L = unwrapIR<Loop>(
IR))
1463 F = L->getHeader()->getParent();
1468 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1472 "\"{0}\", compilation aborted!",
1475 const auto *M = unwrapIR<Module>(
IR);
1477 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
1478 M =
C->begin()->getFunction().getParent();
1483 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1487 "\"{0}\", compilation aborted!",
1492 if (
auto *MF = unwrapIR<MachineFunction>(
IR)) {
1494 dbgs() <<
"Verifying machine function " << MF->
getName() <<
'\n';
1496 formatv(
"Broken machine function found after pass "
1497 "\"{0}\", compilation aborted!",
1518 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1522 [&](
bool InModule,
unsigned Minor,
1525 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1537 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1544 const std::string Removed =
1545 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1546 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1547 const std::string NoChange =
" %l\n";
1548 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1570 this->runAfterPass();
1582void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1591class DotCfgDiffDisplayGraph;
1594class DisplayElement {
1597 StringRef getColour()
const {
return Colour; }
1600 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1606class DisplayEdge :
public DisplayElement {
1611 std::string getValue()
const {
return Value; }
1613 const DisplayNode &getDestinationNode()
const {
return Node; }
1617 const DisplayNode &
Node;
1621class DisplayNode :
public DisplayElement {
1629 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1630 ChildIterator children_begin()
const {
return Children.cbegin(); }
1631 ChildIterator children_end()
const {
return Children.cend(); }
1634 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1635 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1636 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1642 std::string getContent()
const {
return Content; }
1645 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1646 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1647 return *EdgeMap.find(&To)->second;
1652 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1653 return getEdge(Sink).getValue();
1656 void createEdgeMap();
1664 std::vector<DisplayEdge> Edges;
1666 std::vector<DisplayEdge *> EdgePtrs;
1667 std::unordered_set<DisplayNode *>
Children;
1668 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1671 bool AllEdgesCreated =
false;
1675class DotCfgDiffDisplayGraph {
1677 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1680 void generateDotFile(
StringRef DotFile);
1683 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1684 NodeIterator nodes_begin()
const {
1685 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1686 return NodePtrs.cbegin();
1688 NodeIterator nodes_end()
const {
1689 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1690 return NodePtrs.cend();
1695 void setEntryNode(
unsigned N) {
1697 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1698 NodeGenerationComplete =
true;
1699 for (
auto &
N : Nodes)
1700 NodePtrs.emplace_back(&
N);
1702 EntryNode = NodePtrs[
N];
1706 void createNode(std::string
C,
StringRef Colour) {
1707 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1708 Nodes.emplace_back(
C, Colour);
1711 DisplayNode &getNode(
unsigned N) {
1712 assert(
N < Nodes.size() &&
"Node is out of bounds");
1715 unsigned size()
const {
1716 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1717 return Nodes.size();
1721 std::string getGraphName()
const {
return GraphName; }
1726 return Node.getContent();
1730 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1731 return attribute(
Node.getColour());
1735 std::string getEdgeColorAttr(
const DisplayNode &
From,
1736 const DisplayNode &To)
const {
1737 return attribute(
From.getEdge(To).getColour());
1741 DisplayNode *getEntryNode()
const {
1742 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1748 std::string attribute(
StringRef Colour)
const {
1749 return "color=" + Colour.
str();
1752 bool NodeGenerationComplete =
false;
1753 const std::string GraphName;
1754 std::vector<DisplayNode> Nodes;
1755 std::vector<DisplayNode *> NodePtrs;
1756 DisplayNode *EntryNode =
nullptr;
1761 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1762 Edges.emplace_back(
Value.str(),
Node, Colour);
1766void DisplayNode::createEdgeMap() {
1769 AllEdgesCreated =
true;
1770 for (
auto &E : Edges)
1771 EdgeMap.insert({&E.getDestinationNode(), &E});
1774class DotCfgDiffNode;
1778class DotCfgDiffNode {
1780 DotCfgDiffNode() =
delete;
1786 : Graph(
G),
N(
N), Data{&BD, nullptr}, Colour(Colour) {}
1787 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1788 : Graph(DN.Graph),
N(DN.
N), Data{DN.Data[0], DN.Data[1]},
1792 unsigned getIndex()
const {
return N; }
1796 assert(Data[0] &&
"Expected Data[0] to be set.");
1797 return Data[0]->getLabel();
1800 StringRef getColour()
const {
return Colour; }
1804 assert(!Data[1] &&
"Expected only one block datum");
1812 "Unexpected edge count and color.");
1813 EdgesMap[
E] = {
Value.str(), Colour};
1819 StringRef getEdgeColour(
const unsigned S)
const {
1820 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1821 return EdgesMap.at(S).second;
1825 std::string getBodyContent()
const;
1827 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1828 std::map<const unsigned, unsigned> &NodeMap)
const;
1835 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1837 std::vector<unsigned> Edges;
1850 DotCfgDiff(
const DotCfgDiff &) =
delete;
1851 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1853 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1860 StringRef getEdgeSourceLabel(
const unsigned &Source,
1861 const unsigned &Sink)
const {
1863 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1864 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1865 return EdgeLabels.find(S)->getValue();
1869 unsigned size()
const {
return Nodes.size(); }
1871 const DotCfgDiffNode &getNode(
unsigned N)
const {
1872 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1878 std::string colourize(std::string S,
StringRef Colour)
const;
1881 unsigned Pos = Nodes.size();
1882 Nodes.emplace_back(*
this, Pos, BD,
C);
1883 NodePosition.insert({
Label, Pos});
1889 std::vector<DotCfgDiffNode> Nodes;
1891 const std::string GraphName;
1896std::string DotCfgDiffNode::getBodyContent()
const {
1898 assert(
Data[1] &&
"Expected Data[1] to be set.");
1901 for (
unsigned I = 0;
I < 2; ++
I) {
1902 SR[
I] =
Data[
I]->getBody();
1906 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1910 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1912 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1914 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1915 std::string Diff =
Data[0]->getLabel().str();
1916 Diff +=
":\n<BR align=\"left\"/>" +
1917 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1918 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1923 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1926 std::string S =
R.sub(
"", Diff, &
Error);
1937 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1938 std::string Body = makeHTMLReady(
Data[0]->getBody());
1942 if (BS.
front() ==
'\n')
1947 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1949 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1952 while (BS1.
size()) {
1953 S.append(
"<BR align=\"left\"/>");
1955 S.append(
Line.str());
1958 S.append(
"<BR align=\"left\"/></FONT>");
1962std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1963 if (S.length() == 0)
1965 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1970 : GraphName(Title.str()) {
1974 for (
auto &
B :
Before.getData()) {
1983 Sink != E; ++Sink) {
1984 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1985 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1991 for (
auto &
A :
After.getData()) {
1994 unsigned C = NodePosition.count(Label);
1999 assert(
C == 1 &&
"Unexpected multiple nodes.");
2000 Nodes[NodePosition[
Label]].setCommon(BD);
2005 Sink != E; ++Sink) {
2006 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
2007 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2008 unsigned C = EdgesMap.
count(Key);
2018 for (
auto &E : EdgesMap) {
2021 auto SP1 = S.
rsplit(
' ');
2022 auto &SourceSink = SP1.first;
2023 auto SP2 = SourceSink.split(
' ');
2028 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2029 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2030 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2031 unsigned SinkNode = NodePosition[
Sink];
2035 if (EdgeLabels.count(SourceSink) == 0)
2036 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
2038 StringRef V = EdgeLabels.find(SourceSink)->getValue();
2039 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2041 EdgeLabels[SourceSink] =
NV;
2043 SourceNode.addEdge(SinkNode,
Value, Colour);
2045 for (
auto &
I : Nodes)
2049DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2051 assert(NodePosition.count(EntryNodeName) == 1 &&
2052 "Expected to find entry block in map.");
2053 unsigned Entry = NodePosition[EntryNodeName];
2054 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2055 DotCfgDiffDisplayGraph
G(Title.
str());
2057 std::map<const unsigned, unsigned> NodeMap;
2059 int EntryIndex = -1;
2061 for (
auto &
I : Nodes) {
2062 if (
I.getIndex() == Entry)
2064 G.createNode(
I.getBodyContent(),
I.getColour());
2065 NodeMap.insert({
I.getIndex(),
Index++});
2067 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2068 G.setEntryNode(EntryIndex);
2070 for (
auto &
I : NodeMap) {
2071 unsigned SourceNode =
I.first;
2072 unsigned DisplayNode =
I.second;
2073 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2078void DotCfgDiffNode::createDisplayEdges(
2079 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2080 std::map<const unsigned, unsigned> &NodeMap)
const {
2082 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2084 for (
auto I : Edges) {
2085 unsigned SinkNodeIndex =
I;
2086 StringRef Colour = getEdgeColour(SinkNodeIndex);
2087 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2089 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2090 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2091 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2093 SourceDisplayNode.createEdgeMap();
2096void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2097 for (
auto E : EdgesMap) {
2099 Edges.emplace_back(E.first);
2115 return G->getEntryNode();
2118 return N->children_begin();
2122 return G->nodes_begin();
2125 return G->nodes_end();
2128 return N->edges_begin();
2132 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2142 return DiffData->getGraphName();
2146 return "\tsize=\"190, 190\";\n";
2149 const DotCfgDiffDisplayGraph *DiffData) {
2150 return DiffData->getNodeLabel(*Node);
2153 const DotCfgDiffDisplayGraph *DiffData) {
2154 return DiffData->getNodeAttributes(*Node);
2157 DisplayNode::ChildIterator &To) {
2158 return From->getEdgeSourceLabel(**To);
2161 DisplayNode::ChildIterator &To,
2162 const DotCfgDiffDisplayGraph *DiffData) {
2163 return DiffData->getEdgeColorAttr(*
From, **To);
2171void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2175 errs() <<
"Error: " <<
EC.message() <<
"\n";
2190 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2191 if (Br->isUnconditional())
2197 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2200 for (
auto &
C : Sw->cases()) {
2201 assert(
C.getCaseValue() &&
"Expected to find case value.");
2222 assert(
HTML &&
"Expected outstream to be set");
2227 Extender =
formatv(
"{0}_{1}",
N, Minor);
2236 std::string DotFile =
Twine(SV).
str();
2241 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2245 std::string EntryBlockName =
After.getEntryBlockName();
2247 if (EntryBlockName ==
"")
2248 EntryBlockName =
Before.getEntryBlockName();
2249 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2251 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2252 DG.generateDotFile(DotFile);
2257 errs() <<
"Error: " << EC.message() <<
"\n";
2266 return "Unable to find dot executable.";
2271 return "Error executing system dot.";
2275 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2280 assert(
HTML &&
"Expected outstream to be set");
2281 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2282 <<
"Initial IR (by function)</button>\n"
2283 <<
"<div class=\"content\">\n"
2292 [&](
bool InModule,
unsigned Minor,
2309 assert(
HTML &&
"Expected outstream to be set");
2311 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2312 N, makeHTMLReady(PassID),
Name);
2320 assert(
HTML &&
"Expected outstream to be set");
2323 [&](
bool InModule,
unsigned Minor,
2329 *
HTML <<
" </p></div>\n";
2334 assert(
HTML &&
"Expected outstream to be set");
2336 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2342 assert(
HTML &&
"Expected outstream to be set");
2344 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2345 makeHTMLReady(PassID),
Name);
2351 assert(
HTML &&
"Expected outstream to be set");
2353 makeHTMLReady(PassID),
Name);
2360 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2366 *
HTML <<
"<!doctype html>"
2369 <<
"<style>.collapsible { "
2370 <<
"background-color: #777;"
2372 <<
" cursor: pointer;"
2373 <<
" padding: 18px;"
2376 <<
" text-align: left;"
2377 <<
" outline: none;"
2378 <<
" font-size: 15px;"
2379 <<
"} .active, .collapsible:hover {"
2380 <<
" background-color: #555;"
2382 <<
" padding: 0 18px;"
2383 <<
" display: none;"
2384 <<
" overflow: hidden;"
2385 <<
" background-color: #f1f1f1;"
2388 <<
"<title>passes.html</title>"
2398 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2400 <<
"for (i = 0; i < coll.length; i++) {"
2401 <<
"coll[i].addEventListener(\"click\", function() {"
2402 <<
" this.classList.toggle(\"active\");"
2403 <<
" var content = this.nextElementSibling;"
2404 <<
" if (content.style.display === \"block\"){"
2405 <<
" content.style.display = \"none\";"
2408 <<
" content.style.display= \"block\";"
2426 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2432 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2439 : PrintPass(DebugLogging, PrintPassOpts),
2440 OptNone(DebugLogging),
2465void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2472 "Did not expect to get here without option set.");
2481 "Did not expect to get here without option set.");
2482 CrashReporter =
nullptr;
2491 CrashReporter =
this;
2497 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2500 OS <<
" Filtered Out ***\n";
2503 OS <<
" Started ***\n";
2504 unwrapAndPrint(
OS,
IR);
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())
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.
~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.
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)
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.
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()
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)
stable_hash stable_hash_combine_string(const StringRef &S)
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
uint64_t stable_hash
An opaque object representing a stable hash code.
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.