LLVM: lib/Passes/StandardInstrumentations.cpp Source File (original) (raw)

275

276bool shouldPrintIR(Any IR) {

278 return moduleContainsFilterPrintFunc(*M);

279

282

284 return sccContainsFilterPrintFunc(*C);

285

288

292}

293

294

295

297 if (!shouldPrintIR(IR))

298 return;

299

301 auto *M = unwrapModule(IR);

302 assert(M && "should have unwrapped module");

303 printIR(OS, M);

304 return;

305 }

306

308 printIR(OS, M);

309 return;

310 }

311

313 printIR(OS, F);

314 return;

315 }

316

318 printIR(OS, C);

319 return;

320 }

321

323 printIR(OS, L);

324 return;

325 }

326

328 printIR(OS, MF);

329 return;

330 }

332}

333

334

335bool isIgnored(StringRef PassID) {

337 {"PassManager", "PassAdaptor", "AnalysisManagerProxy",

338 "DevirtSCCRepeatedPass", "ModuleInlinerWrapperPass",

339 "VerifierPass", "PrintModulePass", "PrintMIRPass",

340 "PrintMIRPreparePass"});

341}

342

343std::string makeHTMLReady(StringRef SR) {

344 std::string S;

345 while (true) {

347 SR.take_until([](char C) { return C == '<' || C == '>'; });

348 S.append(Clean.str());

350 if (SR.size() == 0)

351 return S;

352 S.append(SR[0] == '<' ? "<" : ">");

354 }

356}

357

358

359const Module *getModuleForComparison(Any IR) {

361 return M;

363 return C->begin()->getFunction().getParent();

364 return nullptr;

365}

366

367bool isInterestingFunction(const Function &F) {

369}

370

371

372

375 return false;

377 return isInterestingFunction(*F);

378 return true;

379}

381}

382

386

387template

390

395 }

396

397

398

399

401

403 return;

404

405

408}

409

410template

413 assert(BeforeStack.empty() && "Unexpected empty stack encountered.");

414

415 std::string Name = getIRName(IR);

416

417 if (isIgnored(PassID)) {

423 } else {

424

426

427 T After;

429

430

431 if (Before == After) {

434 } else

436 }

438}

439

440template

442 assert(BeforeStack.empty() && "Unexpected empty stack encountered.");

443

444

445

446

447

451}

452

453template

458 });

459

460 PIC.registerAfterPassCallback(

463 });

464 PIC.registerAfterPassInvalidatedCallback(

467 });

468}

469

470template

473

475

476

477 auto *M = unwrapModule(IR, true);

478 assert(M && "Expected module to be unwrapped when forced.");

479 Out << "*** IR Dump At Start ***\n";

480 M->print(Out, nullptr);

481}

482

483template

485 Out << formatv("*** IR Dump After {0} on {1} omitted because no change ***\n",

486 PassID, Name);

487}

488

489template

491 Out << formatv("*** IR Pass {0} invalidated ***\n", PassID);

492}

493

494template

496 std::string &Name) {

498 formatv("*** IR Dump After {0} on {1} filtered out ***\n", PassID, Name);

499 Out << Banner;

500}

501

502template

504 Out << formatv("*** IR Pass {0} on {1} ignored ***\n", PassID, Name);

505}

506

508

514

516 std::string &Output) {

518 unwrapAndPrint(OS, IR);

519 OS.str();

520}

521

523 const std::string &Before,

524 const std::string &After, Any) {

525

527 Out << "*** IR Dump Before " << PassID << " on " << Name << " ***\n"

528 << Before;

529

530

531

532 if (After.empty()) {

533 Out << "*** IR Deleted After " << PassID << " on " << Name << " ***\n";

534 return;

535 }

536

537 Out << "*** IR Dump After " << PassID << " on " << Name << " ***\n" << After;

538}

539

541

543 if (TestChanged != "")

545}

546

548

553 dbgs() << "Unable to create temporary file.";

554 return;

555 }

557 if (!Exe) {

558 dbgs() << "Unable to find test-changed executable.";

559 return;

560 }

561

562 StringRef Args[] = {TestChanged, FileName[0], PassID};

564 if (Result < 0) {

565 dbgs() << "Error executing test-changed executable.";

566 return;

567 }

568

570 dbgs() << "Unable to remove temporary file.";

571}

572

574

575

576 std::string S;

579}

580

586 const std::string &Before,

587 const std::string &After, Any) {

589}

590

591template

594 function_ref<void(const T *, const T *)> HandlePair) {

595 const auto &BFD = Before.getData();

596 const auto &AFD = After.getData();

597 std::vectorstd::string::const_iterator BI = Before.getOrder().begin();

598 std::vectorstd::string::const_iterator BE = Before.getOrder().end();

599 std::vectorstd::string::const_iterator AI = After.getOrder().begin();

600 std::vectorstd::string::const_iterator AE = After.getOrder().end();

601

602 auto HandlePotentiallyRemovedData = [&](std::string S) {

603

604 if (!AFD.count(S)) {

605

606 HandlePair(&BFD.find(*BI)->getValue(), nullptr);

607 }

608 };

609 auto HandleNewData = [&](std::vector<const T *> &Q) {

610

611 for (const T *NBI : Q)

612 HandlePair(nullptr, NBI);

613 Q.clear();

614 };

615

616

617

618

619

620

621

622

623

624

625 std::vector<const T *> NewDataQueue;

626 while (AI != AE) {

627 if (!BFD.count(*AI)) {

628

629

630 NewDataQueue.emplace_back(&AFD.find(*AI)->getValue());

631 ++AI;

632 continue;

633 }

634

635

636

637

638

639 while (BI != BE && *BI != *AI) {

640 HandlePotentiallyRemovedData(*BI);

641 ++BI;

642 }

643

644 HandleNewData(NewDataQueue);

645

646 const T &AData = AFD.find(*AI)->getValue();

647 const T &BData = BFD.find(*AI)->getValue();

648 HandlePair(&BData, &AData);

649 if (BI != BE)

650 ++BI;

651 ++AI;

652 }

653

654

655 while (BI != BE) {

656 HandlePotentiallyRemovedData(*BI);

657 ++BI;

658 }

659

660 HandleNewData(NewDataQueue);

661}

662

663template

665 bool CompareModule,

