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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

48#include <unordered_map>

49#include <unordered_set>

50#include

51#include

52

53using namespace llvm;

54

57#ifdef EXPENSIVE_CHECKS

59#else

61#endif

62);

63

64

65

66

69 cl::desc("Print before passes that change them"),

71

72

73

76 cl::desc("system dot used by change reporters"));

77

78

79

80

85

86

87

92

93

94

99

100

101

103 "dot-cfg-dir",

104 cl::desc("Generate dot files into specified directory for changed IRs"),

106

107

109 "print-on-crash-path",

110 cl::desc("Print the last form of the IR before crash to a file"),

112

114 "print-on-crash",

115 cl::desc("Print the last form of the IR before crash (use -print-on-crash-path to dump to a file)"),

117

119 "opt-bisect-print-ir-path",

120 cl::desc("Print IR to path when opt-bisect-limit is reached"), cl::Hidden);

121

124 cl::desc("Print pass names and their ordinals"));

125

128 cl::desc("Print IR before the pass with this number as "

129 "reported by print-pass-numbers"));

130

133 cl::desc("Print IR after the pass with this number as "

134 "reported by print-pass-numbers"));

135

137 "ir-dump-directory",

138 cl::desc("If specified, IR printed using the "

139 "-print-[before|after]{-all} options will be dumped into "

140 "files in this directory rather than written to stderr"),

142

145 cl::desc("Dump dropped debug variables stats"),

147

148template static const IRUnitT *unwrapIR(Any IR) {

149 const IRUnitT **IRPtr = llvm::any_cast<const IRUnitT *>(&IR);

150 return IRPtr ? *IRPtr : nullptr;

151}

152

153namespace {

154

155

156

157

158

159

160

161

164 cl::desc("exe called with module IR after each pass that "

165 "changes it"));

166

167

168

169const Module *unwrapModule(Any IR, bool Force = false) {

170 if (const auto *M = unwrapIR(IR))

171 return M;

172

173 if (const auto *F = unwrapIR(IR)) {

175 return nullptr;

176

177 return F->getParent();

178 }

179

180 if (const auto *C = unwrapIRLazyCallGraph::SCC(IR)) {

184 return F.getParent();

185 }

186 }

187 assert(!Force && "Expected a module");

188 return nullptr;

189 }

190

191 if (const auto *L = unwrapIR(IR)) {

192 const Function *F = L->getHeader()->getParent();

194 return nullptr;

195 return F->getParent();

196 }

197

198 if (const auto *MF = unwrapIR(IR)) {

200 return nullptr;

201 return MF->getFunction().getParent();

202 }

203

205}

206

209 return;

211}

215 M->print(OS, nullptr);

217 for (const auto &F : M->functions()) {

218 printIR(OS, &F);

219 }

220 }

221}

222

227 F.print(OS);

228 }

229 }

230}

231

233 const Function *F = L->getHeader()->getParent();

235 return;

237}

238

241 return;

243}

244

245std::string getIRName(Any IR) {

246 if (unwrapIR(IR))

247 return "[module]";

248

249 if (const auto *F = unwrapIR(IR))

250 return F->getName().str();

251

252 if (const auto *C = unwrapIRLazyCallGraph::SCC(IR))

253 return C->getName();

254

255 if (const auto *L = unwrapIR(IR))

256 return "loop %" + L->getName().str() + " in function " +

257 L->getHeader()->getParent()->getName().str();

258

259 if (const auto *MF = unwrapIR(IR))

263}

264

265bool moduleContainsFilterPrintFunc(const Module &M) {

266 return any_of(M.functions(),

268 return isFunctionInPrintList(F.getName());

269 }) ||

271}

272

277 }) ||

279}

280

281bool shouldPrintIR(Any IR) {

282 if (const auto *M = unwrapIR(IR))

283 return moduleContainsFilterPrintFunc(*M);

284

285 if (const auto *F = unwrapIR(IR))

287

288 if (const auto *C = unwrapIRLazyCallGraph::SCC(IR))

289 return sccContainsFilterPrintFunc(*C);

290

291 if (const auto *L = unwrapIR(IR))

293

294 if (const auto *MF = unwrapIR(IR))

297}

298

299

300

302 if (!shouldPrintIR(IR))

303 return;

304

306 auto *M = unwrapModule(IR);

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

308 printIR(OS, M);

309 return;

310 }

311

312 if (const auto *M = unwrapIR(IR)) {

313 printIR(OS, M);

314 return;

315 }

316

317 if (const auto *F = unwrapIR(IR)) {

318 printIR(OS, F);

319 return;

320 }

321

322 if (const auto *C = unwrapIRLazyCallGraph::SCC(IR)) {

323 printIR(OS, C);

324 return;

325 }

326

327 if (const auto *L = unwrapIR(IR)) {

328 printIR(OS, L);

329 return;

330 }

331

332 if (const auto *MF = unwrapIR(IR)) {

333 printIR(OS, MF);

334 return;

335 }

337}

338

339

340bool isIgnored(StringRef PassID) {

342 {"PassManager", "PassAdaptor", "AnalysisManagerProxy",

343 "DevirtSCCRepeatedPass", "ModuleInlinerWrapperPass",

344 "VerifierPass", "PrintModulePass", "PrintMIRPass",

345 "PrintMIRPreparePass"});

346}

347

348std::string makeHTMLReady(StringRef SR) {

349 std::string S;

350 while (true) {

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

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

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

356 return S;

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

359 }

361}

362

363

364const Module *getModuleForComparison(Any IR) {

365 if (const auto *M = unwrapIR(IR))

366 return M;

367 if (const auto *C = unwrapIRLazyCallGraph::SCC(IR))

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

369 return nullptr;

370}

