43#include <unordered_map>
44#include <unordered_set>
52#ifdef EXPENSIVE_CHECKS
64 cl::desc(
"Print before passes that change them"),
71 cl::desc(
"system dot used by change reporters"));
99 cl::desc(
"Generate dot files into specified directory for changed IRs"),
104 "print-on-crash-path",
105 cl::desc(
"Print the last form of the IR before crash to a file"),
110 cl::desc(
"Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),
114 "opt-bisect-print-ir-path",
119 cl::desc(
"Print pass names and their ordinals"));
123 cl::desc(
"Print IR at pass with this number as "
124 "reported by print-passes-names"));
128 cl::desc(
"If specified, IR printed using the "
129 "-print-[before|after]{-all} options will be dumped into "
130 "files in this directory rather than written to stderr"),
144 cl::desc(
"exe called with module IR after each pass that "
149const Module *unwrapModule(
Any IR,
bool Force =
false) {
150 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
153 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR)) {
157 return (*F)->getParent();
160 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
164 return F.getParent();
167 assert(!Force &&
"Expected a module");
171 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR)) {
172 const Function *
F = (*L)->getHeader()->getParent();
175 return F->getParent();
189 M->print(
OS,
nullptr);
191 for (
const auto &
F :
M->functions()) {
207 const Function *
F = L->getHeader()->getParent();
213std::string getIRName(
Any IR) {
214 if (llvm::any_cast<const Module *>(&
IR))
217 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
218 return (*F)->getName().str();
220 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
221 return (*C)->getName();
223 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
224 return (*L)->getName().str();
226 if (
const auto **MF = llvm::any_cast<const MachineFunction *>(&
IR))
227 return (*MF)->getName().str();
232bool moduleContainsFilterPrintFunc(
const Module &M) {
233 return any_of(M.functions(),
235 return isFunctionInPrintList(F.getName());
248bool shouldPrintIR(
Any IR) {
249 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
250 return moduleContainsFilterPrintFunc(**M);
252 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
255 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
256 return sccContainsFilterPrintFunc(**
C);
258 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
266 if (!shouldPrintIR(
IR))
270 auto *M = unwrapModule(
IR);
271 assert(M &&
"should have unwrapped module");
276 if (
const auto **M = llvm::any_cast<const Module *>(&
IR)) {
281 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR)) {
286 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
291 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR)) {
301 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
302 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
303 "VerifierPass",
"PrintModulePass"});
311 S.append(Clean.
str());
315 S.append(SR[0] ==
'<' ?
"<" :
">");
323 if (
const auto **M = llvm::any_cast<const Module *>(&
IR))
325 if (
const auto **
C = llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
333bool isInterestingFunction(
const Function &
F) {
342 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR))
343 return isInterestingFunction(**
F);
350 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
366 BeforeStack.emplace_back();
372 T &Data = BeforeStack.back();
373 generateIRRepresentation(
IR, PassID, Data);
379 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
381 std::string
Name = getIRName(
IR);
383 if (isIgnored(PassID)) {
385 handleIgnored(PassID,
Name);
388 handleFiltered(PassID,
Name);
391 T &
Before = BeforeStack.back();
394 generateIRRepresentation(
IR, PassID,
After);
399 omitAfter(PassID,
Name);
403 BeforeStack.pop_back();
408 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
415 handleInvalidated(PassID);
416 BeforeStack.pop_back();
432 handleInvalidatedPass(
P);
443 auto *M = unwrapModule(
IR,
true);
444 assert(M &&
"Expected module to be unwrapped when forced.");
445 Out <<
"*** IR Dump At Start ***\n";
446 M->print(Out,
nullptr);
451 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
457 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
464 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
470 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
482 std::string &Output) {
484 unwrapAndPrint(
OS,
IR);
489 const std::string &
Before,
493 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
499 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
503 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" <<
After;
509 if (TestChanged !=
"")
519 dbgs() <<
"Unable to create temporary file.";
524 dbgs() <<
"Unable to find test-changed executable.";
528 StringRef Args[] = {TestChanged, FileName[0], PassID};
531 dbgs() <<
"Error executing test-changed executable.";
536 dbgs() <<
"Unable to remove temporary file.";
552 const std::string &
Before,
561 const auto &BFD =
Before.getData();
562 const auto &AFD =
After.getData();
563 std::vector<std::string>::const_iterator BI =
Before.getOrder().begin();
564 std::vector<std::string>::const_iterator BE =
Before.getOrder().end();
565 std::vector<std::string>::const_iterator AI =
After.getOrder().begin();
566 std::vector<std::string>::const_iterator AE =
After.getOrder().end();
568 auto HandlePotentiallyRemovedData = [&](std::string S) {
572 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
575 auto HandleNewData = [&](std::vector<const T *> &Q) {
577 for (
const T *NBI : Q)
578 HandlePair(
nullptr, NBI);
591 std::vector<const T *> NewDataQueue;
593 if (!BFD.count(*AI)) {
596 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
605 while (BI != BE && *BI != *AI) {
606 HandlePotentiallyRemovedData(*BI);
610 HandleNewData(NewDataQueue);
612 const T &AData = AFD.find(*AI)->getValue();
613 const T &BData = BFD.find(*AI)->getValue();
614 HandlePair(&BData, &AData);
622 HandlePotentiallyRemovedData(*BI);
626 HandleNewData(NewDataQueue);
632 std::function<
void(
bool InModule,
unsigned Minor,
635 if (!CompareModule) {
638 "Expected only one function.");
639 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
640 After.getData().begin()->getValue());
648 assert((
B ||
A) &&
"Both functions cannot be missing.");
653 CompareFunc(
true, Minor++, *
B, *
A);
658 if (
const Module *M = getModuleForComparison(
IR)) {
661 generateFunctionData(
Data,
F);
665 const Function **FPtr = llvm::any_cast<const Function *>(&
IR);
666 const Function *
F = FPtr ? *FPtr :
nullptr;
668 const Loop **L = llvm::any_cast<const Loop *>(&
IR);
669 assert(L &&
"Unknown IR unit.");
670 F = (*L)->getHeader()->getParent();
672 assert(
F &&
"Unknown IR unit.");
673 generateFunctionData(
Data, *
F);
681 for (
const auto &
B :
F) {
682 std::string BBName =
B.getName().str();
683 if (BBName.empty()) {
690 Data.getOrder().emplace_back(
F.getName());
691 Data.getData().insert({
F.getName(), FD});
699 "PassRunDescriptorStack is not empty at exit");
707 unsigned int MaxHashWidth =
sizeof(
stable_hash) * 8 / 4;
709 if (llvm::any_cast<const Module *>(&
IR)) {
710 ResultStream <<
"-module";
711 }
else if (
const Function **
F = llvm::any_cast<const Function *>(&
IR)) {
712 ResultStream <<
"-function-";
717 llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
718 ResultStream <<
"-scc-";
721 }
else if (
const Loop **L = llvm::any_cast<const Loop *>(&
IR)) {
722 ResultStream <<
"-loop-";
735 "The flag -ir-dump-directory must be passed to dump IR to files");
737 ResultPath += RootDirectory;
740 FilenameStream << CurrentPassNumber;
741 FilenameStream <<
"-";
743 FilenameStream <<
"-";
746 return std::string(ResultPath);
756 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
758 return FileSuffixes[
static_cast<size_t>(
Type)];
761void PrintIRInstrumentation::pushPassRunDescriptor(
765 PassRunDescriptor(M, DumpIRFilename, getIRName(
IR), PassID));
768PrintIRInstrumentation::PassRunDescriptor
769PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
770 assert(!PassRunDescriptorStack.
empty() &&
"empty PassRunDescriptorStack");
771 PassRunDescriptor Descriptor = PassRunDescriptorStack.
pop_back_val();
772 assert(Descriptor.PassID.equals(PassID) &&
773 "malformed PassRunDescriptorStack");
781 if (!ParentPath.empty()) {
785 " to support -ir-dump-directory: " + EC.message());
792 " to support -ir-dump-directory: " + EC.message());
796void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
797 if (isIgnored(PassID))
800 std::string DumpIRFilename;
802 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID)))
803 DumpIRFilename = fetchDumpFilename(PassID,
IR);
809 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
810 shouldPrintAfterPass(PassID))
811 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
813 if (!shouldPrintIR(
IR))
818 if (shouldPrintPassNumbers())
819 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
820 <<
" on " << getIRName(
IR) <<
"\n";
822 if (!shouldPrintBeforePass(PassID))
826 Stream <<
"; *** IR Dump Before " << PassID <<
" on " << getIRName(
IR)
828 unwrapAndPrint(Stream,
IR);
831 if (!DumpIRFilename.empty()) {
832 DumpIRFilename +=
getFileSuffix(IRDumpFileSuffixType::Before);
835 WriteIRToStream(DumpIRFileStream);
837 WriteIRToStream(
dbgs());
841void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
842 if (isIgnored(PassID))
845 if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
846 !shouldPrintAtPassNumber())
849 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
850 assert(StoredPassID == PassID &&
"mismatched PassID");
852 if (!shouldPrintIR(
IR) || !shouldPrintAfterPass(PassID))
856 Stream <<
"; *** IR Dump "
857 << (shouldPrintAtPassNumber()
860 <<
" on " << IRName <<
" ***\n";
861 unwrapAndPrint(Stream,
IR);
865 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
866 "should be set in printBeforePass");
867 const std::string DumpIRFilenameWithSuffix =
872 WriteIRToStream(DumpIRFileStream, IRName);
874 WriteIRToStream(
dbgs(), IRName);
878void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
879 if (isIgnored(PassID))
882 if (!shouldPrintAfterPass(PassID) && !shouldPrintPassNumbers() &&
883 !shouldPrintAtPassNumber())
886 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
887 assert(StoredPassID == PassID &&
"mismatched PassID");
890 if (!M || !shouldPrintAfterPass(PassID))
896 if (shouldPrintAtPassNumber())
897 Banner =
formatv(
"; *** IR Dump At {0}-{1} on {2} (invalidated) ***",
898 CurrentPassNumber, PassID, IRName);
900 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***",
902 Stream << Banner <<
"\n";
907 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
908 "should be set in printBeforePass");
909 const std::string DumpIRFilenameWithSuffix =
914 WriteIRToStream(DumpIRFileStream, M, IRName);
916 WriteIRToStream(
dbgs(), M, IRName);
920bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
928bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
939bool PrintIRInstrumentation::shouldPrintPassNumbers() {
943bool PrintIRInstrumentation::shouldPrintAtPassNumber() {
953 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
958 if (shouldPrintPassNumbers() || shouldPrintAtPassNumber() ||
962 this->printAfterPass(
P,
IR);
966 this->printAfterPassInvalidated(
P);
978 const Function **FPtr = llvm::any_cast<const Function *>(&
IR);
979 const Function *
F = FPtr ? *FPtr :
nullptr;
981 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
982 F = (*L)->getHeader()->getParent();
984 bool ShouldRun = !(
F &&
F->hasOptNone());
985 if (!ShouldRun && DebugLogging) {
986 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
987 <<
" due to optnone attribute\n";
1001 this->HasWrittenIR =
true;
1002 const Module *M = unwrapModule(
IR,
true);
1003 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1008 M->print(
OS,
nullptr);
1037 std::vector<StringRef> SpecialPasses;
1039 SpecialPasses.emplace_back(
"PassManager");
1040 SpecialPasses.emplace_back(
"PassAdaptor");
1046 "Unexpectedly skipping special pass");
1048 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1056 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1057 if (
const auto **
F = llvm::any_cast<const Function *>(&
IR)) {
1058 unsigned Count = (*F)->getInstructionCount();
1059 OS <<
" (" << Count <<
" instruction";
1063 }
else if (
const auto **
C =
1064 llvm::any_cast<const LazyCallGraph::SCC *>(&
IR)) {
1065 int Count = (*C)->size();
1066 OS <<
" (" << Count <<
" node";
1092 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1099 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1103 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1109 bool TrackBBLifetime) {
1110 if (TrackBBLifetime)
1112 for (
const auto &BB : *
F) {
1114 BBGuards->try_emplace(intptr_t(&BB), &BB);
1118 BBGuards->try_emplace(intptr_t(Succ), Succ);
1125 out << BB->
getName() <<
"<" << BB <<
">";
1130 out <<
"unnamed_removed<" << BB <<
">";
1136 <<
"<" << BB <<
">";
1140 unsigned FuncOrderBlockNum = 0;
1144 FuncOrderBlockNum++;
1146 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1153 if (
Before.isPoisoned()) {
1154 out <<
"Some blocks were deleted\n";
1160 out <<
"Different number of non-leaf basic blocks: before="
1161 <<
Before.Graph.size() <<
", after=" <<
After.Graph.size() <<
"\n";
1163 for (
auto &BB :
Before.Graph) {
1164 auto BA =
After.Graph.find(BB.first);
1165 if (BA ==
After.Graph.end()) {
1166 out <<
"Non-leaf block ";
1168 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1172 for (
auto &BA :
After.Graph) {
1173 auto BB =
Before.Graph.find(BA.first);
1174 if (BB ==
Before.Graph.end()) {
1175 out <<
"Non-leaf block ";
1177 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1181 if (BB->second == BA.second)
1184 out <<
"Different successors of block ";
1186 out <<
" (unordered):\n";
1187 out <<
"- before (" << BB->second.size() <<
"): ";
1188 for (
auto &SuccB : BB->second) {
1190 if (SuccB.second != 1)
1191 out <<
"(" << SuccB.second <<
"), ";
1196 out <<
"- after (" << BA.second.size() <<
"): ";
1197 for (
auto &SuccA : BA.second) {
1199 if (SuccA.second != 1)
1200 out <<
"(" << SuccA.second <<
"), ";
1280 if (
const auto **MaybeF = llvm::any_cast<const Function *>(&
IR)) {
1282 }
else if (
const auto **MaybeM = llvm::any_cast<const Module *>(&
IR)) {
1294 bool Registered =
false;
1297#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1298 assert(&PassStack.emplace_back(
P));
1303 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1318 if (
auto *MaybeM = llvm::any_cast<const Module *>(&
IR)) {
1326#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1327 assert(PassStack.pop_back_val() ==
P &&
1328 "Before and After callbacks must correspond");
1335#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1336 assert(PassStack.pop_back_val() ==
P &&
1337 "Before and After callbacks must correspond");
1345 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1349 if (
auto *HashBefore =
1353 "Function @{0} changed by {1} without invalidating analyses",
1359 const CFG &GraphBefore,
const CFG &GraphAfter) {
1360 if (GraphAfter == GraphBefore)
1364 <<
"Error: " <<
Pass
1365 <<
" does not invalidate CFG analyses but CFG changes detected in "
1367 << FuncName <<
":\n";
1372 if (
auto *GraphBefore =
1374 CheckCFG(
P,
F->getName(), *GraphBefore,
1377 if (
auto *MaybeM = llvm::any_cast<const Module *>(&
IR)) {
1379 if (
auto *HashBefore =
1383 "Module changed by {0} without invalidating analyses",
P));
1394 if (isIgnored(
P) ||
P ==
"VerifierPass")
1396 const Function **FPtr = llvm::any_cast<const Function *>(&
IR);
1397 const Function *
F = FPtr ? *FPtr :
nullptr;
1399 if (
const auto **L = llvm::any_cast<const Loop *>(&
IR))
1400 F = (*L)->getHeader()->getParent();
1405 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1409 "\"{0}\", compilation aborted!",
1412 const Module **MPtr = llvm::any_cast<const Module *>(&
IR);
1413 const Module *M = MPtr ? *MPtr :
nullptr;
1415 if (
const auto **
C =
1416 llvm::any_cast<const LazyCallGraph::SCC *>(&
IR))
1417 M = (*C)->begin()->getFunction().getParent();
1422 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1426 "\"{0}\", compilation aborted!",
1446 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1450 [&](
bool InModule,
unsigned Minor,
1453 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1465 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1472 const std::string Removed =
1473 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1474 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1475 const std::string NoChange =
" %l\n";
1476 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1498 this->runAfterPass();
1510void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1519class DotCfgDiffDisplayGraph;
1522class DisplayElement {
1525 StringRef getColour()
const {
return Colour; }
1528 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1534class DisplayEdge :
public DisplayElement {
1539 std::string getValue()
const {
return Value; }
1541 const DisplayNode &getDestinationNode()
const {
return Node; }
1545 const DisplayNode &
Node;
1549class DisplayNode :
public DisplayElement {
1557 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1558 ChildIterator children_begin()
const {
return Children.cbegin(); }
1559 ChildIterator children_end()
const {
return Children.cend(); }
1562 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1563 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1564 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1570 std::string getContent()
const {
return Content; }
1573 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1574 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1575 return *EdgeMap.find(&To)->second;
1580 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1581 return getEdge(Sink).getValue();
1584 void createEdgeMap();
1592 std::vector<DisplayEdge> Edges;
1594 std::vector<DisplayEdge *> EdgePtrs;
1595 std::unordered_set<DisplayNode *>
Children;
1596 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1599 bool AllEdgesCreated =
false;
1603class DotCfgDiffDisplayGraph {
1605 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1608 void generateDotFile(
StringRef DotFile);
1611 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1612 NodeIterator nodes_begin()
const {
1613 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1614 return NodePtrs.cbegin();
1616 NodeIterator nodes_end()
const {
1617 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1618 return NodePtrs.cend();
1623 void setEntryNode(
unsigned N) {
1625 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1626 NodeGenerationComplete =
true;
1627 for (
auto &
N : Nodes)
1628 NodePtrs.emplace_back(&
N);
1630 EntryNode = NodePtrs[
N];
1634 void createNode(std::string
C,
StringRef Colour) {
1635 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1636 Nodes.emplace_back(
C, Colour);
1639 DisplayNode &getNode(
unsigned N) {
1640 assert(
N < Nodes.size() &&
"Node is out of bounds");
1643 unsigned size()
const {
1644 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1645 return Nodes.size();
1649 std::string getGraphName()
const {
return GraphName; }
1654 return Node.getContent();
1658 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1659 return attribute(
Node.getColour());
1663 std::string getEdgeColorAttr(
const DisplayNode &
From,
1664 const DisplayNode &To)
const {
1665 return attribute(
From.getEdge(To).getColour());
1669 DisplayNode *getEntryNode()
const {
1670 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1676 std::string attribute(
StringRef Colour)
const {
1677 return "color=" + Colour.
str();
1680 bool NodeGenerationComplete =
false;
1681 const std::string GraphName;
1682 std::vector<DisplayNode> Nodes;
1683 std::vector<DisplayNode *> NodePtrs;
1684 DisplayNode *EntryNode =
nullptr;
1689 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1690 Edges.emplace_back(
Value.str(),
Node, Colour);
1694void DisplayNode::createEdgeMap() {
1697 AllEdgesCreated =
true;
1698 for (
auto &
E : Edges)
1699 EdgeMap.insert({&
E.getDestinationNode(), &
E});
1702class DotCfgDiffNode;
1706class DotCfgDiffNode {
1708 DotCfgDiffNode() =
delete;
1714 : Graph(
G),
N(
N), Data{&BD, nullptr}, Colour(Colour) {}
1715 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1716 : Graph(DN.Graph),
N(DN.
N), Data{DN.Data[0], DN.Data[1]},
1720 unsigned getIndex()
const {
return N; }
1724 assert(Data[0] &&
"Expected Data[0] to be set.");
1725 return Data[0]->getLabel();
1728 StringRef getColour()
const {
return Colour; }
1732 assert(!Data[1] &&
"Expected only one block datum");
1740 "Unexpected edge count and color.");
1741 EdgesMap[
E] = {
Value.str(), Colour};
1747 StringRef getEdgeColour(
const unsigned S)
const {
1748 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1749 return EdgesMap.at(S).second;
1753 std::string getBodyContent()
const;
1755 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1756 std::map<const unsigned, unsigned> &NodeMap)
const;
1763 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1765 std::vector<unsigned> Edges;
1778 DotCfgDiff(
const DotCfgDiff &) =
delete;
1779 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1781 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1788 StringRef getEdgeSourceLabel(
const unsigned &Source,
1789 const unsigned &Sink)
const {
1791 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1792 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1793 return EdgeLabels.find(S)->getValue();
1797 unsigned size()
const {
return Nodes.size(); }
1799 const DotCfgDiffNode &getNode(
unsigned N)
const {
1800 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1806 std::string colourize(std::string S,
StringRef Colour)
const;
1809 unsigned Pos = Nodes.size();
1810 Nodes.emplace_back(*
this, Pos, BD,
C);
1811 NodePosition.insert({
Label, Pos});
1817 std::vector<DotCfgDiffNode> Nodes;
1819 const std::string GraphName;
1824std::string DotCfgDiffNode::getBodyContent()
const {
1826 assert(
Data[1] &&
"Expected Data[1] to be set.");
1829 for (
unsigned I = 0;
I < 2; ++
I) {
1830 SR[
I] =
Data[
I]->getBody();
1832 if (SR[
I][0] ==
'\n')
1835 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1839 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1841 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1843 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1844 std::string Diff =
Data[0]->getLabel().str();
1845 Diff +=
":\n<BR align=\"left\"/>" +
1846 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1847 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1852 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1855 std::string S =
R.sub(
"", Diff, &
Error);
1866 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1867 std::string Body = makeHTMLReady(
Data[0]->getBody());
1871 if (BS.
front() ==
'\n')
1876 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1878 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1881 while (BS1.
size()) {
1882 S.append(
"<BR align=\"left\"/>");
1884 S.append(
Line.str());
1887 S.append(
"<BR align=\"left\"/></FONT>");
1891std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1892 if (S.length() == 0)
1894 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1899 : GraphName(Title.str()) {
1903 for (
auto &
B :
Before.getData()) {
1912 Sink !=
E; ++Sink) {
1913 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1914 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1920 for (
auto &
A :
After.getData()) {
1923 unsigned C = NodePosition.count(Label);
1928 assert(
C == 1 &&
"Unexpected multiple nodes.");
1929 Nodes[NodePosition[
Label]].setCommon(BD);
1934 Sink !=
E; ++Sink) {
1935 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1936 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1937 unsigned C = EdgesMap.
count(Key);
1947 for (
auto &
E : EdgesMap) {
1950 auto SP1 = S.
rsplit(
' ');
1951 auto &SourceSink = SP1.first;
1952 auto SP2 = SourceSink.split(
' ');
1957 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
1958 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
1959 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
1960 unsigned SinkNode = NodePosition[
Sink];
1964 if (EdgeLabels.count(SourceSink) == 0)
1965 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
1967 StringRef V = EdgeLabels.find(SourceSink)->getValue();
1968 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
1970 EdgeLabels[SourceSink] =
NV;
1972 SourceNode.addEdge(SinkNode,
Value, Colour);
1974 for (
auto &
I : Nodes)
1978DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
1980 assert(NodePosition.count(EntryNodeName) == 1 &&
1981 "Expected to find entry block in map.");
1982 unsigned Entry = NodePosition[EntryNodeName];
1983 assert(Entry < Nodes.size() &&
"Expected to find entry node");
1984 DotCfgDiffDisplayGraph
G(Title.
str());
1986 std::map<const unsigned, unsigned> NodeMap;
1988 int EntryIndex = -1;
1990 for (
auto &
I : Nodes) {
1991 if (
I.getIndex() == Entry)
1993 G.createNode(
I.getBodyContent(),
I.getColour());
1994 NodeMap.insert({
I.getIndex(),
Index++});
1996 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
1997 G.setEntryNode(EntryIndex);
1999 for (
auto &
I : NodeMap) {
2000 unsigned SourceNode =
I.first;
2001 unsigned DisplayNode =
I.second;
2002 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2007void DotCfgDiffNode::createDisplayEdges(
2008 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2009 std::map<const unsigned, unsigned> &NodeMap)
const {
2011 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2013 for (
auto I : Edges) {
2014 unsigned SinkNodeIndex =
I;
2015 StringRef Colour = getEdgeColour(SinkNodeIndex);
2016 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2018 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2019 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2020 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2022 SourceDisplayNode.createEdgeMap();
2025void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2026 for (
auto E : EdgesMap) {
2028 Edges.emplace_back(
E.first);
2044 return G->getEntryNode();
2047 return N->children_begin();
2051 return G->nodes_begin();
2054 return G->nodes_end();
2057 return N->edges_begin();
2061 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2071 return DiffData->getGraphName();
2075 return "\tsize=\"190, 190\";\n";
2078 const DotCfgDiffDisplayGraph *DiffData) {
2079 return DiffData->getNodeLabel(*Node);
2082 const DotCfgDiffDisplayGraph *DiffData) {
2083 return DiffData->getNodeAttributes(*Node);
2086 DisplayNode::ChildIterator &To) {
2087 return From->getEdgeSourceLabel(**To);
2090 DisplayNode::ChildIterator &To,
2091 const DotCfgDiffDisplayGraph *DiffData) {
2092 return DiffData->getEdgeColorAttr(*
From, **To);
2100void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2104 errs() <<
"Error: " <<
EC.message() <<
"\n";
2119 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2120 if (Br->isUnconditional())
2126 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2129 for (
auto &
C : Sw->cases()) {
2130 assert(
C.getCaseValue() &&
"Expected to find case value.");
2146 assert(
HTML &&
"Expected outstream to be set");
2151 Extender =
formatv(
"{0}_{1}",
N, Minor);
2160 std::string DotFile =
Twine(SV).
str();
2165 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2169 std::string EntryBlockName =
After.getEntryBlockName();
2171 if (EntryBlockName ==
"")
2172 EntryBlockName =
Before.getEntryBlockName();
2173 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2175 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2176 DG.generateDotFile(DotFile);
2181 errs() <<
"Error: " << EC.message() <<
"\n";
2190 return "Unable to find dot executable.";
2195 return "Error executing system dot.";
2199 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2204 assert(
HTML &&
"Expected outstream to be set");
2205 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2206 <<
"Initial IR (by function)</button>\n"
2207 <<
"<div class=\"content\">\n"
2216 [&](
bool InModule,
unsigned Minor,
2233 assert(
HTML &&
"Expected outstream to be set");
2235 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2236 N, makeHTMLReady(PassID),
Name);
2244 assert(
HTML &&
"Expected outstream to be set");
2247 [&](
bool InModule,
unsigned Minor,
2253 *
HTML <<
" </p></div>\n";
2258 assert(
HTML &&
"Expected outstream to be set");
2260 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2266 assert(
HTML &&
"Expected outstream to be set");
2268 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2269 makeHTMLReady(PassID),
Name);
2275 assert(
HTML &&
"Expected outstream to be set");
2277 makeHTMLReady(PassID),
Name);
2284 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2290 *
HTML <<
"<!doctype html>"
2293 <<
"<style>.collapsible { "
2294 <<
"background-color: #777;"
2296 <<
" cursor: pointer;"
2297 <<
" padding: 18px;"
2300 <<
" text-align: left;"
2301 <<
" outline: none;"
2302 <<
" font-size: 15px;"
2303 <<
"} .active, .collapsible:hover {"
2304 <<
" background-color: #555;"
2306 <<
" padding: 0 18px;"
2307 <<
" display: none;"
2308 <<
" overflow: hidden;"
2309 <<
" background-color: #f1f1f1;"
2312 <<
"<title>passes.html</title>"
2322 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2324 <<
"for (i = 0; i < coll.length; i++) {"
2325 <<
"coll[i].addEventListener(\"click\", function() {"
2326 <<
" this.classList.toggle(\"active\");"
2327 <<
" var content = this.nextElementSibling;"
2328 <<
" if (content.style.display === \"block\"){"
2329 <<
" content.style.display = \"none\";"
2332 <<
" content.style.display= \"block\";"
2350 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2356 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2363 : PrintPass(DebugLogging, PrintPassOpts),
2364 OptNone(DebugLogging),
2389void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2396 "Did not expect to get here without option set.");
2405 "Did not expect to get here without option set.");
2406 CrashReporter =
nullptr;
2415 CrashReporter =
this;
2421 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2424 OS <<
" Filtered Out ***\n";
2427 OS <<
" Started ***\n";
2428 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< 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< 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< unsigned > PrintAtPassNumber("print-at-pass-number", cl::init(0), cl::Hidden, cl::desc("Print IR at pass with this number as " "reported by print-passes-names"))
static cl::opt< std::string > DotBinary("print-changed-dot-path", cl::Hidden, cl::init("dot"), cl::desc("system dot used by change reporters"))
static int prepareDumpIRFileDescriptor(const StringRef DumpIRFilename)
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 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)
static bool generateFunctionData(IRDataT< T > &Data, const Function &F)
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.
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.
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.
Interval::succ_iterator succ_end(Interval *I)
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
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)
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
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 timeTraceProfilerBegin(StringRef Name, StringRef Detail)
Manually begin a time section, with the given Name and Detail.
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.
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.