666 std::function<void(bool InModule, unsigned Minor,

668 CompareFunc) {

669 if (!CompareModule) {

670

671 assert(Before.getData().size() == 1 && After.getData().size() == 1 &&

672 "Expected only one function.");

673 CompareFunc(false, 0, Before.getData().begin()->getValue(),

674 After.getData().begin()->getValue());

675 return;

676 }

677

678 unsigned Minor = 0;

682 assert((B || A) && "Both functions cannot be missing.");

683 if (B)

684 B = &Missing;

685 else if (A)

686 A = &Missing;

687 CompareFunc(true, Minor++, *B, *A);

688 });

689}

690

692 if (const Module *M = getModuleForComparison(IR)) {

693

696 return;

697 }

698

701 return;

702 }

703

705 auto *F = L->getHeader()->getParent();

707 return;

708 }

709

712 return;

713 }

714

716}

717

721

725

726template

727template

731 int I = 0;

732 for (const auto &B : F) {

733 std::string BBName = B.getName().str();

734 if (BBName.empty()) {

736 ++I;

737 }

738 FD.getOrder().emplace_back(BBName);

740 }

741 Data.getOrder().emplace_back(F.getName());

742 Data.getData().insert({F.getName(), FD});

743 return true;

744 }

745 return false;

746}

747

749 assert(PassRunDescriptorStack.empty() &&

750 "PassRunDescriptorStack is not empty at exit");

751}

752

754 const Module *M = unwrapModule(IR, true);

755 assert(M && "should have unwrapped module");

757 unsigned MaxHashWidth = sizeof(uint64_t) * 2;

760 ResultStream << "-module";

762 ResultStream << "-function-";

763 auto FunctionNameHash = xxh3_64bits(F->getName());

765 MaxHashWidth);

767 ResultStream << "-scc-";

768 auto SCCNameHash = xxh3_64bits(C->getName());

771 ResultStream << "-loop-";

772 auto LoopNameHash = xxh3_64bits(L->getName());

775 ResultStream << "-machine-function-";

778 MaxHashWidth);

779 } else {

781 }

782}

783

785 std::string Result;

788 return Result;

789}

790

791StringRef PrintIRInstrumentation::getFileSuffix(IRDumpFileSuffixType Type) {

792 static constexpr std::array FileSuffixes = {"-before.ll", "-after.ll",

793 "-invalidated.ll"};

794 return FileSuffixes[static_cast<size_t>(Type)];

795}

796

797std::string PrintIRInstrumentation::fetchDumpFilename(

799 IRDumpFileSuffixType SuffixType) {

801 "The flag -ir-dump-directory must be passed to dump IR to files");

802

804 raw_svector_ostream FilenameStream(Filename);

805 FilenameStream << PassNumber;

806 FilenameStream << '-' << IRFileDisplayName << '-';

808 FilenameStream << getFileSuffix(SuffixType);

809

810 SmallString<128> ResultPath;

812 return std::string(ResultPath);

813}

814

815void PrintIRInstrumentation::pushPassRunDescriptor(StringRef PassID, Any IR,

816 unsigned PassNumber) {

817 const Module *M = unwrapModule(IR);

819 getIRName(IR), PassID);

820}

821

822PrintIRInstrumentation::PassRunDescriptor

823PrintIRInstrumentation::popPassRunDescriptor(StringRef PassID) {

824 assert(!PassRunDescriptorStack.empty() && "empty PassRunDescriptorStack");

825 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();

826 assert(Descriptor.PassID == PassID && "malformed PassRunDescriptorStack");

827 return Descriptor;

828}

829

830

832 std::error_code EC;

834 if (!ParentPath.empty()) {

836 if (EC)

838 " to support -ir-dump-directory: " + EC.message());

839 }

840 int Result = 0;

843 if (EC)

845 " to support -ir-dump-directory: " + EC.message());

846 return Result;

847}

848

849void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) {

850 if (isIgnored(PassID))

851 return;

852

853

854

855

856

857 if (shouldPrintAfterPass(PassID))

858 pushPassRunDescriptor(PassID, IR, CurrentPassNumber);

859

860 if (!shouldPrintIR(IR))

861 return;

862

863 ++CurrentPassNumber;

864

865 if (shouldPrintPassNumbers())

866 dbgs() << " Running pass " << CurrentPassNumber << " " << PassID

867 << " on " << getIRName(IR) << "\n";

868

869 if (shouldPrintAfterCurrentPassNumber())

870 pushPassRunDescriptor(PassID, IR, CurrentPassNumber);

871

872 if (!shouldPrintBeforePass(PassID) && !shouldPrintBeforeCurrentPassNumber())

873 return;

874

875 auto WriteIRToStream = [&](raw_ostream &Stream) {

876 Stream << "; *** IR Dump Before ";

877 if (shouldPrintBeforeSomePassNumber())

878 Stream << CurrentPassNumber << "-";

879 Stream << PassID << " on " << getIRName(IR) << " ***\n";

880 unwrapAndPrint(Stream, IR);

881 };

882

884 std::string DumpIRFilename =

886 IRDumpFileSuffixType::Before);

887 llvm::raw_fd_ostream DumpIRFileStream{

889 WriteIRToStream(DumpIRFileStream);

890 } else {

891 WriteIRToStream(dbgs());

892 }

893}

894

895void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) {

896 if (isIgnored(PassID))

897 return;

898

899 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())

900 return;

901

902 auto [M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =

903 popPassRunDescriptor(PassID);

904 assert(StoredPassID == PassID && "mismatched PassID");

905

906 if (!shouldPrintIR(IR) ||

907 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))

908 return;

909

910 auto WriteIRToStream = [&](raw_ostream &Stream, const StringRef IRName) {

911 Stream << "; *** IR Dump After ";

912 if (shouldPrintAfterSomePassNumber())

913 Stream << CurrentPassNumber << "-";

914 Stream << StringRef(formatv("{0}", PassID)) << " on " << IRName << " ***\n";

915 unwrapAndPrint(Stream, IR);

916 };

917

919 std::string DumpIRFilename =

921 IRDumpFileSuffixType::After);

922 llvm::raw_fd_ostream DumpIRFileStream{

924 true};

925 WriteIRToStream(DumpIRFileStream, IRName);

926 } else {

927 WriteIRToStream(dbgs(), IRName);

928 }

929}

930

931void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {

932 if (isIgnored(PassID))

933 return;

934

935 if (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber())

936 return;

937

938 auto [M, PassNumber, IRFileDisplayName, IRName, StoredPassID] =

939 popPassRunDescriptor(PassID);

940 assert(StoredPassID == PassID && "mismatched PassID");

941

942

943 if (!M ||

944 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))

945 return;

946