371

372bool isInterestingFunction(const Function &F) {

374}

375

376

377

380 return false;

381 if (const auto *F = unwrapIR(IR))

382 return isInterestingFunction(*F);

383 return true;

384}

385

386}

387

389 assert(BeforeStack.empty() && "Problem with Change Printer stack.");

390}

391

392template

395

396 if (InitialIR) {

397 InitialIR = false;

398 if (VerboseMode)

399 handleInitialIR(IR);

400 }

401

402

403

404

405 BeforeStack.emplace_back();

406

408 return;

409

410

411 T &Data = BeforeStack.back();

412 generateIRRepresentation(IR, PassID, Data);

413}

414

415template

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

419

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

421

422 if (isIgnored(PassID)) {

423 if (VerboseMode)

424 handleIgnored(PassID, Name);

426 if (VerboseMode)

427 handleFiltered(PassID, Name);

428 } else {

429

430 T &Before = BeforeStack.back();

431

433 generateIRRepresentation(IR, PassID, After);

434

435

437 if (VerboseMode)

438 omitAfter(PassID, Name);

439 } else

441 }

442 BeforeStack.pop_back();

443}

444

445template

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

448

449

450

451

452

453 if (VerboseMode)

454 handleInvalidated(PassID);

455 BeforeStack.pop_back();

456}

457

458template

463 });

464

468 });

471 handleInvalidatedPass(P);

472 });

473}

474

475template

478

480

481

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

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

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

485 M->print(Out, nullptr);

486}

487

488template

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

491 PassID, Name);

492}

493

494template

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

497}

498

499template

501 std::string &Name) {

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

504 Out << Banner;

505}

506

507template

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

510}

511

513

518}

519

521 std::string &Output) {

523 unwrapAndPrint(OS, IR);

524 OS.str();

525}

526

528 const std::string &Before,

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

530

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

534

535

536

537 if (After.empty()) {

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

539 return;

540 }

541

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

543}

544

546

548 if (TestChanged != "")

550}

551

553

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

559 return;

560 }

562 if (!Exe) {

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

564 return;

565 }

566

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

569 if (Result < 0) {

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

571 return;

572 }

573

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

576}

577

579

580

581 std::string S;

584}

585

591 const std::string &Before,

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

594}

595

596template

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

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

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

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

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

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

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

606

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

608

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

610

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

612 }

613 };

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

615

616 for (const T *NBI : Q)

617 HandlePair(nullptr, NBI);

618 Q.clear();

619 };

620

621

622

623

624

625

626

627

628

629

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

631 while (AI != AE) {

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

633

634

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

636 ++AI;

637 continue;

638 }

639

640

641

642

643

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

645 HandlePotentiallyRemovedData(*BI);

646 ++BI;

647 }

648

649 HandleNewData(NewDataQueue);

650

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

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

653 HandlePair(&BData, &AData);

654 if (BI != BE)

655 ++BI;

656 ++AI;

657 }

658

659

660 while (BI != BE) {

661 HandlePotentiallyRemovedData(*BI);

662 ++BI;

663 }

664

665 HandleNewData(NewDataQueue);

666}

667

668template

670 bool CompareModule,

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

673 CompareFunc) {

674 if (!CompareModule) {

675

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

677 "Expected only one function.");

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

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

680 return;

681 }

682

683 unsigned Minor = 0;

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

688 if (B)

689 B = &Missing;

690 else if (A)

691 A = &Missing;

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

693 });

694}

695

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

698

700 generateFunctionData(Data, F);

701 return;

702 }

703

704 if (const auto *F = unwrapIR(IR)) {

705 generateFunctionData(Data, *F);

706 return;

707 }

708

709 if (const auto *L = unwrapIR(IR)) {

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

711 generateFunctionData(Data, *F);

712 return;

713 }

714

715 if (const auto *MF = unwrapIR(IR)) {

716 generateFunctionData(Data, *MF);

717 return;

718 }

719

721}

722

725}

726

729}

730

731template

732template

736 int I = 0;

737 for (const auto &B : F) {

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

739 if (BBName.empty()) {

741 ++I;

742 }

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

745 }

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

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

748 return true;

749 }

750 return false;

751}

752

755 "PassRunDescriptorStack is not empty at exit");

756}

757

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

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

764 unsigned MaxHashWidth = sizeof(uint64_t) * 2;

766 if (unwrapIR(IR)) {

767 ResultStream << "-module";

768 } else if (const auto *F = unwrapIR(IR)) {

769 ResultStream << "-function-";

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

772 MaxHashWidth);

773 } else if (const auto *C = unwrapIRLazyCallGraph::SCC(IR)) {

774 ResultStream << "-scc-";

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

777 } else if (const auto *L = unwrapIR(IR)) {

778 ResultStream << "-loop-";

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

781 } else if (const auto *MF = unwrapIR(IR)) {

782 ResultStream << "-machine-function-";

785 MaxHashWidth);

786 } else {

788 }

789 return Result;

790}

791

792std::string PrintIRInstrumentation::fetchDumpFilename(StringRef PassName,

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

798 ResultPath += RootDirectory;

801 FilenameStream << CurrentPassNumber;

802 FilenameStream << "-";

804 FilenameStream << "-";

807 return std::string(ResultPath);

808}

809

814};

815

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

818 "-invalidated.ll"};

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

820}

821

822void PrintIRInstrumentation::pushPassRunDescriptor(

823 StringRef PassID, Any IR, std::string &DumpIRFilename) {

824 const Module *M = unwrapModule(IR);

826 PassRunDescriptor(M, DumpIRFilename, getIRName(IR), PassID));

827}

828

