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 L->getName().str();
250 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
256bool moduleContainsFilterPrintFunc(
const Module &M) {
259 return isFunctionInPrintList(F.getName());
272bool shouldPrintIR(
Any IR) {
273 if (
const auto *M = unwrapIR<Module>(
IR))
274 return moduleContainsFilterPrintFunc(*M);
276 if (
const auto *
F = unwrapIR<Function>(
IR))
279 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
280 return sccContainsFilterPrintFunc(*
C);
282 if (
const auto *L = unwrapIR<Loop>(
IR))
285 if (
const auto *MF = unwrapIR<MachineFunction>(
IR))
293 if (!shouldPrintIR(
IR))
297 auto *
M = unwrapModule(
IR);
298 assert(M &&
"should have unwrapped module");
301 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
303 for (
const auto &
F : *M) {
304 if (
auto *MF = MMI.getMachineFunction(
F))
311 if (
const auto *M = unwrapIR<Module>(
IR)) {
316 if (
const auto *
F = unwrapIR<Function>(
IR)) {
321 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
326 if (
const auto *L = unwrapIR<Loop>(
IR)) {
331 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
341 {
"PassManager",
"PassAdaptor",
"AnalysisManagerProxy",
342 "DevirtSCCRepeatedPass",
"ModuleInlinerWrapperPass",
343 "VerifierPass",
"PrintModulePass",
"PrintMIRPass",
344 "PrintMIRPreparePass"});
352 S.append(Clean.
str());
356 S.append(SR[0] ==
'<' ?
"<" :
">");
364 if (
const auto *M = unwrapIR<Module>(
IR))
366 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
367 return C->begin()->getFunction().getParent();
371bool isInterestingFunction(
const Function &
F) {
380 if (
const auto *
F = unwrapIR<Function>(
IR))
381 return isInterestingFunction(*
F);
388 assert(BeforeStack.empty() &&
"Problem with Change Printer stack.");
404 BeforeStack.emplace_back();
410 T &Data = BeforeStack.back();
411 generateIRRepresentation(
IR, PassID, Data);
417 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
419 std::string
Name = getIRName(
IR);
421 if (isIgnored(PassID)) {
423 handleIgnored(PassID,
Name);
426 handleFiltered(PassID,
Name);
429 T &
Before = BeforeStack.back();
432 generateIRRepresentation(
IR, PassID,
After);
437 omitAfter(PassID,
Name);
441 BeforeStack.pop_back();
446 assert(!BeforeStack.empty() &&
"Unexpected empty stack encountered.");
453 handleInvalidated(PassID);
454 BeforeStack.pop_back();
470 handleInvalidatedPass(
P);
481 auto *M = unwrapModule(
IR,
true);
482 assert(M &&
"Expected module to be unwrapped when forced.");
483 Out <<
"*** IR Dump At Start ***\n";
484 M->print(Out,
nullptr);
489 Out <<
formatv(
"*** IR Dump After {0} on {1} omitted because no change ***\n",
495 Out <<
formatv(
"*** IR Pass {0} invalidated ***\n", PassID);
502 formatv(
"*** IR Dump After {0} on {1} filtered out ***\n", PassID,
Name);
508 Out <<
formatv(
"*** IR Pass {0} on {1} ignored ***\n", PassID,
Name);
520 std::string &Output) {
522 unwrapAndPrint(
OS,
IR);
527 const std::string &
Before,
531 Out <<
"*** IR Dump Before " << PassID <<
" on " <<
Name <<
" ***\n"
537 Out <<
"*** IR Deleted After " << PassID <<
" on " <<
Name <<
" ***\n";
541 Out <<
"*** IR Dump After " << PassID <<
" on " <<
Name <<
" ***\n" <<
After;
547 if (TestChanged !=
"")
557 dbgs() <<
"Unable to create temporary file.";
562 dbgs() <<
"Unable to find test-changed executable.";
566 StringRef Args[] = {TestChanged, FileName[0], PassID};
569 dbgs() <<
"Error executing test-changed executable.";
574 dbgs() <<
"Unable to remove temporary file.";
590 const std::string &
Before,
599 const auto &BFD =
Before.getData();
600 const auto &AFD =
After.getData();
601 std::vector<std::string>::const_iterator BI =
Before.getOrder().begin();
602 std::vector<std::string>::const_iterator BE =
Before.getOrder().end();
603 std::vector<std::string>::const_iterator AI =
After.getOrder().begin();
604 std::vector<std::string>::const_iterator AE =
After.getOrder().end();
606 auto HandlePotentiallyRemovedData = [&](std::string S) {
610 HandlePair(&BFD.find(*BI)->getValue(),
nullptr);
613 auto HandleNewData = [&](std::vector<const T *> &Q) {
615 for (
const T *NBI : Q)
616 HandlePair(
nullptr, NBI);
629 std::vector<const T *> NewDataQueue;
631 if (!BFD.count(*AI)) {
634 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());
643 while (BI != BE && *BI != *AI) {
644 HandlePotentiallyRemovedData(*BI);
648 HandleNewData(NewDataQueue);
650 const T &AData = AFD.find(*AI)->getValue();
651 const T &BData = BFD.find(*AI)->getValue();
652 HandlePair(&BData, &AData);
660 HandlePotentiallyRemovedData(*BI);
664 HandleNewData(NewDataQueue);
670 std::function<
void(
bool InModule,
unsigned Minor,
673 if (!CompareModule) {
676 "Expected only one function.");
677 CompareFunc(
false, 0,
Before.getData().begin()->getValue(),
678 After.getData().begin()->getValue());
686 assert((
B ||
A) &&
"Both functions cannot be missing.");
691 CompareFunc(
true, Minor++, *
B, *
A);
696 if (
const Module *M = getModuleForComparison(
IR)) {
699 generateFunctionData(
Data,
F);
703 if (
const auto *
F = unwrapIR<Function>(
IR)) {
704 generateFunctionData(
Data, *
F);
708 if (
const auto *L = unwrapIR<Loop>(
IR)) {
709 auto *
F = L->getHeader()->getParent();
710 generateFunctionData(
Data, *
F);
714 if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
715 generateFunctionData(
Data, *MF);
731template <
typename FunctionT>
736 for (
const auto &
B :
F) {
737 std::string BBName =
B.getName().str();
738 if (BBName.empty()) {
745 Data.getOrder().emplace_back(
F.getName());
746 Data.getData().insert({
F.getName(), FD});
754 "PassRunDescriptorStack is not empty at exit");
762 unsigned int MaxHashWidth =
sizeof(
stable_hash) * 8 / 4;
764 if (unwrapIR<Module>(
IR)) {
765 ResultStream <<
"-module";
766 }
else if (
const auto *
F = unwrapIR<Function>(
IR)) {
767 ResultStream <<
"-function-";
771 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
772 ResultStream <<
"-scc-";
775 }
else if (
const auto *L = unwrapIR<Loop>(
IR)) {
776 ResultStream <<
"-loop-";
779 }
else if (
const auto *MF = unwrapIR<MachineFunction>(
IR)) {
780 ResultStream <<
"-machine-function-";
795 "The flag -ir-dump-directory must be passed to dump IR to files");
797 ResultPath += RootDirectory;
800 FilenameStream << CurrentPassNumber;
801 FilenameStream <<
"-";
803 FilenameStream <<
"-";
806 return std::string(ResultPath);
816 static constexpr std::array FileSuffixes = {
"-before.ll",
"-after.ll",
818 return FileSuffixes[
static_cast<size_t>(
Type)];
821void PrintIRInstrumentation::pushPassRunDescriptor(
825 PassRunDescriptor(M, DumpIRFilename, getIRName(
IR), PassID));
828PrintIRInstrumentation::PassRunDescriptor
829PrintIRInstrumentation::popPassRunDescriptor(
StringRef PassID) {
830 assert(!PassRunDescriptorStack.
empty() &&
"empty PassRunDescriptorStack");
831 PassRunDescriptor Descriptor = PassRunDescriptorStack.
pop_back_val();
832 assert(Descriptor.PassID.equals(PassID) &&
833 "malformed PassRunDescriptorStack");
841 if (!ParentPath.empty()) {
845 " to support -ir-dump-directory: " + EC.message());
852 " to support -ir-dump-directory: " + EC.message());
856void PrintIRInstrumentation::printBeforePass(
StringRef PassID,
Any IR) {
857 if (isIgnored(PassID))
860 std::string DumpIRFilename;
862 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID) ||
863 shouldPrintBeforeCurrentPassNumber() ||
864 shouldPrintAfterCurrentPassNumber()))
865 DumpIRFilename = fetchDumpFilename(PassID,
IR);
871 if (shouldPrintAfterPass(PassID))
872 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
874 if (!shouldPrintIR(
IR))
879 if (shouldPrintPassNumbers())
880 dbgs() <<
" Running pass " << CurrentPassNumber <<
" " << PassID
881 <<
" on " << getIRName(
IR) <<
"\n";
883 if (shouldPrintAfterCurrentPassNumber())
884 pushPassRunDescriptor(PassID,
IR, DumpIRFilename);
886 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())
890 Stream <<
"; *** IR Dump Before ";
891 if (shouldPrintBeforeSomePassNumber())
892 Stream << CurrentPassNumber <<
"-";
893 Stream << PassID <<
" on " << getIRName(
IR) <<
" ***\n";
894 unwrapAndPrint(Stream,
IR);
897 if (!DumpIRFilename.empty()) {
898 DumpIRFilename +=
getFileSuffix(IRDumpFileSuffixType::Before);
901 WriteIRToStream(DumpIRFileStream);
903 WriteIRToStream(
dbgs());
907void PrintIRInstrumentation::printAfterPass(
StringRef PassID,
Any IR) {
908 if (isIgnored(PassID))
911 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
914 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
915 assert(StoredPassID == PassID &&
"mismatched PassID");
917 if (!shouldPrintIR(
IR) ||
918 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
922 Stream <<
"; *** IR Dump After ";
923 if (shouldPrintAfterSomePassNumber())
924 Stream << CurrentPassNumber <<
"-";
925 Stream <<
StringRef(
formatv(
"{0}", PassID)) <<
" on " << IRName <<
" ***\n";
926 unwrapAndPrint(Stream,
IR);
930 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
931 "should be set in printBeforePass");
932 const std::string DumpIRFilenameWithSuffix =
937 WriteIRToStream(DumpIRFileStream, IRName);
939 WriteIRToStream(
dbgs(), IRName);
943void PrintIRInstrumentation::printAfterPassInvalidated(
StringRef PassID) {
944 if (isIgnored(PassID))
947 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())
950 auto [
M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);
951 assert(StoredPassID == PassID &&
"mismatched PassID");
955 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))
961 Banner =
formatv(
"; *** IR Dump After {0} on {1} (invalidated) ***", PassID,
963 Stream << Banner <<
"\n";
968 assert(!DumpIRFilename.empty() &&
"DumpIRFilename must not be empty and "
969 "should be set in printBeforePass");
970 const std::string DumpIRFilenameWithSuffix =
975 WriteIRToStream(DumpIRFileStream, M, IRName);
977 WriteIRToStream(
dbgs(), M, IRName);
981bool PrintIRInstrumentation::shouldPrintBeforePass(
StringRef PassID) {
989bool PrintIRInstrumentation::shouldPrintAfterPass(
StringRef PassID) {
997bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {
998 return shouldPrintBeforeSomePassNumber() &&
1002bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {
1003 return shouldPrintAfterSomePassNumber() &&
1007bool PrintIRInstrumentation::shouldPrintPassNumbers() {
1011bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {
1015bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {
1026 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||
1035 this->printAfterPass(
P,
IR);
1039 this->printAfterPassInvalidated(
P);
1050bool OptNoneInstrumentation::shouldRun(
StringRef PassID,
Any IR) {
1051 const auto *
F = unwrapIR<Function>(
IR);
1053 if (
const auto *L = unwrapIR<Loop>(
IR))
1054 F = L->getHeader()->getParent();
1056 bool ShouldRun = !(
F &&
F->hasOptNone());
1057 if (!ShouldRun && DebugLogging) {
1058 errs() <<
"Skipping pass " << PassID <<
" on " <<
F->getName()
1059 <<
" due to optnone attribute\n";
1073 this->HasWrittenIR =
true;
1074 const Module *M = unwrapModule(
IR,
true);
1075 assert((M && &M->getContext() == &Context) &&
"Missing/Mismatching Module");
1080 M->print(
OS,
nullptr);
1109 std::vector<StringRef> SpecialPasses;
1111 SpecialPasses.emplace_back(
"PassManager");
1112 SpecialPasses.emplace_back(
"PassAdaptor");
1118 "Unexpectedly skipping special pass");
1120 print() <<
"Skipping pass: " << PassID <<
" on " << getIRName(
IR) <<
"\n";
1128 OS <<
"Running pass: " << PassID <<
" on " << getIRName(
IR);
1129 if (
const auto *
F = unwrapIR<Function>(
IR)) {
1130 unsigned Count =
F->getInstructionCount();
1131 OS <<
" (" << Count <<
" instruction";
1135 }
else if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR)) {
1136 int Count =
C->size();
1137 OS <<
" (" << Count <<
" node";
1163 print() <<
"Running analysis: " << PassID <<
" on " << getIRName(
IR)
1170 print() <<
"Invalidating analysis: " << PassID <<
" on " << getIRName(
IR)
1174 print() <<
"Clearing all analysis results for: " << IRName <<
"\n";
1180 bool TrackBBLifetime) {
1181 if (TrackBBLifetime)
1183 for (
const auto &BB : *
F) {
1185 BBGuards->try_emplace(intptr_t(&BB), &BB);
1189 BBGuards->try_emplace(intptr_t(Succ), Succ);
1196 out << BB->
getName() <<
"<" << BB <<
">";
1201 out <<
"unnamed_removed<" << BB <<
">";
1207 <<
"<" << BB <<
">";
1211 unsigned FuncOrderBlockNum = 0;
1215 FuncOrderBlockNum++;
1217 out <<
"unnamed_" << FuncOrderBlockNum <<
"<" << BB <<
">";
1224 if (
Before.isPoisoned()) {
1225 out <<
"Some blocks were deleted\n";
1231 out <<
"Different number of non-leaf basic blocks: before="
1232 <<
Before.Graph.size() <<
", after=" <<
After.Graph.size() <<
"\n";
1234 for (
auto &BB :
Before.Graph) {
1235 auto BA =
After.Graph.find(BB.first);
1236 if (BA ==
After.Graph.end()) {
1237 out <<
"Non-leaf block ";
1239 out <<
" is removed (" << BB.second.size() <<
" successors)\n";
1243 for (
auto &BA :
After.Graph) {
1244 auto BB =
Before.Graph.find(BA.first);
1245 if (BB ==
Before.Graph.end()) {
1246 out <<
"Non-leaf block ";
1248 out <<
" is added (" << BA.second.size() <<
" successors)\n";
1252 if (BB->second == BA.second)
1255 out <<
"Different successors of block ";
1257 out <<
" (unordered):\n";
1258 out <<
"- before (" << BB->second.size() <<
"): ";
1259 for (
auto &SuccB : BB->second) {
1261 if (SuccB.second != 1)
1262 out <<
"(" << SuccB.second <<
"), ";
1267 out <<
"- after (" << BA.second.size() <<
"): ";
1268 for (
auto &SuccA : BA.second) {
1270 if (SuccA.second != 1)
1271 out <<
"(" << SuccA.second <<
"), ";
1351 if (
const auto *MaybeF = unwrapIR<Function>(
IR)) {
1353 }
else if (
const auto *MaybeM = unwrapIR<Module>(
IR)) {
1365 bool Registered =
false;
1368#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1369 assert(&PassStack.emplace_back(
P));
1374 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1389 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1390 auto &M = *
const_cast<Module *
>(MPtr);
1397#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1398 assert(PassStack.pop_back_val() ==
P &&
1399 "Before and After callbacks must correspond");
1406#ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
1407 assert(PassStack.pop_back_val() ==
P &&
1408 "Before and After callbacks must correspond");
1416 *
const_cast<Module *
>(unwrapModule(
IR,
true)))
1420 if (
auto *HashBefore =
1424 "Function @{0} changed by {1} without invalidating analyses",
1430 const CFG &GraphBefore,
const CFG &GraphAfter) {
1431 if (GraphAfter == GraphBefore)
1435 <<
"Error: " <<
Pass
1436 <<
" does not invalidate CFG analyses but CFG changes detected in "
1438 << FuncName <<
":\n";
1443 if (
auto *GraphBefore =
1445 CheckCFG(
P,
F->getName(), *GraphBefore,
1448 if (
const auto *MPtr = unwrapIR<Module>(
IR)) {
1449 auto &M = *
const_cast<Module *
>(MPtr);
1450 if (
auto *HashBefore =
1454 "Module changed by {0} without invalidating analyses",
P));
1465 if (isIgnored(
P) ||
P ==
"VerifierPass")
1467 const auto *
F = unwrapIR<Function>(
IR);
1469 if (
const auto *L = unwrapIR<Loop>(
IR))
1470 F = L->getHeader()->getParent();
1475 dbgs() <<
"Verifying function " <<
F->getName() <<
"\n";
1479 "\"{0}\", compilation aborted!",
1482 const auto *M = unwrapIR<Module>(
IR);
1484 if (
const auto *
C = unwrapIR<LazyCallGraph::SCC>(
IR))
1485 M =
C->begin()->getFunction().getParent();
1490 dbgs() <<
"Verifying module " << M->getName() <<
"\n";
1494 "\"{0}\", compilation aborted!",
1514 formatv(
"*** IR Dump After {0} on {1} ***\n", PassID,
Name);
1518 [&](
bool InModule,
unsigned Minor,
1521 handleFunctionCompare(
Name,
"", PassID,
" on ", InModule,
1533 Out <<
"\n*** IR for function " <<
Name <<
" ***\n";
1540 const std::string Removed =
1541 UseColour ?
"\033[31m-%l\033[0m\n" :
"-%l\n";
1542 const std::string Added = UseColour ?
"\033[32m+%l\033[0m\n" :
"+%l\n";
1543 const std::string NoChange =
" %l\n";
1544 Out <<
doSystemDiff(BStr, AStr, Removed, Added, NoChange);
1566 this->runAfterPass();
1578void TimeProfilingPassesHandler::runBeforePass(
StringRef PassID,
Any IR) {
1587class DotCfgDiffDisplayGraph;
1590class DisplayElement {
1593 StringRef getColour()
const {
return Colour; }
1596 DisplayElement(
StringRef Colour) : Colour(Colour) {}
1602class DisplayEdge :
public DisplayElement {
1607 std::string getValue()
const {
return Value; }
1609 const DisplayNode &getDestinationNode()
const {
return Node; }
1613 const DisplayNode &
Node;
1617class DisplayNode :
public DisplayElement {
1625 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;
1626 ChildIterator children_begin()
const {
return Children.cbegin(); }
1627 ChildIterator children_end()
const {
return Children.cend(); }
1630 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;
1631 EdgeIterator edges_begin()
const {
return EdgePtrs.cbegin(); }
1632 EdgeIterator edges_end()
const {
return EdgePtrs.cend(); }
1638 std::string getContent()
const {
return Content; }
1641 const DisplayEdge &getEdge(
const DisplayNode &To)
const {
1642 assert(EdgeMap.find(&To) != EdgeMap.end() &&
"Expected to find edge.");
1643 return *EdgeMap.find(&To)->second;
1648 std::string getEdgeSourceLabel(
const DisplayNode &Sink)
const {
1649 return getEdge(Sink).getValue();
1652 void createEdgeMap();
1660 std::vector<DisplayEdge> Edges;
1662 std::vector<DisplayEdge *> EdgePtrs;
1663 std::unordered_set<DisplayNode *>
Children;
1664 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;
1667 bool AllEdgesCreated =
false;
1671class DotCfgDiffDisplayGraph {
1673 DotCfgDiffDisplayGraph(std::string
Name) : GraphName(
Name) {}
1676 void generateDotFile(
StringRef DotFile);
1679 using NodeIterator = std::vector<DisplayNode *>::const_iterator;
1680 NodeIterator nodes_begin()
const {
1681 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1682 return NodePtrs.cbegin();
1684 NodeIterator nodes_end()
const {
1685 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1686 return NodePtrs.cend();
1691 void setEntryNode(
unsigned N) {
1693 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1694 NodeGenerationComplete =
true;
1695 for (
auto &
N : Nodes)
1696 NodePtrs.emplace_back(&
N);
1698 EntryNode = NodePtrs[
N];
1702 void createNode(std::string
C,
StringRef Colour) {
1703 assert(!NodeGenerationComplete &&
"Unexpected node creation");
1704 Nodes.emplace_back(
C, Colour);
1707 DisplayNode &getNode(
unsigned N) {
1708 assert(
N < Nodes.size() &&
"Node is out of bounds");
1711 unsigned size()
const {
1712 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1713 return Nodes.size();
1717 std::string getGraphName()
const {
return GraphName; }
1722 return Node.getContent();
1726 std::string getNodeAttributes(
const DisplayNode &
Node)
const {
1727 return attribute(
Node.getColour());
1731 std::string getEdgeColorAttr(
const DisplayNode &
From,
1732 const DisplayNode &To)
const {
1733 return attribute(
From.getEdge(To).getColour());
1737 DisplayNode *getEntryNode()
const {
1738 assert(NodeGenerationComplete &&
"Unexpected children iterator creation");
1744 std::string attribute(
StringRef Colour)
const {
1745 return "color=" + Colour.
str();
1748 bool NodeGenerationComplete =
false;
1749 const std::string GraphName;
1750 std::vector<DisplayNode> Nodes;
1751 std::vector<DisplayNode *> NodePtrs;
1752 DisplayNode *EntryNode =
nullptr;
1757 assert(!AllEdgesCreated &&
"Expected to be able to still create edges.");
1758 Edges.emplace_back(
Value.str(),
Node, Colour);
1762void DisplayNode::createEdgeMap() {
1765 AllEdgesCreated =
true;
1766 for (
auto &E : Edges)
1767 EdgeMap.insert({&E.getDestinationNode(), &E});
1770class DotCfgDiffNode;
1774class DotCfgDiffNode {
1776 DotCfgDiffNode() =
delete;
1782 : Graph(
G),
N(
N), Data{&BD, nullptr}, Colour(Colour) {}
1783 DotCfgDiffNode(
const DotCfgDiffNode &DN)
1784 : Graph(DN.Graph),
N(DN.
N), Data{DN.Data[0], DN.Data[1]},
1788 unsigned getIndex()
const {
return N; }
1792 assert(Data[0] &&
"Expected Data[0] to be set.");
1793 return Data[0]->getLabel();
1796 StringRef getColour()
const {
return Colour; }
1800 assert(!Data[1] &&
"Expected only one block datum");
1808 "Unexpected edge count and color.");
1809 EdgesMap[
E] = {
Value.str(), Colour};
1815 StringRef getEdgeColour(
const unsigned S)
const {
1816 assert(EdgesMap.count(S) == 1 &&
"Expected to find edge.");
1817 return EdgesMap.at(S).second;
1821 std::string getBodyContent()
const;
1823 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph,
unsigned DisplayNode,
1824 std::map<const unsigned, unsigned> &NodeMap)
const;
1831 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;
1833 std::vector<unsigned> Edges;
1846 DotCfgDiff(
const DotCfgDiff &) =
delete;
1847 DotCfgDiff &operator=(
const DotCfgDiff &) =
delete;
1849 DotCfgDiffDisplayGraph createDisplayGraph(
StringRef Title,
1856 StringRef getEdgeSourceLabel(
const unsigned &Source,
1857 const unsigned &Sink)
const {
1859 getNode(Source).getLabel().
str() +
" " + getNode(Sink).getLabel().str();
1860 assert(EdgeLabels.count(S) == 1 &&
"Expected to find edge label.");
1861 return EdgeLabels.find(S)->getValue();
1865 unsigned size()
const {
return Nodes.size(); }
1867 const DotCfgDiffNode &getNode(
unsigned N)
const {
1868 assert(
N < Nodes.size() &&
"Unexpected index for node reference");
1874 std::string colourize(std::string S,
StringRef Colour)
const;
1877 unsigned Pos = Nodes.size();
1878 Nodes.emplace_back(*
this, Pos, BD,
C);
1879 NodePosition.insert({
Label, Pos});
1885 std::vector<DotCfgDiffNode> Nodes;
1887 const std::string GraphName;
1892std::string DotCfgDiffNode::getBodyContent()
const {
1894 assert(
Data[1] &&
"Expected Data[1] to be set.");
1897 for (
unsigned I = 0;
I < 2; ++
I) {
1898 SR[
I] =
Data[
I]->getBody();
1902 SR[
I] = SR[
I].
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1906 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
BeforeColour);
1908 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
AfterColour);
1910 "<FONT COLOR=\"{0}\">%l</FONT><BR align=\"left\"/>",
CommonColour);
1911 std::string Diff =
Data[0]->getLabel().str();
1912 Diff +=
":\n<BR align=\"left\"/>" +
1913 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),
1914 OldLineFormat, NewLineFormat, UnchangedLineFormat);
1919 Regex R(
"<FONT COLOR=\"\\w+\"></FONT>");
1922 std::string S =
R.sub(
"", Diff, &
Error);
1933 assert(!
Data[1] &&
"Data[1] is set unexpectedly.");
1934 std::string Body = makeHTMLReady(
Data[0]->getBody());
1938 if (BS.
front() ==
'\n')
1943 BS1 = BS1.
drop_until([](
char C) {
return C ==
'\n'; }).drop_front();
1945 std::string S =
"<FONT COLOR=\"" + Colour.
str() +
"\">" +
Label.str() +
":";
1948 while (BS1.
size()) {
1949 S.append(
"<BR align=\"left\"/>");
1951 S.append(
Line.str());
1954 S.append(
"<BR align=\"left\"/></FONT>");
1958std::string DotCfgDiff::colourize(std::string S,
StringRef Colour)
const {
1959 if (S.length() == 0)
1961 return "<FONT COLOR=\"" + Colour.
str() +
"\">" + S +
"</FONT>";
1966 : GraphName(Title.str()) {
1970 for (
auto &
B :
Before.getData()) {
1979 Sink != E; ++Sink) {
1980 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
1981 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
1987 for (
auto &
A :
After.getData()) {
1990 unsigned C = NodePosition.count(Label);
1995 assert(
C == 1 &&
"Unexpected multiple nodes.");
1996 Nodes[NodePosition[
Label]].setCommon(BD);
2001 Sink != E; ++Sink) {
2002 std::string
Key = (
Label +
" " +
Sink->getKey().str()).str() +
" " +
2003 BD.
getData().getSuccessorLabel(
Sink->getKey()).str();
2004 unsigned C = EdgesMap.
count(Key);
2014 for (
auto &E : EdgesMap) {
2017 auto SP1 = S.
rsplit(
' ');
2018 auto &SourceSink = SP1.first;
2019 auto SP2 = SourceSink.split(
' ');
2024 assert(NodePosition.count(Source) == 1 &&
"Expected to find node.");
2025 DotCfgDiffNode &SourceNode = Nodes[NodePosition[
Source]];
2026 assert(NodePosition.count(Sink) == 1 &&
"Expected to find node.");
2027 unsigned SinkNode = NodePosition[
Sink];
2031 if (EdgeLabels.count(SourceSink) == 0)
2032 EdgeLabels.insert({SourceSink, colourize(
Value.str(), Colour)});
2034 StringRef V = EdgeLabels.find(SourceSink)->getValue();
2035 std::string
NV = colourize(
V.str() +
" " +
Value.str(), Colour);
2037 EdgeLabels[SourceSink] =
NV;
2039 SourceNode.addEdge(SinkNode,
Value, Colour);
2041 for (
auto &
I : Nodes)
2045DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(
StringRef Title,
2047 assert(NodePosition.count(EntryNodeName) == 1 &&
2048 "Expected to find entry block in map.");
2049 unsigned Entry = NodePosition[EntryNodeName];
2050 assert(Entry < Nodes.size() &&
"Expected to find entry node");
2051 DotCfgDiffDisplayGraph
G(Title.
str());
2053 std::map<const unsigned, unsigned> NodeMap;
2055 int EntryIndex = -1;
2057 for (
auto &
I : Nodes) {
2058 if (
I.getIndex() == Entry)
2060 G.createNode(
I.getBodyContent(),
I.getColour());
2061 NodeMap.insert({
I.getIndex(),
Index++});
2063 assert(EntryIndex >= 0 &&
"Expected entry node index to be set.");
2064 G.setEntryNode(EntryIndex);
2066 for (
auto &
I : NodeMap) {
2067 unsigned SourceNode =
I.first;
2068 unsigned DisplayNode =
I.second;
2069 getNode(SourceNode).createDisplayEdges(
G, DisplayNode, NodeMap);
2074void DotCfgDiffNode::createDisplayEdges(
2075 DotCfgDiffDisplayGraph &
DisplayGraph,
unsigned DisplayNodeIndex,
2076 std::map<const unsigned, unsigned> &NodeMap)
const {
2078 DisplayNode &SourceDisplayNode =
DisplayGraph.getNode(DisplayNodeIndex);
2080 for (
auto I : Edges) {
2081 unsigned SinkNodeIndex =
I;
2082 StringRef Colour = getEdgeColour(SinkNodeIndex);
2083 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);
2085 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);
2086 DisplayNode &SinkDisplayNode =
DisplayGraph.getNode(SinkNode->getIndex());
2087 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);
2089 SourceDisplayNode.createEdgeMap();
2092void DotCfgDiffNode::finalize(DotCfgDiff &
G) {
2093 for (
auto E : EdgesMap) {
2095 Edges.emplace_back(E.first);
2111 return G->getEntryNode();
2114 return N->children_begin();
2118 return G->nodes_begin();
2121 return G->nodes_end();
2124 return N->edges_begin();
2128 static unsigned size(
const DotCfgDiffDisplayGraph *
G) {
return G->size(); }
2138 return DiffData->getGraphName();
2142 return "\tsize=\"190, 190\";\n";
2145 const DotCfgDiffDisplayGraph *DiffData) {
2146 return DiffData->getNodeLabel(*Node);
2149 const DotCfgDiffDisplayGraph *DiffData) {
2150 return DiffData->getNodeAttributes(*Node);
2153 DisplayNode::ChildIterator &To) {
2154 return From->getEdgeSourceLabel(**To);
2157 DisplayNode::ChildIterator &To,
2158 const DotCfgDiffDisplayGraph *DiffData) {
2159 return DiffData->getEdgeColorAttr(*
From, **To);
2167void DotCfgDiffDisplayGraph::generateDotFile(
StringRef DotFile) {
2171 errs() <<
"Error: " <<
EC.message() <<
"\n";
2186 if (
const BranchInst *Br = dyn_cast<const BranchInst>(Term))
2187 if (Br->isUnconditional())
2193 else if (
const SwitchInst *Sw = dyn_cast<const SwitchInst>(Term)) {
2196 for (
auto &
C : Sw->cases()) {
2197 assert(
C.getCaseValue() &&
"Expected to find case value.");
2218 assert(
HTML &&
"Expected outstream to be set");
2223 Extender =
formatv(
"{0}_{1}",
N, Minor);
2232 std::string DotFile =
Twine(SV).
str();
2237 Text =
formatv(
"{0}.{1}{2}{3}{4}",
Number, Prefix, makeHTMLReady(PassID),
2241 std::string EntryBlockName =
After.getEntryBlockName();
2243 if (EntryBlockName ==
"")
2244 EntryBlockName =
Before.getEntryBlockName();
2245 assert(EntryBlockName !=
"" &&
"Expected to find entry block");
2247 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);
2248 DG.generateDotFile(DotFile);
2253 errs() <<
"Error: " << EC.message() <<
"\n";
2262 return "Unable to find dot executable.";
2267 return "Error executing system dot.";
2271 " <a href=\"{0}\" target=\"_blank\">{1}</a><br/>\n", PDFFileName, Text);
2276 assert(
HTML &&
"Expected outstream to be set");
2277 *
HTML <<
"<button type=\"button\" class=\"collapsible\">0. "
2278 <<
"Initial IR (by function)</button>\n"
2279 <<
"<div class=\"content\">\n"
2288 [&](
bool InModule,
unsigned Minor,
2305 assert(
HTML &&
"Expected outstream to be set");
2307 formatv(
" <a>{0}. Pass {1} on {2} omitted because no change</a><br/>\n",
2308 N, makeHTMLReady(PassID),
Name);
2316 assert(
HTML &&
"Expected outstream to be set");
2319 [&](
bool InModule,
unsigned Minor,
2325 *
HTML <<
" </p></div>\n";
2330 assert(
HTML &&
"Expected outstream to be set");
2332 formatv(
" <a>{0}. {1} invalidated</a><br/>\n",
N, makeHTMLReady(PassID));
2338 assert(
HTML &&
"Expected outstream to be set");
2340 formatv(
" <a>{0}. Pass {1} on {2} filtered out</a><br/>\n",
N,
2341 makeHTMLReady(PassID),
Name);
2347 assert(
HTML &&
"Expected outstream to be set");
2349 makeHTMLReady(PassID),
Name);
2356 HTML = std::make_unique<raw_fd_ostream>(
DotCfgDir +
"/passes.html", EC);
2362 *
HTML <<
"<!doctype html>"
2365 <<
"<style>.collapsible { "
2366 <<
"background-color: #777;"
2368 <<
" cursor: pointer;"
2369 <<
" padding: 18px;"
2372 <<
" text-align: left;"
2373 <<
" outline: none;"
2374 <<
" font-size: 15px;"
2375 <<
"} .active, .collapsible:hover {"
2376 <<
" background-color: #555;"
2378 <<
" padding: 0 18px;"
2379 <<
" display: none;"
2380 <<
" overflow: hidden;"
2381 <<
" background-color: #f1f1f1;"
2384 <<
"<title>passes.html</title>"
2394 <<
"<script>var coll = document.getElementsByClassName(\"collapsible\");"
2396 <<
"for (i = 0; i < coll.length; i++) {"
2397 <<
"coll[i].addEventListener(\"click\", function() {"
2398 <<
" this.classList.toggle(\"active\");"
2399 <<
" var content = this.nextElementSibling;"
2400 <<
" if (content.style.display === \"block\"){"
2401 <<
" content.style.display = \"none\";"
2404 <<
" content.style.display= \"block\";"
2422 assert(!OutputDir.
empty() &&
"expected output dir to be non-empty");
2428 dbgs() <<
"Unable to open output stream for -cfg-dot-changed\n";
2435 : PrintPass(DebugLogging, PrintPassOpts),
2436 OptNone(DebugLogging),
2461void PrintCrashIRInstrumentation::SignalHandler(
void *) {
2468 "Did not expect to get here without option set.");
2477 "Did not expect to get here without option set.");
2478 CrashReporter =
nullptr;
2487 CrashReporter =
this;
2493 OS <<
formatv(
"*** Dump of {0}IR Before Last Pass {1}",
2496 OS <<
" Filtered Out ***\n";
2499 OS <<
" Started ***\n";
2500 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.
MachineModuleInfo & getMMI() const
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()
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.