947 auto WriteIRToStream = [&](raw_ostream &Stream, const Module *M,

948 const StringRef IRName) {

949 SmallString<20> Banner;

950 Banner = formatv("; *** IR Dump After {0} on {1} (invalidated) ***", PassID,

951 IRName);

952 Stream << Banner << "\n";

953 printIR(Stream, M);

954 };

955

957 std::string DumpIRFilename =

958 fetchDumpFilename(PassID, IRFileDisplayName, PassNumber,

959 IRDumpFileSuffixType::Invalidated);

960 llvm::raw_fd_ostream DumpIRFileStream{

962 true};

963 WriteIRToStream(DumpIRFileStream, M, IRName);

964 } else {

965 WriteIRToStream(dbgs(), M, IRName);

966 }

967}

968

969bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {

971 return true;

972

973 StringRef PassName = PIC->getPassNameForClassName(PassID);

975}

976

977bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {

979 return true;

980

981 StringRef PassName = PIC->getPassNameForClassName(PassID);

983}

984

985bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {

986 return shouldPrintBeforeSomePassNumber() &&

988}

989

990bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {

991 return shouldPrintAfterSomePassNumber() &&

993}

994

995bool PrintIRInstrumentation::shouldPrintPassNumbers() {

997}

998

999bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {

1001}

1002

1003bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {

1005}

1006

1009 this->PIC = &PIC;

1010

1011

1012

1013

1014 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||

1019

1021 PIC.registerAfterPassCallback(

1023 this->printAfterPass(P, IR);

1024 });

1025 PIC.registerAfterPassInvalidatedCallback(

1027 this->printAfterPassInvalidated(P);

1028 });

1029 }

1030}

1031

1034 PIC.registerShouldRunOptionalPassCallback(

1036}

1037

1038bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) {

1039 bool ShouldRun = true;

1041 ShouldRun = F->hasOptNone();

1043 ShouldRun = !L->getHeader()->getParent()->hasOptNone();

1046

1047 if (!ShouldRun && DebugLogging) {

1048 errs() << "Skipping pass " << PassID << " on " << getIRName(IR)

1049 << " due to optnone attribute\n";

1050 }

1051 return ShouldRun;

1052}

1053

1056 return true;

1057

1058 bool ShouldRun =

1059 Context.getOptPassGate().shouldRunPass(PassName, getIRName(IR));

1061

1062

1063 this->HasWrittenIR = true;

1064 const Module *M = unwrapModule(IR, true);

1065 assert((M && &M->getContext() == &Context) && "Missing/Mismatching Module");

1066 std::error_code EC;

1068 if (EC)

1070 M->print(OS, nullptr);

1071 }

1072 return ShouldRun;

1073}

1074

1077 const OptPassGate &PassGate = Context.getOptPassGate();

1079 return;

1080

1081 PIC.registerShouldRunOptionalPassCallback(

1087 });

1088}

1089

1090raw_ostream &PrintPassInstrumentation::print() {

1092 assert(Indent >= 0);

1094 }

1095 return dbgs();

1096}

1097

1100 if (!Enabled)

1101 return;

1102

1103 std::vector SpecialPasses;

1104 if (!Opts.Verbose) {

1105 SpecialPasses.emplace_back("PassManager");

1106 SpecialPasses.emplace_back("PassAdaptor");

1107 }

1108

1109 PIC.registerBeforeSkippedPassCallback([this, SpecialPasses](StringRef PassID,

1112 "Unexpectedly skipping special pass");

1113

1114 print() << "Skipping pass: " << PassID << " on " << getIRName(IR) << "\n";

1115 });

1116 PIC.registerBeforeNonSkippedPassCallback([this, SpecialPasses](

1119 return;

1120

1121 auto &OS = print();

1122 OS << "Running pass: " << PassID << " on " << getIRName(IR);

1124 unsigned Count = F->getInstructionCount();

1125 OS << " (" << Count << " instruction";

1127 OS << 's';

1128 OS << ')';

1130 int Count = C->size();

1131 OS << " (" << Count << " node";

1133 OS << 's';

1134 OS << ')';

1135 }

1136 OS << "\n";

1137 Indent += 2;

1138 });

1139 PIC.registerAfterPassCallback(

1143 return;

1144

1145 Indent -= 2;

1146 });

1147 PIC.registerAfterPassInvalidatedCallback(

1150 return;

1151

1152 Indent -= 2;

1153 });

1154

1155 if (!Opts.SkipAnalyses) {

1156 PIC.registerBeforeAnalysisCallback([this](StringRef PassID, Any IR) {

1157 print() << "Running analysis: " << PassID << " on " << getIRName(IR)

1158 << "\n";

1159 Indent += 2;

1160 });

1161 PIC.registerAfterAnalysisCallback(

1163 PIC.registerAnalysisInvalidatedCallback([this](StringRef PassID, Any IR) {

1164 print() << "Invalidating analysis: " << PassID << " on " << getIRName(IR)

1165 << "\n";

1166 });

1167 PIC.registerAnalysesClearedCallback([this](StringRef IRName) {

1168 print() << "Clearing all analysis results for: " << IRName << "\n";

1169 });

1170 }

1171}

1172

1174 bool TrackBBLifetime) {

1175 if (TrackBBLifetime)

1177 for (const auto &BB : *F) {

1179 BBGuards->try_emplace(intptr_t(&BB), &BB);

1180 for (const auto *Succ : successors(&BB)) {

1181 Graph[&BB][Succ]++;

1183 BBGuards->try_emplace(intptr_t(Succ), Succ);

1184 }

1185 }

1186}

1187

1190 out << BB->getName() << "<" << BB << ">";

1191 return;

1192 }

1193

1195 out << "unnamed_removed<" << BB << ">";

1196 return;

1197 }

1198

1200 out << "entry"

1201 << "<" << BB << ">";

1202 return;

1203 }

1204

1205 unsigned FuncOrderBlockNum = 0;

1206 for (auto &FuncBB : *BB->getParent()) {

1207 if (&FuncBB == BB)

1208 break;

1209 FuncOrderBlockNum++;

1210 }

1211 out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">";

1212}

1213

1215 const CFG &Before,

1216 const CFG &After) {

1219 out << "Some blocks were deleted\n";

1220 return;

1221 }

1222

1223

1224 if (Before.Graph.size() != After.Graph.size())

1225 out << "Different number of non-leaf basic blocks: before="

1226 << Before.Graph.size() << ", after=" << After.Graph.size() << "\n";

1227