829PrintIRInstrumentation::PassRunDescriptor

830PrintIRInstrumentation::popPassRunDescriptor(StringRef PassID) {

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

832 PassRunDescriptor Descriptor = PassRunDescriptorStack.pop_back_val();

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

834 return Descriptor;

835}

836

837

839 std::error_code EC;

841 if (!ParentPath.empty()) {

843 if (EC)

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

846 }

847 int Result = 0;

850 if (EC)

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

853 return Result;

854}

855

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

857 if (isIgnored(PassID))

858 return;

859

860 std::string DumpIRFilename;

862 (shouldPrintBeforePass(PassID) || shouldPrintAfterPass(PassID) ||

863 shouldPrintBeforeCurrentPassNumber() ||

864 shouldPrintAfterCurrentPassNumber()))

865 DumpIRFilename = fetchDumpFilename(PassID, IR);

866

867

868

869

870

871 if (shouldPrintAfterPass(PassID))

872 pushPassRunDescriptor(PassID, IR, DumpIRFilename);

873

874 if (!shouldPrintIR(IR))

875 return;

876

877 ++CurrentPassNumber;

878

879 if (shouldPrintPassNumbers())

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

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

882

883 if (shouldPrintAfterCurrentPassNumber())

884 pushPassRunDescriptor(PassID, IR, DumpIRFilename);

885

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

887 return;

888

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

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

891 if (shouldPrintBeforeSomePassNumber())

892 Stream << CurrentPassNumber << "-";

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

894 unwrapAndPrint(Stream, IR);

895 };

896

897 if (!DumpIRFilename.empty()) {

898 DumpIRFilename += getFileSuffix(IRDumpFileSuffixType::Before);

901 WriteIRToStream(DumpIRFileStream);

902 } else {

903 WriteIRToStream(dbgs());

904 }

905}

906

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

908 if (isIgnored(PassID))

909 return;

910

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

912 return;

913

914 auto [M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);

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

916

917 if (!shouldPrintIR(IR) ||

918 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))

919 return;

920

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

923 if (shouldPrintAfterSomePassNumber())

924 Stream << CurrentPassNumber << "-";

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

926 unwrapAndPrint(Stream, IR);

927 };

928

930 assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "

931 "should be set in printBeforePass");

932 const std::string DumpIRFilenameWithSuffix =

933 DumpIRFilename + getFileSuffix(IRDumpFileSuffixType::After).str();

936 true};

937 WriteIRToStream(DumpIRFileStream, IRName);

938 } else {

939 WriteIRToStream(dbgs(), IRName);

940 }

941}

942

943void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) {

944 if (isIgnored(PassID))

945 return;

946

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

948 return;

949

950 auto [M, DumpIRFilename, IRName, StoredPassID] = popPassRunDescriptor(PassID);

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

952

953

954 if (!M ||

955 (!shouldPrintAfterPass(PassID) && !shouldPrintAfterCurrentPassNumber()))

956 return;

957

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

962 IRName);

963 Stream << Banner << "\n";

964 printIR(Stream, M);

965 };

966

968 assert(!DumpIRFilename.empty() && "DumpIRFilename must not be empty and "

969 "should be set in printBeforePass");

970 const std::string DumpIRFilenameWithSuffix =

971 DumpIRFilename + getFileSuffix(IRDumpFileSuffixType::Invalidated).str();

974 true};

975 WriteIRToStream(DumpIRFileStream, M, IRName);

976 } else {

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

978 }

979}

980

981bool PrintIRInstrumentation::shouldPrintBeforePass(StringRef PassID) {

983 return true;

984

987}

988

989bool PrintIRInstrumentation::shouldPrintAfterPass(StringRef PassID) {

991 return true;

992

995}

996

997bool PrintIRInstrumentation::shouldPrintBeforeCurrentPassNumber() {

998 return shouldPrintBeforeSomePassNumber() &&

1000}

1001

1002bool PrintIRInstrumentation::shouldPrintAfterCurrentPassNumber() {

1003 return shouldPrintAfterSomePassNumber() &&

1005}

1006

1007bool PrintIRInstrumentation::shouldPrintPassNumbers() {

1009}

1010

1011bool PrintIRInstrumentation::shouldPrintBeforeSomePassNumber() {

1013}

1014

1015bool PrintIRInstrumentation::shouldPrintAfterSomePassNumber() {

1017}

1018

1021 this->PIC = &PIC;

1022

1023

1024

1025

1026 if (shouldPrintPassNumbers() || shouldPrintBeforeSomePassNumber() ||

1031

1035 this->printAfterPass(P, IR);

1036 });

1039 this->printAfterPassInvalidated(P);

1040 });

1041 }

1042}

1043

1048}

1049

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

1051 bool ShouldRun = true;

1052 if (const auto *F = unwrapIR(IR))

1053 ShouldRun = F->hasOptNone();

1054 else if (const auto *L = unwrapIR(IR))

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

1056 else if (const auto *MF = unwrapIR(IR))

1058

1059 if (!ShouldRun && DebugLogging) {

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

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

1062 }

1063 return ShouldRun;

1064}

1065

1068 return true;

1069

1070 bool ShouldRun =

1073

1074

1075 this->HasWrittenIR = true;

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

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

1078 std::error_code EC;

1080 if (EC)

1082 M->print(OS, nullptr);

1083 }

1084 return ShouldRun;

1085}

1086

1091 return;

1092

1095 });

1096}

1097

1098raw_ostream &PrintPassInstrumentation::print() {

1100 assert(Indent >= 0);

1102 }

1103 return dbgs();

1104}

1105

1108 if (!Enabled)

1109 return;

1110

1111 std::vector SpecialPasses;

1113 SpecialPasses.emplace_back("PassManager");

1114 SpecialPasses.emplace_back("PassAdaptor");

1115 }

1116

1120 "Unexpectedly skipping special pass");

1121

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

1123 });

1127 return;

1128

1129 auto &OS = print();

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

1131 if (const auto *F = unwrapIR(IR)) {

1132 unsigned Count = F->getInstructionCount();

1133 OS << " (" << Count << " instruction";

1134 if (Count != 1)

1135 OS << 's';

1136 OS << ')';

1137 } else if (const auto *C = unwrapIRLazyCallGraph::SCC(IR)) {

1138 int Count = C->size();

1139 OS << " (" << Count << " node";

1140 if (Count != 1)

1141 OS << 's';

1142 OS << ')';

1143 }

1144 OS << "\n";

1145 Indent += 2;

1146 });

1151 return;

1152

1153 Indent -= 2;

1154 });

1158 return;

1159

1160 Indent -= 2;

1161 });

1162

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

1166 << "\n";

1167 Indent += 2;

1168 });

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

1173 << "\n";

1174 });

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

1177 });

1178 }

1179}

1180

1182 bool TrackBBLifetime) {

1183 if (TrackBBLifetime)

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

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

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

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

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

1192 }

1193 }

1194}

1195

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

1199 return;

1200 }

1201

1203 out << "unnamed_removed<" << BB << ">";

1204 return;

1205 }

1206

1208 out << "entry"

1209 << "<" << BB << ">";

1210 return;

1211 }

1212

1213 unsigned FuncOrderBlockNum = 0;

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

1215 if (&FuncBB == BB)

1216 break;

1217 FuncOrderBlockNum++;

1218 }

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

1220}

1221

1226 if (Before.isPoisoned()) {

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

1228 return;

1229 }

1230

1231

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

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

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

1235

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

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

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

1239 out << "Non-leaf block ";

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

1242 }

1243 }

1244

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

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

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

1248 out << "Non-leaf block ";

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

1251 continue;

1252 }

1253

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

1255 continue;

1256

1257 out << "Different successors of block ";

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

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

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

1263 if (SuccB.second != 1)

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

1265 else

1266 out << ", ";

1267 }

1268 out << "\n";

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

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

1272 if (SuccA.second != 1)

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

1274 else

1275 out << ", ";

1276 }

1277 out << "\n";

1278 }

1279}

1280

1281

1282

1283

1284

1285

1286

1287

1288

1289

1293

1295

1296public:

1297

1299

1300

1302 return Result(&F, true);

1303 }

1304};

1305

1307

1311

1314 };

1315

1317

1320 }

1321};

1322

1324

1328

1331 };

1332

1334

1337 }

1338};

1339

1341

1348}

1349

1352

1353 if (const auto *MaybeF = unwrapIR(IR)) {

1355 } else if (const auto *MaybeM = unwrapIR(IR)) {

1358 }

1359 return Functions;

1360}

1361

1365 return;

1366

1367 bool Registered = false;

1370#if LLVM_ENABLE_ABI_BREAKING_CHECKS

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

1372#endif

1373 (void)this;

1374

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

1377 .getManager();

1378 if (!Registered) {

1382 Registered = true;

1383 }

1384

1386

1389 }

1390

1391 if (const auto *MPtr = unwrapIR(IR)) {

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

1394 }

1395 });

1396

1399#if LLVM_ENABLE_ABI_BREAKING_CHECKS

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

1401 "Before and After callbacks must correspond");

1402#endif

1403 (void)this;

1404 });

1405

1408#if LLVM_ENABLE_ABI_BREAKING_CHECKS

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

1410 "Before and After callbacks must correspond");

1411#endif

1412 (void)this;

1413

1414

1415

1416

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

1419 .getManager();

1420

1422 if (auto *HashBefore =

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

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

1428 }

1429 }

1430

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

1433 if (GraphAfter == GraphBefore)

1434 return;

1435

1437 << "Error: " << Pass

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

1439 "function @"

1440 << FuncName << ":\n";

1443 };

1444

1445 if (auto *GraphBefore =

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

1448 CFG(F, false));

1449 }

1450 if (const auto *MPtr = unwrapIR(IR)) {

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

1452 if (auto *HashBefore =

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

1457 }

1458 }

1459 }

1460 });

1461}

1462

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

1468 return;

1469 const auto *F = unwrapIR(IR);

1470 if (F) {

1471 if (const auto *L = unwrapIR(IR))

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

1473 }

1474

1475 if (F) {

1476 if (DebugLogging)

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

1478

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

1482 P));

1483 } else {

1484 const auto *M = unwrapIR(IR);

1485 if (!M) {

1486 if (const auto *C = unwrapIRLazyCallGraph::SCC(IR))

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

1488 }

1489

1490 if (M) {

1491 if (DebugLogging)

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

1493

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

1497 P));

1498 }

1499

1500 if (auto *MF = unwrapIR(IR)) {

1501 if (DebugLogging)

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

1503 std::string Banner =

1504 formatv("Broken machine function found after pass "

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

1506 P);

1507 if (MAM) {

1509 auto &MFAM =

1511 .getManager();

1514 } else {

1516 }

1517 }

1518 }

1519 });

1520}

1521

1523

1528}

1529

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

1536 Out << Banner;

1538 .compare(getModuleForComparison(IR),

1539 [&](bool InModule, unsigned Minor,

1542 handleFunctionCompare(Name, "", PassID, " on ", InModule,

1544 });

1545 Out << "\n";

1546}

1547

1552

1553 if (InModule)

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

1555

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

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

1561 const std::string Removed =

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

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

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

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

1566 });