1228 for (auto &BB : Before.Graph) {

1229 auto BA = After.Graph.find(BB.first);

1230 if (BA == After.Graph.end()) {

1231 out << "Non-leaf block ";

1233 out << " is removed (" << BB.second.size() << " successors)\n";

1234 }

1235 }

1236

1237 for (auto &BA : After.Graph) {

1238 auto BB = Before.Graph.find(BA.first);

1239 if (BB == Before.Graph.end()) {

1240 out << "Non-leaf block ";

1242 out << " is added (" << BA.second.size() << " successors)\n";

1243 continue;

1244 }

1245

1246 if (BB->second == BA.second)

1247 continue;

1248

1249 out << "Different successors of block ";

1251 out << " (unordered):\n";

1252 out << "- before (" << BB->second.size() << "): ";

1253 for (auto &SuccB : BB->second) {

1255 if (SuccB.second != 1)

1256 out << "(" << SuccB.second << "), ";

1257 else

1258 out << ", ";

1259 }

1260 out << "\n";

1261 out << "- after (" << BA.second.size() << "): ";

1262 for (auto &SuccA : BA.second) {

1264 if (SuccA.second != 1)

1265 out << "(" << SuccA.second << "), ";

1266 else

1267 out << ", ";

1268 }

1269 out << "\n";

1270 }

1271}

1272

1273

1274

1275

1276

1277

1278

1279

1280

1281

1285

1287

1288public:

1289

1291

1292

1294 return Result(&F, true);

1295 }

1296};

1297

1299

1314

1316

1331

1333

1336 FunctionAnalysisManager::Invalidator &) {

1340}

1341

1344

1346 Functions.push_back(const_cast<Function *>(MaybeF));

1349 Functions.push_back(&F);

1350 }

1351 return Functions;

1352}

1353

1357 return;

1358

1359 bool Registered = false;

1360 PIC.registerBeforeNonSkippedPassCallback([this, &MAM, Registered](

1362#if LLVM_ENABLE_ABI_BREAKING_CHECKS

1363 assert(&PassStack.emplace_back(P));

1364#endif

1365 (void)this;

1366

1368 *const_cast<Module *>(unwrapModule(IR, true)))

1369 .getManager();

1370 if (!Registered) {

1374 Registered = true;

1375 }

1376

1378

1381 }

1382

1384 auto &M = *const_cast<Module *>(MPtr);

1386 }

1387 });

1388

1389 PIC.registerAfterPassInvalidatedCallback(

1391#if LLVM_ENABLE_ABI_BREAKING_CHECKS

1392 assert(PassStack.pop_back_val() == P &&

1393 "Before and After callbacks must correspond");

1394#endif

1395 (void)this;

1396 });

1397

1400#if LLVM_ENABLE_ABI_BREAKING_CHECKS

1401 assert(PassStack.pop_back_val() == P &&

1402 "Before and After callbacks must correspond");

1403#endif

1404 (void)this;

1405

1406

1407

1408

1410 *const_cast<Module *>(unwrapModule(IR, true)))

1411 .getManager();

1412

1414 if (auto *HashBefore =

1418 "Function @{0} changed by {1} without invalidating analyses",

1419 F->getName(), P));

1420 }

1421 }

1422

1424 const CFG &GraphBefore, const CFG &GraphAfter) {

1425 if (GraphAfter == GraphBefore)

1426 return;

1427

1429 << "Error: " << Pass

1430 << " does not invalidate CFG analyses but CFG changes detected in "

1431 "function @"

1432 << FuncName << ":\n";

1435 };

1436

1437 if (auto *GraphBefore =

1439 CheckCFG(P, F->getName(), *GraphBefore,

1440 CFG(F, false));

1441 }

1443 auto &M = *const_cast<Module *>(MPtr);

1444 if (auto *HashBefore =

1448 "Module changed by {0} without invalidating analyses", P));

1449 }

1450 }

1451 }

1452 });

1453}

1454

1457 PIC.registerAfterPassCallback(

1459 if (isIgnored(P) || P == "VerifierPass")

1460 return;

1462 if (F) {

1464 F = L->getHeader()->getParent();

1465 }

1466

1467 if (F) {

1468 if (DebugLogging)

1469 dbgs() << "Verifying function " << F->getName() << "\n";

1470

1473 "\"{0}\", compilation aborted!",

1474 P));

1475 } else {

1477 if (!M) {

1479 M = C->begin()->getFunction().getParent();

1480 }

1481

1482 if (M) {

1483 if (DebugLogging)

1484 dbgs() << "Verifying module " << M->getName() << "\n";

1485

1488 "\"{0}\", compilation aborted!",

1489 P));

1490 }

1491

1493 if (DebugLogging)

1494 dbgs() << "Verifying machine function " << MF->getName() << '\n';

1495 std::string Banner =

1496 formatv("Broken machine function found after pass "

1497 "\"{0}\", compilation aborted!",

1498 P);

1499 if (MAM) {

1501 auto &MFAM =

1503 .getManager();

1506 } else {

1508 }

1509 }

1510 }

1511 });

1512}

1513

1515

1521

1527 formatv("*** IR Dump After {0} on {1} ***\n", PassID, Name);

1528 Out << Banner;

1530 .compare(getModuleForComparison(IR),

1531 [&](bool InModule, unsigned Minor,

1535 Minor, Before, After);

1536 });

1537 Out << "\n";

1538}

1539

1544

1545 if (InModule)

1546 Out << "\n*** IR for function " << Name << " ***\n";

1547

1549 Before, After,

1551 StringRef BStr = B ? B->getBody() : "\n";

1552 StringRef AStr = A ? A->getBody() : "\n";

1553 const std::string Removed =

1554 UseColour ? "\033[31m-%l\033[0m\n" : "-%l\n";

1555 const std::string Added = UseColour ? "\033[32m+%l\033[0m\n" : "+%l\n";

1556 const std::string NoChange = " %l\n";

1557 Out << doSystemDiff(BStr, AStr, Removed, Added, NoChange);

1558 });

1559}

1560

1568

1570

1574 return;

1575 PIC.registerBeforeNonSkippedPassCallback(

1577 PIC.registerAfterPassCallback(

1579 this->runAfterPass();

1580 },

1581 true);

1582 PIC.registerAfterPassInvalidatedCallback(

1584 true);

1585 PIC.registerBeforeAnalysisCallback(

1587 PIC.registerAfterAnalysisCallback(

1588 [this](StringRef P, Any IR) { this->runAfterPass(); }, true);

1589}

1590

1591void TimeProfilingPassesHandler::runBeforePass(StringRef PassID, Any IR) {

1593}

1594

1596

1597namespace {

1598

1599class DisplayNode;

1600class DotCfgDiffDisplayGraph;

1601

1602

1603class DisplayElement {

1604public:

1605

1606 StringRef getColour() const { return Colour; }

1607

1608protected:

1609 DisplayElement(StringRef Colour) : Colour(Colour) {}

1610 const StringRef Colour;

1611};

1612

1613

1614

1615class DisplayEdge : public DisplayElement {

1616public:

1617 DisplayEdge(std::string Value, DisplayNode &Node, StringRef Colour)

1619

1620 std::string getValue() const { return Value; }

1621

1622 const DisplayNode &getDestinationNode() const { return Node; }

1623

1624protected:

1625 std::string Value;

1626 const DisplayNode &Node;

1627};

1628

1629

1630class DisplayNode : public DisplayElement {

1631public:

1632

1633

1634 DisplayNode(std::string Content, StringRef Colour)

1635 : DisplayElement(Colour), Content(Content) {}

1636

1637

1638 using ChildIterator = std::unordered_set<DisplayNode *>::const_iterator;

1639 ChildIterator children_begin() const { return Children.cbegin(); }

1640 ChildIterator children_end() const { return Children.cend(); }

1641

1642

1643 using EdgeIterator = std::vector<DisplayEdge *>::const_iterator;

1644 EdgeIterator edges_begin() const { return EdgePtrs.cbegin(); }

1645 EdgeIterator edges_end() const { return EdgePtrs.cend(); }

1646

1647

1648 void createEdge(StringRef Value, DisplayNode &Node, StringRef Colour);

1649

1650

1651 std::string getContent() const { return Content; }

1652

1653

1654 const DisplayEdge &getEdge(const DisplayNode &To) const {

1655 assert(EdgeMap.find(&To) != EdgeMap.end() && "Expected to find edge.");

1656 return *EdgeMap.find(&To)->second;

1657 }

1658

1659

1660

1661 std::string getEdgeSourceLabel(const DisplayNode &Sink) const {

1662 return getEdge(Sink).getValue();

1663 }

1664

1665 void createEdgeMap();

1666

1667protected:

1668 const std::string Content;

1669

1670

1671

1672

1673 std::vector Edges;

1674

1675 std::vector<DisplayEdge *> EdgePtrs;

1676 std::unordered_set<DisplayNode *> Children;

1677 std::unordered_map<const DisplayNode *, const DisplayEdge *> EdgeMap;

1678

1679

1680 bool AllEdgesCreated = false;

1681};

1682

1683

1684class DotCfgDiffDisplayGraph {

1685public:

1686 DotCfgDiffDisplayGraph(std::string Name) : GraphName(Name) {}

1687

1688

1689 void generateDotFile(StringRef DotFile);

1690

1691

1692 using NodeIterator = std::vector<DisplayNode *>::const_iterator;

1693 NodeIterator nodes_begin() const {

1694 assert(NodeGenerationComplete && "Unexpected children iterator creation");

1695 return NodePtrs.cbegin();

1696 }

1697 NodeIterator nodes_end() const {

1698 assert(NodeGenerationComplete && "Unexpected children iterator creation");

1699 return NodePtrs.cend();

1700 }

1701

1702

1703

1704 void setEntryNode(unsigned N) {

1705

1706 assert(!NodeGenerationComplete && "Unexpected node creation");

1707 NodeGenerationComplete = true;

1708 for (auto &N : Nodes)

1709 NodePtrs.emplace_back(&N);

1710

1711 EntryNode = NodePtrs[N];

1712 }

1713

1714

1715 void createNode(std::string C, StringRef Colour) {

1716 assert(!NodeGenerationComplete && "Unexpected node creation");

1717 Nodes.emplace_back(C, Colour);

1718 }

1719

1720 DisplayNode &getNode(unsigned N) {

1721 assert(N < Nodes.size() && "Node is out of bounds");

1722 return Nodes[N];

1723 }

1724 unsigned size() const {

1725 assert(NodeGenerationComplete && "Unexpected children iterator creation");

1726 return Nodes.size();

1727 }

1728

1729

1730 std::string getGraphName() const { return GraphName; }

1731

1732

1733

1734 std::string getNodeLabel(const DisplayNode &Node) const {

1735 return Node.getContent();

1736 }

1737

1738

1739 std::string getNodeAttributes(const DisplayNode &Node) const {

1740 return attribute(Node.getColour());

1741 }

1742

1743

1744 std::string getEdgeColorAttr(const DisplayNode &From,

1745 const DisplayNode &To) const {

1746 return attribute(From.getEdge(To).getColour());

1747 }

1748

1749

1750 DisplayNode *getEntryNode() const {

1751 assert(NodeGenerationComplete && "Unexpected children iterator creation");

1752 return EntryNode;

1753 }

1754

1755protected:

1756

1757 std::string attribute(StringRef Colour) const {

1758 return "color=" + Colour.str();

1759 }

1760

1761 bool NodeGenerationComplete = false;

1762 const std::string GraphName;

1763 std::vector Nodes;

1764 std::vector<DisplayNode *> NodePtrs;

1765 DisplayNode *EntryNode = nullptr;

1766};

1767

1768void DisplayNode::createEdge(StringRef Value, DisplayNode &Node,

1769 StringRef Colour) {

1770 assert(!AllEdgesCreated && "Expected to be able to still create edges.");

1771 Edges.emplace_back(Value.str(), Node, Colour);

1773}

1774

1775void DisplayNode::createEdgeMap() {

1776

1777

1778 AllEdgesCreated = true;

1779 for (auto &E : Edges)

1780 EdgeMap.insert({&E.getDestinationNode(), &E});

1781}

1782

1783class DotCfgDiffNode;

1784class DotCfgDiff;

1785

1786

1787class DotCfgDiffNode {

1788public:

1789 DotCfgDiffNode() = delete;

1790

1791

1792

1793 DotCfgDiffNode(DotCfgDiff &G, unsigned N, const BlockDataT &BD,

1794 StringRef Colour)

1795 : Graph(G), N(N), Data{&BD, nullptr}, Colour(Colour) {}

1796 DotCfgDiffNode(const DotCfgDiffNode &DN)

1797 : Graph(DN.Graph), N(DN.N), Data{DN.Data[0], DN.Data[1]},

1798 Colour(DN.Colour), EdgesMap(DN.EdgesMap), Children(DN.Children),

1799 Edges(DN.Edges) {}

1800

1801 unsigned getIndex() const { return N; }

1802

1803

1804 StringRef getLabel() const {

1805 assert(Data[0] && "Expected Data[0] to be set.");

1806 return Data[0]->getLabel();

1807 }

1808

1809 StringRef getColour() const { return Colour; }

1810

1811

1812 void setCommon(const BlockDataT &Other) {

1813 assert(Data[1] && "Expected only one block datum");

1816 }

1817

1818 void addEdge(unsigned E, StringRef Value, StringRef Colour) {

1819

1821 "Unexpected edge count and color.");

1822 EdgesMap[E] = {Value.str(), Colour};

1823 }

1824

1826

1827

1828 StringRef getEdgeColour(const unsigned S) const {

1829 assert(EdgesMap.count(S) == 1 && "Expected to find edge.");

1830 return EdgesMap.at(S).second;

1831 }

1832

1833

1834 std::string getBodyContent() const;

1835

1836 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph, unsigned DisplayNode,

1837 std::map<const unsigned, unsigned> &NodeMap) const;