1567}

1568

1575}

1576

1578

1582 return;

1587 this->runAfterPass();

1588 },

1589 true);

1592 true);

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

1597}

1598

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

1601}

1602

1604

1605namespace {

1606

1607class DisplayNode;

1608class DotCfgDiffDisplayGraph;

1609

1610

1611class DisplayElement {

1612public:

1613

1614 StringRef getColour() const { return Colour; }

1615

1616protected:

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

1619};

1620

1621

1622

1623class DisplayEdge : public DisplayElement {

1624public:

1627

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

1629

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

1631

1632protected:

1633 std::string Value;

1634 const DisplayNode &Node;

1635};

1636

1637

1638class DisplayNode : public DisplayElement {

1639public:

1640

1641

1644

1645

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

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

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

1649

1650

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

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

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

1654

1655

1657

1658

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

1660

1661

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

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

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

1665 }

1666

1667

1668

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

1670 return getEdge(Sink).getValue();

1671 }

1672

1673 void createEdgeMap();

1674

1675protected:

1676 const std::string Content;

1677

1678

1679

1680

1681 std::vector Edges;

1682

1683 std::vector<DisplayEdge *> EdgePtrs;

1684 std::unordered_set<DisplayNode *> Children;

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

1686

1687

1688 bool AllEdgesCreated = false;

1689};

1690

1691

1692class DotCfgDiffDisplayGraph {

1693public:

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

1695

1696

1697 void generateDotFile(StringRef DotFile);

1698

1699

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

1701 NodeIterator nodes_begin() const {

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

1703 return NodePtrs.cbegin();

1704 }

1705 NodeIterator nodes_end() const {

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

1707 return NodePtrs.cend();

1708 }

1709

1710

1711

1712 void setEntryNode(unsigned N) {

1713

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

1715 NodeGenerationComplete = true;

1716 for (auto &N : Nodes)

1717 NodePtrs.emplace_back(&N);

1718

1719 EntryNode = NodePtrs[N];

1720 }

1721

1722

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

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

1725 Nodes.emplace_back(C, Colour);

1726 }

1727

1728 DisplayNode &getNode(unsigned N) {

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

1730 return Nodes[N];

1731 }

1732 unsigned size() const {

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

1734 return Nodes.size();

1735 }

1736

1737

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

1739

1740

1741

1743 return Node.getContent();

1744 }

1745

1746

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

1748 return attribute(Node.getColour());

1749 }

1750

1751

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

1753 const DisplayNode &To) const {

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

1755 }

1756

1757

1758 DisplayNode *getEntryNode() const {

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

1760 return EntryNode;

1761 }

1762

1763protected:

1764

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

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

1767 }

1768

1769 bool NodeGenerationComplete = false;

1770 const std::string GraphName;

1771 std::vector Nodes;

1772 std::vector<DisplayNode *> NodePtrs;

1773 DisplayNode *EntryNode = nullptr;

1774};

1775

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

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

1781}

1782

1783void DisplayNode::createEdgeMap() {

1784

1785

1786 AllEdgesCreated = true;

1787 for (auto &E : Edges)

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

1789}

1790

1791class DotCfgDiffNode;

1792class DotCfgDiff;

1793

1794

1795class DotCfgDiffNode {

1796public:

1797 DotCfgDiffNode() = delete;

1798

1799

1800

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

1804 DotCfgDiffNode(const DotCfgDiffNode &DN)

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

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

1807 Edges(DN.Edges) {}

1808

1809 unsigned getIndex() const { return N; }

1810

1811

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

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

1815 }

1816

1817 StringRef getColour() const { return Colour; }

1818

1819

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

1822 Data[1] = &Other;

1824 }

1825

1827

1829 "Unexpected edge count and color.");

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

1831 }

1832

1834

1835

1836 StringRef getEdgeColour(const unsigned S) const {

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

1838 return EdgesMap.at(S).second;

1839 }

1840

1841

1842 std::string getBodyContent() const;

1843

1844 void createDisplayEdges(DotCfgDiffDisplayGraph &Graph, unsigned DisplayNode,

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

1846

1847protected:

1848 DotCfgDiff &Graph;

1849 const unsigned N;

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

1853 std::vector Children;

1854 std::vector Edges;

1855};

1856

1857

1858class DotCfgDiff {

1859public:

1860

1861

1862

1863

1866

1867 DotCfgDiff(const DotCfgDiff &) = delete;

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

1869

1870 DotCfgDiffDisplayGraph createDisplayGraph(StringRef Title,

1872

1873

1874

1875

1876

1877 StringRef getEdgeSourceLabel(const unsigned &Source,

1878 const unsigned &Sink) const {

1879 std::string S =

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

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

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

1883 }

1884

1885

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

1887

1888 const DotCfgDiffNode &getNode(unsigned N) const {

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

1890 return Nodes[N];

1891 }

1892

1893protected:

1894

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

1896

1898 unsigned Pos = Nodes.size();

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

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

1901 }

1902

1903

1904

1905

1906 std::vector Nodes;

1908 const std::string GraphName;

1909

1911};

1912

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

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

1916

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

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

1920

1922

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

1924 }

1925

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

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

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

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

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

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

1935 OldLineFormat, NewLineFormat, UnchangedLineFormat);

1936

1937

1938

1939

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

1941 while (true) {

1942 std::string Error;

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

1944 if (Error != "")

1946 if (S == Diff)

1947 return Diff;

1948 Diff = S;

1949 }

1951 }

1952

1953

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

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

1958

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

1961

1963

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

1965

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

1967

1968

1969 while (BS1.size()) {

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

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

1974 }

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

1976 return S;

1977}

1978

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

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

1981 return S;

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

1983}

1984

1987 : GraphName(Title.str()) {

1989

1990

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

1995

1996

1997

2000 Sink != E; ++Sink) {

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

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

2004 }

2005 }

2006

2007

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

2011 unsigned C = NodePosition.count(Label);

2012 if (C == 0)

2013

2015 else {

2016 assert(C == 1 && "Unexpected multiple nodes.");

2017 Nodes[NodePosition[Label]].setCommon(BD);

2018 }

2019

2022 Sink != E; ++Sink) {

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

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

2025 unsigned C = EdgesMap.count(Key);

2026 if (C == 0)

2028 else {

2030 }

2031 }

2032 }

2033

2034

2035 for (auto &E : EdgesMap) {

2036

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

2039 auto &SourceSink = SP1.first;

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

2044

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

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

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

2048 unsigned SinkNode = NodePosition[Sink];

2050

2051

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

2053 if (Inserted)

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

2055 else {

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

2059 It->getValue() = NV;

2060 }

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

2062 }

2063 for (auto &I : Nodes)

2064 I.finalize(*this);

2065}

2066

2067DotCfgDiffDisplayGraph DotCfgDiff::createDisplayGraph(StringRef Title,

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

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

2071 unsigned Entry = NodePosition[EntryNodeName];

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

2073 DotCfgDiffDisplayGraph G(Title.str());

2074

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

2076

2077 int EntryIndex = -1;

2078 unsigned Index = 0;

2079 for (auto &I : Nodes) {

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

2081 EntryIndex = Index;

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

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

2084 }

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

2086 G.setEntryNode(EntryIndex);

2087

2088 for (auto &I : NodeMap) {

2089 unsigned SourceNode = I.first;

2090 unsigned DisplayNode = I.second;

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

2092 }

2093 return G;

2094}

2095

2096void DotCfgDiffNode::createDisplayEdges(

2097 DotCfgDiffDisplayGraph &DisplayGraph, unsigned DisplayNodeIndex,

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

2099

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

2101

2102 for (auto I : Edges) {

2103 unsigned SinkNodeIndex = I;

2104 StringRef Colour = getEdgeColour(SinkNodeIndex);

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

2106

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

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

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

2110 }

2111 SourceDisplayNode.createEdgeMap();

2112}

2113

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

2115 for (auto E : EdgesMap) {

2116 Children.emplace_back(E.first);

2117 Edges.emplace_back(E.first);

2118 }

2119}

2120

2121}

2122

2123namespace llvm {

2124

2125template <> struct GraphTraits<DotCfgDiffDisplayGraph *> {

2131

2133 return G->getEntryNode();

2134 }

2136 return N->children_begin();

2137 }

2140 return G->nodes_begin();

2141 }

2143 return G->nodes_end();

2144 }

2146 return N->edges_begin();

2147 }

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

2151};

2152

2153template <>

2157

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

2160 return DiffData->getGraphName();

2161 }

2162 static std::string

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

2165 }

2167 const DotCfgDiffDisplayGraph *DiffData) {

2168 return DiffData->getNodeLabel(*Node);

2169 }

2171 const DotCfgDiffDisplayGraph *DiffData) {

2172 return DiffData->getNodeAttributes(*Node);

2173 }

2175 DisplayNode::ChildIterator &To) {

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

2177 }

2179 DisplayNode::ChildIterator &To,

2180 const DotCfgDiffDisplayGraph *DiffData) {

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

2182 }

2183};

2184

2185}

2186

2187namespace {

2188

2189void DotCfgDiffDisplayGraph::generateDotFile(StringRef DotFile) {

2190 std::error_code EC;

2192 if (EC) {

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

2194 return;

2195 }

2197 OutStream.flush();

2198 OutStream.close();

2199}

2200

2201}

2202

2203namespace llvm {

2204

2206

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

2208 if (const BranchInst *Br = dyn_cast(Term))

2209 if (Br->isUnconditional())

2211 else {

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

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

2214 }

2215 else if (const SwitchInst *Sw = dyn_cast(Term)) {

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

2217 "default");

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

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

2222 }

2223 } else

2226}

2227

2231}

2232

2235

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

2243

2244 if (InModule) {

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

2247 } else {

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

2250 }

2251

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

2255

2258

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

2260 Divider, Name);

2261

2263 std::string EntryBlockName = After.getEntryBlockName();

2264

2265 if (EntryBlockName == "")

2266 EntryBlockName = Before.getEntryBlockName();

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

2268

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

2270 DG.generateDotFile(DotFile);

2271

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

2274 if (EC)

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

2276}

2277

2281

2283 if (!DotExe)

2284 return "Unable to find dot executable.";

2285

2288 if (Result < 0)

2289 return "Error executing system dot.";

2290

2291

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

2294 return S.c_str();

2295}

2296

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

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

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

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

2302 << "

\n";

2303

2306

2307

2309 .compare(getModuleForComparison(IR),

2310 [&](bool InModule, unsigned Minor,

2315 });

2316 *HTML << "

\n"

2317 << "
\n";

2318 ++N;

2319}

2320

2324}

2325

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

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

2330 N, makeHTMLReady(PassID), Name);

2331 *HTML << Banner;

2332 ++N;

2333}

2334

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

2340 .compare(getModuleForComparison(IR),

2341 [&](bool InModule, unsigned Minor,

2346 });

2347 *HTML << "

\n";

2348 ++N;

2349}

2350

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

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

2355 *HTML << Banner;

2356 ++N;

2357}

2358

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

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

2363 makeHTMLReady(PassID), Name);

2364 *HTML << Banner;

2365 ++N;

2366}

2367

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

2371 makeHTMLReady(PassID), Name);