1838

1839protected:

1840 DotCfgDiff &Graph;

1841 const unsigned N;

1842 const BlockDataT *Data[2];

1843 StringRef Colour;

1844 std::map<const unsigned, std::pair<std::string, StringRef>> EdgesMap;

1845 std::vector Children;

1846 std::vector Edges;

1847};

1848

1849

1850class DotCfgDiff {

1851public:

1852

1853

1854

1855

1856 DotCfgDiff(StringRef Title, const FuncDataT &Before,

1857 const FuncDataT &After);

1858

1859 DotCfgDiff(const DotCfgDiff &) = delete;

1860 DotCfgDiff &operator=(const DotCfgDiff &) = delete;

1861

1862 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,

1863 StringRef EntryNodeName);

1864

1865

1866

1867

1868

1869 StringRef getEdgeSourceLabel(const unsigned &Source,

1870 const unsigned &Sink) const {

1871 std::string S =

1872 getNode(Source).getLabel().str() + " " + getNode(Sink).getLabel().str();

1873 assert(EdgeLabels.count(S) == 1 && "Expected to find edge label.");

1874 return EdgeLabels.find(S)->getValue();

1875 }

1876

1877

1878 unsigned size() const { return Nodes.size(); }

1879

1880 const DotCfgDiffNode &getNode(unsigned N) const {

1881 assert(N < Nodes.size() && "Unexpected index for node reference");

1882 return Nodes[N];

1883 }

1884

1885protected:

1886

1887 std::string colourize(std::string S, StringRef Colour) const;

1888

1889 void createNode(StringRef Label, const BlockDataT &BD, StringRef C) {

1890 unsigned Pos = Nodes.size();

1891 Nodes.emplace_back(*this, Pos, BD, C);

1892 NodePosition.insert({Label, Pos});

1893 }

1894

1895

1896

1897

1898 std::vector Nodes;

1899 StringMap NodePosition;

1900 const std::string GraphName;

1901

1902 StringMapstd::string EdgeLabels;

1903};

1904

1905std::string DotCfgDiffNode::getBodyContent() const {

1907 assert(Data[1] && "Expected Data[1] to be set.");

1908

1909 StringRef SR[2];

1910 for (unsigned I = 0; I < 2; ++I) {

1911 SR[I] = Data[I]->getBody();

1912

1914

1915 SR[I] = SR[I].drop_until([](char C) { return C == '\n'; }).drop_front();

1916 }

1917

1918 SmallString<80> OldLineFormat = formatv(

1919 "<FONT COLOR=\"{0}\">%l<BR align=\"left\"/>", BeforeColour);

1920 SmallString<80> NewLineFormat = formatv(

1921 "<FONT COLOR=\"{0}\">%l<BR align=\"left\"/>", AfterColour);

1922 SmallString<80> UnchangedLineFormat = formatv(

1923 "<FONT COLOR=\"{0}\">%l<BR align=\"left\"/>", CommonColour);

1924 std::string Diff = Data[0]->getLabel().str();

1925 Diff += ":\n<BR align=\"left\"/>" +

1926 doSystemDiff(makeHTMLReady(SR[0]), makeHTMLReady(SR[1]),

1927 OldLineFormat, NewLineFormat, UnchangedLineFormat);

1928

1929

1930

1931

1932 Regex R("<FONT COLOR=\"\\w+\">");

1933 while (true) {

1934 std::string Error;

1935 std::string S = R.sub("", Diff, &Error);

1936 if (Error != "")

1938 if (S == Diff)

1939 return Diff;

1940 Diff = S;

1941 }

1943 }

1944

1945

1946 assert(Data[1] && "Data[1] is set unexpectedly.");

1947 std::string Body = makeHTMLReady(Data[0]->getBody());

1948 const StringRef BS = Body;

1949 StringRef BS1 = BS;

1950

1951 if (BS.front() == '\n')

1953

1954 StringRef Label = BS1.take_until([](char C) { return C == ':'; });

1955

1956 BS1 = BS1.drop_until([](char C) { return C == '\n'; }).drop_front();

1957

1958 std::string S = "<FONT COLOR=\"" + Colour.str() + "\">" + Label.str() + ":";

1959

1960

1961 while (BS1.size()) {

1962 S.append("<BR align=\"left\"/>");

1963 StringRef Line = BS1.take_until([](char C) { return C == '\n'; });

1964 S.append(Line.str());

1966 }

1967 S.append("<BR align=\"left\"/>");

1968 return S;

1969}

1970

1971std::string DotCfgDiff::colourize(std::string S, StringRef Colour) const {

1972 if (S.length() == 0)

1973 return S;

1974 return "<FONT COLOR=\"" + Colour.str() + "\">" + S + "";

1975}

1976

1977DotCfgDiff::DotCfgDiff(StringRef Title, const FuncDataT &Before,

1978 const FuncDataT &After)