2372 *HTML << Banner;

2373 ++N;

2374}

2375

2377 std::error_code EC;

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

2379 if (EC) {

2380 HTML = nullptr;

2381 return false;

2382 }

2383

2384 *HTML << ""

2385 << ""

2386 << ""

2387 << ""

2406 << "passes.html"

2407 << "\n"

2408 << "";

2409 return true;

2410}

2411

2414 return;

2416 << ""

2431 << ""

2432 << "\n";

2433 HTML->flush();

2434 HTML->close();

2435}

2436

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

2448 return;

2449 }

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

2451 }

2452}

2453

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

2467

2469 nullptr;

2470

2473 std::error_code EC;

2475 if (EC)

2478 } else {

2480 }

2481}

2482

2483void PrintCrashIRInstrumentation::SignalHandler(void *) {

2484

2485

2486 if (!CrashReporter)

2487 return;

2488

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

2492}

2493

2495 if (!CrashReporter)

2496 return;

2497

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

2500 CrashReporter = nullptr;

2501}

2502

2506 return;

2507

2509 CrashReporter = this;

2510

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

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

2519 return;

2520 }

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

2522 unwrapAndPrint(OS, IR);

2523 });

2524}

2525

2535 if (VerifyEach)

2542 if (MAM)

2544

2545

2546

2547

2548

2549

2550

2552}

2553

2556

2563

2564}

static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)

This file provides Any, a non-template class modeled in the spirit of std::any.

BlockVerifier::State From

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

std::optional< std::vector< StOtherPiece > > Other

Module.h This file contains the declarations for the Module class.

This header defines various interfaces for pass management in LLVM.

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)

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 ...

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

verify safepoint Safepoint IR Verifier

static cl::opt< std::string > BeforeColour("dot-cfg-before-color", cl::desc("Color for dot-cfg before elements"), cl::Hidden, cl::init("red"))

static cl::opt< std::string > IRDumpDirectory("ir-dump-directory", cl::desc("If specified, IR printed using the " "-print-[before|after]{-all} options will be dumped into " "files in this directory rather than written to stderr"), cl::Hidden, cl::value_desc("filename"))

static cl::opt< bool > DroppedVarStats("dropped-variable-stats", cl::Hidden, cl::desc("Dump dropped debug variables stats"), cl::init(false))

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 " (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

void registerCallbacks(PassInstrumentationCallbacks &PIC)

Represents either an error or a value T.

Lightweight error class with error context and mandatory checking.

bool hasOptNone() const

Do not optimize this function (-O0).

Module * getParent()

Get the module that this global value is contained inside of...

~IRChangedPrinter() override

void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override

void registerCallbacks(PassInstrumentationCallbacks &PIC)

void generateIRRepresentation(Any IR, StringRef PassID, std::string &Output) override

void handleIgnored(StringRef PassID, std::string &Name) override

void handleAfter(StringRef PassID, std::string &Name, const std::string &Before, const std::string &After, Any) override

void omitAfter(StringRef PassID, std::string &Name) override

void handleInvalidated(StringRef PassID) override

void handleIR(const std::string &IR, StringRef PassID)

void handleInitialIR(Any IR) override

void registerCallbacks(PassInstrumentationCallbacks &PIC)

void handleFiltered(StringRef PassID, std::string &Name) override

~IRChangedTester() override

static bool generateFunctionData(IRDataT< T > &Data, const FunctionT &F)

static void analyzeIR(Any IR, IRDataT< T > &Data)

void compare(bool CompareModule, std::function< void(bool InModule, unsigned Minor, const FuncDataT< T > &Before, const FuncDataT< T > &After)> CompareFunc)

void registerCallbacks(PassInstrumentationCallbacks &PIC)

~InLineChangePrinter() override

void handleAfter(StringRef PassID, std::string &Name, const IRDataT< EmptyData > &Before, const IRDataT< EmptyData > &After, Any) override

void generateIRRepresentation(Any IR, StringRef PassID, IRDataT< EmptyData > &Output) override

void handleFunctionCompare(StringRef Name, StringRef Prefix, StringRef PassID, StringRef Divider, bool InModule, unsigned Minor, const FuncDataT< EmptyData > &Before, const FuncDataT< EmptyData > &After)

An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...

This is an important class for using LLVM in a threaded context.

OptPassGate & getOptPassGate() const

Access the object which can disable optional passes and individual optimizations at compile time.

A node in the call graph.

An SCC of the call graph.

Represents a single loop in the control flow graph.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

Function & getFunction()

Return the LLVM function that this machine code represents.

void print(raw_ostream &OS, const SlotIndexes *=nullptr) const

print - Print out the MachineFunction in a format suitable for debugging to the specified stream.

A Module instance is used to store all the information related to an LLVM module.

void registerCallbacks(PassInstrumentationCallbacks &PIC)

void registerCallbacks(PassInstrumentationCallbacks &PIC)

bool shouldRun(StringRef PassName, Any IR)

Extensions to this class implement mechanisms to disable passes and individual optimizations at compi...

virtual bool isEnabled() const

isEnabled() should return true before calling shouldRunPass().

virtual bool shouldRunPass(const StringRef PassName, StringRef IRDescription)

IRDescription is a textual description of the IR unit the pass is running over.

static void report(const OrderedChangedData &Before, const OrderedChangedData &After, function_ref< void(const T *, const T *)> HandlePair)

StringMap< T > & getData()

std::vector< std::string > & getOrder()

Pass interface - Implemented by all 'passes'.

A set of analyses that are preserved following a run of a transformation pass.

PreservedAnalysisChecker getChecker() const

Build a checker for this PreservedAnalyses and the specified analysis type.