1979 : GraphName(Title.str()) {

1980 StringMap EdgesMap;

1981

1982

1983 for (auto &B : Before.getData()) {

1984 StringRef Label = B.getKey();

1985 const BlockDataT &BD = B.getValue();

1986 createNode(Label, BD, BeforeColour);

1987

1988

1989

1990 for (StringMapstd::string::const_iterator Sink = BD.getData().begin(),

1991 E = BD.getData().end();

1992 Sink != E; ++Sink) {

1993 std::string Key = (Label + " " + Sink->getKey().str()).str() + " " +

1994 BD.getData().getSuccessorLabel(Sink->getKey()).str();

1995 EdgesMap.insert({Key, BeforeColour});

1996 }

1997 }

1998

1999

2000 for (auto &A : After.getData()) {

2001 StringRef Label = A.getKey();

2002 const BlockDataT &BD = A.getValue();

2003 auto It = NodePosition.find(Label);

2004 if (It == NodePosition.end())

2005

2006 createNode(Label, BD, AfterColour);

2007 else

2008 Nodes[It->second].setCommon(BD);

2009

2010 for (StringMapstd::string::const_iterator Sink = BD.getData().begin(),

2011 E = BD.getData().end();

2012 Sink != E; ++Sink) {

2013 std::string Key = (Label + " " + Sink->getKey().str()).str() + " " +

2014 BD.getData().getSuccessorLabel(Sink->getKey()).str();

2015 auto [It, Inserted] = EdgesMap.try_emplace(Key, AfterColour);

2016 if (!Inserted)

2017 It->second = CommonColour;

2018 }

2019 }

2020

2021

2022 for (auto &E : EdgesMap) {

2023

2025 auto SP1 = S.rsplit(' ');

2026 auto &SourceSink = SP1.first;

2027 auto SP2 = SourceSink.split(' ');

2031

2032 assert(NodePosition.count(Source) == 1 && "Expected to find node.");

2033 DotCfgDiffNode &SourceNode = Nodes[NodePosition[Source]];

2034 assert(NodePosition.count(Sink) == 1 && "Expected to find node.");

2035 unsigned SinkNode = NodePosition[Sink];

2037

2038

2039 auto [It, Inserted] = EdgeLabels.try_emplace(SourceSink);

2040 if (Inserted)

2041 It->getValue() = colourize(Value.str(), Colour);

2042 else {

2044 std::string NV = colourize(V.str() + " " + Value.str(), Colour);

2046 It->getValue() = NV;

2047 }

2048 SourceNode.addEdge(SinkNode, Value, Colour);

2049 }

2050 for (auto &I : Nodes)

2051 I.finalize(*this);

2052}

2053

2054DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(StringRef Title,

2056 assert(NodePosition.count(EntryNodeName) == 1 &&

2057 "Expected to find entry block in map.");

2058 unsigned Entry = NodePosition[EntryNodeName];

2059 assert(Entry < Nodes.size() && "Expected to find entry node");

2060 DotCfgDiffDisplayGraph G(Title.str());

2061

2062 std::map<const unsigned, unsigned> NodeMap;

2063

2064 int EntryIndex = -1;

2065 unsigned Index = 0;

2066 for (auto &I : Nodes) {

2067 if (I.getIndex() == Entry)

2068 EntryIndex = Index;

2069 G.createNode(I.getBodyContent(), I.getColour());

2070 NodeMap.insert({I.getIndex(), Index++});

2071 }

2072 assert(EntryIndex >= 0 && "Expected entry node index to be set.");

2073 G.setEntryNode(EntryIndex);

2074

2075 for (auto &I : NodeMap) {

2076 unsigned SourceNode = I.first;

2077 unsigned DisplayNode = I.second;

2078 getNode(SourceNode).createDisplayEdges(G, DisplayNode, NodeMap);

2079 }

2080 return G;

2081}

2082

2083void DotCfgDiffNode::createDisplayEdges(

2084 DotCfgDiffDisplayGraph &DisplayGraph, unsigned DisplayNodeIndex,

2085 std::map<const unsigned, unsigned> &NodeMap) const {

2086

2087 DisplayNode &SourceDisplayNode = DisplayGraph.getNode(DisplayNodeIndex);

2088

2089 for (auto I : Edges) {

2090 unsigned SinkNodeIndex = I;

2091 StringRef Colour = getEdgeColour(SinkNodeIndex);

2092 const DotCfgDiffNode *SinkNode = &Graph.getNode(SinkNodeIndex);

2093

2094 StringRef Label = Graph.getEdgeSourceLabel(getIndex(), SinkNodeIndex);

2095 DisplayNode &SinkDisplayNode = DisplayGraph.getNode(SinkNode->getIndex());

2096 SourceDisplayNode.createEdge(Label, SinkDisplayNode, Colour);

2097 }

2098 SourceDisplayNode.createEdgeMap();

2099}

2100

2101void DotCfgDiffNode::finalize(DotCfgDiff &G) {

2102 for (auto E : EdgesMap) {

2104 Edges.emplace_back(E.first);

2105 }

2106}

2107

2108}

2109

2110namespace llvm {

2111

2112template <> struct GraphTraits<DotCfgDiffDisplayGraph *> {

2118

2120 return G->getEntryNode();

2121 }

2123 return N->children_begin();

2124 }

2127 return G->nodes_begin();

2128 }

2130 return G->nodes_end();

2131 }

2133 return N->edges_begin();

2134 }

2137 static unsigned size(const DotCfgDiffDisplayGraph *G) { return G->size(); }

2138};

2139

2140template <>

2144

2146 static std::string getGraphName(const DotCfgDiffDisplayGraph *DiffData) {

2147 return DiffData->getGraphName();

2148 }

2149 static std::string

2151 return "\tsize=\"190, 190\";\n";

2152 }

2154 const DotCfgDiffDisplayGraph *DiffData) {

2155 return DiffData->getNodeLabel(*Node);

2156 }

2158 const DotCfgDiffDisplayGraph *DiffData) {

2159 return DiffData->getNodeAttributes(*Node);

2160 }

2162 DisplayNode::ChildIterator &To) {

2163 return From->getEdgeSourceLabel(**To);

2164 }

2166 DisplayNode::ChildIterator &To,

2167 const DotCfgDiffDisplayGraph *DiffData) {

2168 return DiffData->getEdgeColorAttr(*From, **To);

2169 }

2170};

2171

2172}

2173

2174namespace {

2175

2176void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {

2177 std::error_code EC;

2178 raw_fd_ostream OutStream(DotFile, EC);

2179 if (EC) {

2180 errs() << "Error: " << EC.message() << "\n";

2181 return;

2182 }

2184 OutStream.flush();

2185 OutStream.close();

2186}

2187

2188}

2189