void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM)

~PrintCrashIRInstrumentation()

void registerCallbacks(PassInstrumentationCallbacks &PIC)

~PrintIRInstrumentation()

void registerCallbacks(PassInstrumentationCallbacks &PIC)

void registerCallbacks(PassInstrumentationCallbacks &PIC)

void registerCallbacks(PassInstrumentationCallbacks &PIC)

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM=nullptr)

StandardInstrumentations(LLVMContext &Context, bool DebugLogging, bool VerifyEach=false, PrintPassOptions PrintPassOpts=PrintPassOptions())

StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...

size_type count(StringRef Key) const

count - Return 1 if the element is in the map, 0 otherwise.

bool insert(MapEntryTy *KeyValue)

insert - Insert the specified key/value pair into the map.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

constexpr bool empty() const

empty - Check if the string is empty.

StringRef drop_front(size_t N=1) const

Return a StringRef equal to 'this' but with the first N elements dropped.

StringRef drop_until(function_ref< bool(char)> F) const

Return a StringRef equal to 'this', but with all characters not satisfying the given predicate droppe...

constexpr size_t size() const

size - Get the string size.

char front() const

front - Get the first character in the string.

bool consume_front(StringRef Prefix)

Returns true if this StringRef has the given prefix and removes that prefix.

StringRef take_until(function_ref< bool(char)> F) const

Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...

std::pair< StringRef, StringRef > rsplit(StringRef Separator) const

Split into two substrings around the last occurrence of a separator string.

void handleInitialIR(Any IR) override

void handleInvalidated(StringRef PassID) override

TextChangeReporter(bool Verbose)

void omitAfter(StringRef PassID, std::string &Name) override

void handleIgnored(StringRef PassID, std::string &Name) override

void handleFiltered(StringRef PassID, std::string &Name) override

void registerCallbacks(PassInstrumentationCallbacks &PIC)

void registerCallbacks(PassInstrumentationCallbacks &PIC)

TimeProfilingPassesHandler()

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

std::string str() const

Return the twine contents as a std::string.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM Value Representation.

StringRef getName() const

Return a constant reference to the value's name.

void registerCallbacks(PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM)

An efficient, type-erasing, non-owning reference to a callable.

A raw_ostream that writes to a file descriptor.

This class implements an extremely fast bulk output stream that can only output to a stream.

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

A raw_ostream that writes to an std::string.

A raw_ostream that writes to an SmallVector or SmallString.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

@ C

The default llvm calling convention, compatible with C.

initializer< Ty > init(const Ty &Val)

DiagnosticInfoOptimizationBase::Argument NV

void make_absolute(const Twine &current_directory, SmallVectorImpl< char > &path)

Make path an absolute path.

std::error_code openFile(const Twine &Name, int &ResultFD, CreationDisposition Disp, FileAccess Access, OpenFlags Flags, unsigned Mode=0666)

Opens a file with the specified creation disposition, access mode, and flags and returns a file descr...

void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)

Expands ~ expressions to the user's home directory.

@ OF_Text

The file should be opened in text mode on platforms like z/OS that make this distinction.

std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)

Remove path.

@ CD_OpenAlways

CD_OpenAlways - When opening a file:

void createUniquePath(const Twine &Model, SmallVectorImpl< char > &ResultPath, bool MakeAbsolute)

Create a potentially unique file name but does not create it.

std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)

Create all the non-existent directories in path.

StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get parent path.

void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)

Add a function to be called when an abort/kill signal is delivered to the process.

int ExecuteAndWait(StringRef Program, ArrayRef< StringRef > Args, std::optional< ArrayRef< StringRef > > Env=std::nullopt, ArrayRef< std::optional< StringRef > > Redirects={}, unsigned SecondsToWait=0, unsigned MemoryLimit=0, std::string *ErrMsg=nullptr, bool *ExecutionFailed=nullptr, std::optional< ProcessStatistics > *ProcStat=nullptr, BitVector *AffinityMask=nullptr)

This function executes the program using the arguments provided.

ErrorOr< std::string > findProgramByName(StringRef Name, ArrayRef< StringRef > Paths={})

Find the first executable file Name in Paths.

This is an optimization pass for GlobalISel generic memory operations.

std::error_code prepareTempFiles(SmallVector< int > &FD, ArrayRef< StringRef > SR, SmallVector< std::string > &FileName)

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

bool forcePrintModuleIR()

std::vector< std::string > printAfterPasses()

uint64_t xxh3_64bits(ArrayRef< uint8_t > data)

bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)

Check a function for errors, useful for use when debugging a pass.

auto successors(const MachineBasicBlock *BB)

bool DisplayGraph(StringRef Filename, bool wait=true, GraphProgram::Name program=GraphProgram::DOT)

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.

auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)

bool shouldPrintAfterSomePass()

void verifyMachineFunction(const std::string &Banner, const MachineFunction &MF)

raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool isFunctionInPrintList(StringRef FunctionName)

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

bool isPassInPrintList(StringRef PassName)

bool isSpecialPass(StringRef PassID, const std::vector< StringRef > &Specials)

void timeTraceProfilerEnd()

Manually end the last time section.

std::error_code cleanUpTempFiles(ArrayRef< std::string > FileName)

raw_fd_ostream & errs()

This returns a reference to a raw_ostream for standard error.

void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)

std::string doSystemDiff(StringRef Before, StringRef After, StringRef OldLineFormat, StringRef NewLineFormat, StringRef UnchangedLineFormat)

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

std::array< uint32_t, 5 > ModuleHash

160 bits SHA1

stable_hash StructuralHash(const Function &F, bool DetailedHash=false)

Returns a hash of the function F.

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)

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)

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.