2190namespace llvm {

2191

2193

2194 const Instruction *Term = B.getTerminator();

2196 if (Br->isUnconditional())

2198 else {

2199 addSuccessorLabel(Br->getSuccessor(0)->getName().str(), "true");

2200 addSuccessorLabel(Br->getSuccessor(1)->getName().str(), "false");

2201 }

2203 addSuccessorLabel(Sw->case_default()->getCaseSuccessor()->getName().str(),

2204 "default");

2205 for (auto &C : Sw->cases()) {

2206 assert(C.getCaseValue() && "Expected to find case value.");

2209 }

2210 } else

2213}

2214

2219

2222

2227 assert(HTML && "Expected outstream to be set");

2230

2231 if (InModule) {

2232 Extender = formatv("{0}_{1}", N, Minor);

2234 } else {

2235 Extender = formatv("{0}", N);

2237 }

2238

2241 std::string DotFile = Twine(SV).str();

2242

2245

2246 Text = formatv("{0}.{1}{2}{3}{4}", Number, Prefix, makeHTMLReady(PassID),

2247 Divider, Name);

2248

2249 DotCfgDiff Diff(Text, Before, After);

2251

2252 if (EntryBlockName == "")

2254 assert(EntryBlockName != "" && "Expected to find entry block");

2255

2256 DotCfgDiffDisplayGraph DG = Diff.createDisplayGraph(Text, EntryBlockName);

2257 DG.generateDotFile(DotFile);

2258

2259 *HTML << genHTML(Text, DotFile, PDFFileName);

2261 if (EC)

2262 errs() << "Error: " << EC.message() << "\n";

2263}

2264

2268

2270 if (!DotExe)

2271 return "Unable to find dot executable.";

2272

2275 if (Result < 0)

2276 return "Error executing system dot.";

2277

2278

2280 " <a href=\"{0}\" target=\"_blank\">{1}
\n", PDFFileName, Text);

2281 return S.c_str();

2282}

2283

2285 assert(HTML && "Expected outstream to be set");

2286 *HTML << "<button type=\"button\" class=\"collapsible\">0. "

2287 << "Initial IR (by function)\n"

2288 << "<div class=\"content\">\n"

2289 << "

\n";

2290

2293

2294

2296 .compare(getModuleForComparison(IR),

2297 [&](bool InModule, unsigned Minor,

2301 Minor, Before, After);

2302 });

2303 *HTML << "

\n"

2304 << "
\n";

2305 ++N;

2306}

2307

2312

2314 assert(HTML && "Expected outstream to be set");

2316 formatv(" {0}. Pass {1} on {2} omitted because no change
\n",

2317 N, makeHTMLReady(PassID), Name);

2318 *HTML << Banner;

2319 ++N;

2320}

2321

2325 assert(HTML && "Expected outstream to be set");

2327 .compare(getModuleForComparison(IR),

2328 [&](bool InModule, unsigned Minor,

2332 Minor, Before, After);

2333 });

2334 *HTML << "

\n";

2335 ++N;

2336}

2337

2339 assert(HTML && "Expected outstream to be set");

2341 formatv(" {0}. {1} invalidated
\n", N, makeHTMLReady(PassID));

2342 *HTML << Banner;

2343 ++N;

2344}

2345

2347 assert(HTML && "Expected outstream to be set");

2349 formatv(" {0}. Pass {1} on {2} filtered out
\n", N,

2350 makeHTMLReady(PassID), Name);

2351 *HTML << Banner;

2352 ++N;

2353}

2354

2356 assert(HTML && "Expected outstream to be set");

2358 makeHTMLReady(PassID), Name);

2359 *HTML << Banner;

2360 ++N;

2361}

2362

2364 std::error_code EC;

2365 HTML = std::make_unique<raw_fd_ostream>(DotCfgDir + "/passes.html", EC);

2366 if (EC) {

2367 HTML = nullptr;

2368 return false;

2369 }

2370

2371 *HTML << ""

2372 << ""

2373 << ""

2374 << ""

2393 << "passes.html"

2394 << "\n"

2395 << "";

2396 return true;

2397}

2398

2401 return;

2403 << ""

2418 << ""

2419 << "\n";

2420 HTML->flush();

2421 HTML->close();

2422}

2423

2431 assert(!OutputDir.empty() && "expected output dir to be non-empty");

2435 return;

2436 }

2437 dbgs() << "Unable to open output stream for -cfg-dot-changed\n";

2438 }

2439}

2440

2442 LLVMContext &Context, bool DebugLogging, bool VerifyEach,

2444 : PrintPass(DebugLogging, PrintPassOpts), OptNone(DebugLogging),

2445 OptPassGate(Context),

2453 VerifyEach(VerifyEach) {}

2454

2456 nullptr;

2457

2460 std::error_code EC;

2462 if (EC)

2465 } else {

2467 }

2468}

2469

2470void PrintCrashIRInstrumentation::SignalHandler(void *) {

2471

2472

2473 if (!CrashReporter)

2474 return;

2475

2477 "Did not expect to get here without option set.");

2479}

2480

2482 if (!CrashReporter)

2483 return;

2484

2486 "Did not expect to get here without option set.");

2487 CrashReporter = nullptr;

2488}

2489

2493 return;

2494

2496 CrashReporter = this;

2497

2498 PIC.registerBeforeNonSkippedPassCallback(

2502 OS << formatv("; *** Dump of {0}IR Before Last Pass {1}",

2504 if (isInteresting(IR, PassID, PIC.getPassNameForClassName(PassID))) {

2505 OS << " Filtered Out ***\n";

2506 return;

2507 }

2508 OS << " Started ***\n";

2509 unwrapAndPrint(OS, IR);

2510 });

2511}

2512

2515 PrintIR.registerCallbacks(PIC);

2516 PrintPass.registerCallbacks(PIC);

2517 TimePasses.registerCallbacks(PIC);

2518 OptNone.registerCallbacks(PIC);

2519 OptPassGate.registerCallbacks(PIC);

2520 PrintChangedIR.registerCallbacks(PIC);

2521 PseudoProbeVerification.registerCallbacks(PIC);

2522 if (VerifyEach)

2523 Verify.registerCallbacks(PIC, MAM);

2524 PrintChangedDiff.registerCallbacks(PIC);

2525 WebsiteChangeReporter.registerCallbacks(PIC);

2526 ChangeTester.registerCallbacks(PIC);

2527 PrintCrashIR.registerCallbacks(PIC);

2528 DroppedStatsIR.registerCallbacks(PIC);

2529 if (MAM)

2530 PreservedCFGChecker.registerCallbacks(PIC, *MAM);

2531

2532

2533

2534

2535

2536

2537

2538 TimeProfilingPasses.registerCallbacks(PIC);

2539}

2540

2543

2550

2551}