1 //===- Standard pass instrumentations handling ----------------*- C++ -*--===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file defines IR-printing pass instrumentation callbacks as well as 11 /// StandardInstrumentations class that manages standard pass instrumentations. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Passes/StandardInstrumentations.h" 16 #include "llvm/ADT/Any.h" 17 #include "llvm/ADT/Optional.h" 18 #include "llvm/Analysis/CallGraphSCCPass.h" 19 #include "llvm/Analysis/LazyCallGraph.h" 20 #include "llvm/Analysis/LoopInfo.h" 21 #include "llvm/IR/Function.h" 22 #include "llvm/IR/IRPrintingPasses.h" 23 #include "llvm/IR/Module.h" 24 #include "llvm/IR/PassInstrumentation.h" 25 #include "llvm/IR/Verifier.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Support/Debug.h" 28 #include "llvm/Support/FormatVariadic.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <unordered_set> 31 #include <vector> 32 33 using namespace llvm; 34 35 cl::opt<bool> PreservedCFGCheckerInstrumentation::VerifyPreservedCFG( 36 "verify-cfg-preserved", cl::Hidden, 37 #ifdef NDEBUG 38 cl::init(false)); 39 #else 40 cl::init(false)); 41 #endif 42 43 // FIXME: Change `-debug-pass-manager` from boolean to enum type. Similar to 44 // `-debug-pass` in legacy PM. 45 static cl::opt<bool> 46 DebugPMVerbose("debug-pass-manager-verbose", cl::Hidden, cl::init(false), 47 cl::desc("Print all pass management debugging information. " 48 "`-debug-pass-manager` must also be specified")); 49 50 // An option that prints out the IR after passes, similar to 51 // -print-after-all except that it only prints the IR after passes that 52 // change the IR. Those passes that do not make changes to the IR are 53 // reported as not making any changes. In addition, the initial IR is 54 // also reported. Other hidden options affect the output from this 55 // option. -filter-passes will limit the output to the named passes 56 // that actually change the IR and other passes are reported as filtered out. 57 // The specified passes will either be reported as making no changes (with 58 // no IR reported) or the changed IR will be reported. Also, the 59 // -filter-print-funcs and -print-module-scope options will do similar 60 // filtering based on function name, reporting changed IRs as functions(or 61 // modules if -print-module-scope is specified) for a particular function 62 // or indicating that the IR has been filtered out. The extra options 63 // can be combined, allowing only changed IRs for certain passes on certain 64 // functions to be reported in different formats, with the rest being 65 // reported as filtered out. The -print-before-changed option will print 66 // the IR as it was before each pass that changed it. 67 static cl::opt<bool> PrintChanged("print-changed", 68 cl::desc("Print changed IRs"), 69 cl::init(false), cl::Hidden); 70 // An option that supports the -print-changed option. See 71 // the description for -print-changed for an explanation of the use 72 // of this option. Note that this option has no effect without -print-changed. 73 static cl::list<std::string> 74 PrintPassesList("filter-passes", cl::value_desc("pass names"), 75 cl::desc("Only consider IR changes for passes whose names " 76 "match for the print-changed option"), 77 cl::CommaSeparated, cl::Hidden); 78 // An option that supports the -print-changed option. See 79 // the description for -print-changed for an explanation of the use 80 // of this option. Note that this option has no effect without -print-changed. 81 static cl::opt<bool> 82 PrintChangedBefore("print-before-changed", 83 cl::desc("Print before passes that change them"), 84 cl::init(false), cl::Hidden); 85 86 namespace { 87 88 /// Extracting Module out of \p IR unit. Also fills a textual description 89 /// of \p IR for use in header when printing. 90 Optional<std::pair<const Module *, std::string>> 91 unwrapModule(Any IR, bool Force = false) { 92 if (any_isa<const Module *>(IR)) 93 return std::make_pair(any_cast<const Module *>(IR), std::string()); 94 95 if (any_isa<const Function *>(IR)) { 96 const Function *F = any_cast<const Function *>(IR); 97 if (!Force && !llvm::isFunctionInPrintList(F->getName())) 98 return None; 99 100 const Module *M = F->getParent(); 101 return std::make_pair(M, formatv(" (function: {0})", F->getName()).str()); 102 } 103 104 if (any_isa<const LazyCallGraph::SCC *>(IR)) { 105 const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR); 106 for (const LazyCallGraph::Node &N : *C) { 107 const Function &F = N.getFunction(); 108 if (Force || (!F.isDeclaration() && isFunctionInPrintList(F.getName()))) { 109 const Module *M = F.getParent(); 110 return std::make_pair(M, formatv(" (scc: {0})", C->getName()).str()); 111 } 112 } 113 assert(!Force && "Expected to have made a pair when forced."); 114 return None; 115 } 116 117 if (any_isa<const Loop *>(IR)) { 118 const Loop *L = any_cast<const Loop *>(IR); 119 const Function *F = L->getHeader()->getParent(); 120 if (!Force && !isFunctionInPrintList(F->getName())) 121 return None; 122 const Module *M = F->getParent(); 123 std::string LoopName; 124 raw_string_ostream ss(LoopName); 125 L->getHeader()->printAsOperand(ss, false); 126 return std::make_pair(M, formatv(" (loop: {0})", ss.str()).str()); 127 } 128 129 llvm_unreachable("Unknown IR unit"); 130 } 131 132 void printIR(raw_ostream &OS, const Function *F, StringRef Banner, 133 StringRef Extra = StringRef(), bool Brief = false) { 134 if (Brief) { 135 OS << F->getName() << '\n'; 136 return; 137 } 138 139 if (!llvm::isFunctionInPrintList(F->getName())) 140 return; 141 OS << Banner << Extra << "\n" << static_cast<const Value &>(*F); 142 } 143 144 void printIR(raw_ostream &OS, const Module *M, StringRef Banner, 145 StringRef Extra = StringRef(), bool Brief = false, 146 bool ShouldPreserveUseListOrder = false) { 147 if (Brief) { 148 OS << M->getName() << '\n'; 149 return; 150 } 151 152 if (llvm::isFunctionInPrintList("*") || llvm::forcePrintModuleIR()) { 153 OS << Banner << Extra << "\n"; 154 M->print(OS, nullptr, ShouldPreserveUseListOrder); 155 } else { 156 for (const auto &F : M->functions()) { 157 printIR(OS, &F, Banner, Extra); 158 } 159 } 160 } 161 162 void printIR(raw_ostream &OS, const LazyCallGraph::SCC *C, StringRef Banner, 163 StringRef Extra = StringRef(), bool Brief = false) { 164 if (Brief) { 165 OS << *C << '\n'; 166 return; 167 } 168 169 bool BannerPrinted = false; 170 for (const LazyCallGraph::Node &N : *C) { 171 const Function &F = N.getFunction(); 172 if (!F.isDeclaration() && llvm::isFunctionInPrintList(F.getName())) { 173 if (!BannerPrinted) { 174 OS << Banner << Extra << "\n"; 175 BannerPrinted = true; 176 } 177 F.print(OS); 178 } 179 } 180 } 181 182 void printIR(raw_ostream &OS, const Loop *L, StringRef Banner, 183 bool Brief = false) { 184 if (Brief) { 185 OS << *L; 186 return; 187 } 188 189 const Function *F = L->getHeader()->getParent(); 190 if (!llvm::isFunctionInPrintList(F->getName())) 191 return; 192 llvm::printLoop(const_cast<Loop &>(*L), OS, std::string(Banner)); 193 } 194 195 /// Generic IR-printing helper that unpacks a pointer to IRUnit wrapped into 196 /// llvm::Any and does actual print job. 197 void unwrapAndPrint(raw_ostream &OS, Any IR, StringRef Banner, 198 bool ForceModule = false, bool Brief = false, 199 bool ShouldPreserveUseListOrder = false) { 200 if (ForceModule) { 201 if (auto UnwrappedModule = unwrapModule(IR)) 202 printIR(OS, UnwrappedModule->first, Banner, UnwrappedModule->second, 203 Brief, ShouldPreserveUseListOrder); 204 return; 205 } 206 207 if (any_isa<const Module *>(IR)) { 208 const Module *M = any_cast<const Module *>(IR); 209 assert(M && "module should be valid for printing"); 210 printIR(OS, M, Banner, "", Brief, ShouldPreserveUseListOrder); 211 return; 212 } 213 214 if (any_isa<const Function *>(IR)) { 215 const Function *F = any_cast<const Function *>(IR); 216 assert(F && "function should be valid for printing"); 217 printIR(OS, F, Banner, "", Brief); 218 return; 219 } 220 221 if (any_isa<const LazyCallGraph::SCC *>(IR)) { 222 const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR); 223 assert(C && "scc should be valid for printing"); 224 std::string Extra = std::string(formatv(" (scc: {0})", C->getName())); 225 printIR(OS, C, Banner, Extra, Brief); 226 return; 227 } 228 229 if (any_isa<const Loop *>(IR)) { 230 const Loop *L = any_cast<const Loop *>(IR); 231 assert(L && "Loop should be valid for printing"); 232 printIR(OS, L, Banner, Brief); 233 return; 234 } 235 llvm_unreachable("Unknown wrapped IR type"); 236 } 237 238 // Return true when this is a pass for which changes should be ignored 239 bool isIgnored(StringRef PassID) { 240 return isSpecialPass(PassID, 241 {"PassManager", "PassAdaptor", "AnalysisManagerProxy"}); 242 } 243 244 } // namespace 245 246 template <typename IRUnitT> 247 ChangeReporter<IRUnitT>::~ChangeReporter<IRUnitT>() { 248 assert(BeforeStack.empty() && "Problem with Change Printer stack."); 249 } 250 251 template <typename IRUnitT> 252 bool ChangeReporter<IRUnitT>::isInterestingFunction(const Function &F) { 253 return llvm::isFunctionInPrintList(F.getName()); 254 } 255 256 template <typename IRUnitT> 257 bool ChangeReporter<IRUnitT>::isInterestingPass(StringRef PassID) { 258 if (isIgnored(PassID)) 259 return false; 260 261 static std::unordered_set<std::string> PrintPassNames(PrintPassesList.begin(), 262 PrintPassesList.end()); 263 return PrintPassNames.empty() || PrintPassNames.count(PassID.str()); 264 } 265 266 // Return true when this is a pass on IR for which printing 267 // of changes is desired. 268 template <typename IRUnitT> 269 bool ChangeReporter<IRUnitT>::isInteresting(Any IR, StringRef PassID) { 270 if (!isInterestingPass(PassID)) 271 return false; 272 if (any_isa<const Function *>(IR)) 273 return isInterestingFunction(*any_cast<const Function *>(IR)); 274 return true; 275 } 276 277 template <typename IRUnitT> 278 void ChangeReporter<IRUnitT>::saveIRBeforePass(Any IR, StringRef PassID) { 279 // Always need to place something on the stack because invalidated passes 280 // are not given the IR so it cannot be determined whether the pass was for 281 // something that was filtered out. 282 BeforeStack.emplace_back(); 283 284 if (!isInteresting(IR, PassID)) 285 return; 286 // Is this the initial IR? 287 if (InitialIR) { 288 InitialIR = false; 289 handleInitialIR(IR); 290 } 291 292 // Save the IR representation on the stack. 293 IRUnitT &Data = BeforeStack.back(); 294 generateIRRepresentation(IR, PassID, Data); 295 } 296 297 template <typename IRUnitT> 298 void ChangeReporter<IRUnitT>::handleIRAfterPass(Any IR, StringRef PassID) { 299 assert(!BeforeStack.empty() && "Unexpected empty stack encountered."); 300 std::string Name; 301 302 // unwrapModule has inconsistent handling of names for function IRs. 303 if (any_isa<const Function *>(IR)) { 304 const Function *F = any_cast<const Function *>(IR); 305 Name = formatv(" (function: {0})", F->getName()).str(); 306 } else { 307 if (auto UM = unwrapModule(IR)) 308 Name = UM->second; 309 } 310 if (Name == "") 311 Name = " (module)"; 312 313 if (isIgnored(PassID)) 314 handleIgnored(PassID, Name); 315 else if (!isInteresting(IR, PassID)) 316 handleFiltered(PassID, Name); 317 else { 318 // Get the before rep from the stack 319 IRUnitT &Before = BeforeStack.back(); 320 // Create the after rep 321 IRUnitT After; 322 generateIRRepresentation(IR, PassID, After); 323 324 // Was there a change in IR? 325 if (same(Before, After)) 326 omitAfter(PassID, Name); 327 else 328 handleAfter(PassID, Name, Before, After, IR); 329 } 330 BeforeStack.pop_back(); 331 } 332 333 template <typename IRUnitT> 334 void ChangeReporter<IRUnitT>::handleInvalidatedPass(StringRef PassID) { 335 assert(!BeforeStack.empty() && "Unexpected empty stack encountered."); 336 337 // Always flag it as invalidated as we cannot determine when 338 // a pass for a filtered function is invalidated since we do not 339 // get the IR in the call. Also, the output is just alternate 340 // forms of the banner anyway. 341 handleInvalidated(PassID); 342 BeforeStack.pop_back(); 343 } 344 345 template <typename IRUnitT> 346 void ChangeReporter<IRUnitT>::registerRequiredCallbacks( 347 PassInstrumentationCallbacks &PIC) { 348 PIC.registerBeforeNonSkippedPassCallback( 349 [this](StringRef P, Any IR) { saveIRBeforePass(IR, P); }); 350 351 PIC.registerAfterPassCallback( 352 [this](StringRef P, Any IR, const PreservedAnalyses &) { 353 handleIRAfterPass(IR, P); 354 }); 355 PIC.registerAfterPassInvalidatedCallback( 356 [this](StringRef P, const PreservedAnalyses &) { 357 handleInvalidatedPass(P); 358 }); 359 } 360 361 template <typename IRUnitT> 362 TextChangeReporter<IRUnitT>::TextChangeReporter() 363 : ChangeReporter<IRUnitT>(), Out(dbgs()) {} 364 365 template <typename IRUnitT> 366 void TextChangeReporter<IRUnitT>::handleInitialIR(Any IR) { 367 // Always print the module. 368 // Unwrap and print directly to avoid filtering problems in general routines. 369 auto UnwrappedModule = unwrapModule(IR, /*Force=*/true); 370 assert(UnwrappedModule && "Expected module to be unwrapped when forced."); 371 Out << "*** IR Dump At Start: ***" << UnwrappedModule->second << "\n"; 372 UnwrappedModule->first->print(Out, nullptr, 373 /*ShouldPreserveUseListOrder=*/true); 374 } 375 376 template <typename IRUnitT> 377 void TextChangeReporter<IRUnitT>::omitAfter(StringRef PassID, 378 std::string &Name) { 379 Out << formatv("*** IR Dump After {0}{1} omitted because no change ***\n", 380 PassID, Name); 381 } 382 383 template <typename IRUnitT> 384 void TextChangeReporter<IRUnitT>::handleInvalidated(StringRef PassID) { 385 Out << formatv("*** IR Pass {0} invalidated ***\n", PassID); 386 } 387 388 template <typename IRUnitT> 389 void TextChangeReporter<IRUnitT>::handleFiltered(StringRef PassID, 390 std::string &Name) { 391 SmallString<20> Banner = 392 formatv("*** IR Dump After {0}{1} filtered out ***\n", PassID, Name); 393 Out << Banner; 394 } 395 396 template <typename IRUnitT> 397 void TextChangeReporter<IRUnitT>::handleIgnored(StringRef PassID, 398 std::string &Name) { 399 Out << formatv("*** IR Pass {0}{1} ignored ***\n", PassID, Name); 400 } 401 402 IRChangedPrinter::~IRChangedPrinter() {} 403 404 void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) { 405 if (PrintChanged) 406 TextChangeReporter<std::string>::registerRequiredCallbacks(PIC); 407 } 408 409 void IRChangedPrinter::generateIRRepresentation(Any IR, StringRef PassID, 410 std::string &Output) { 411 raw_string_ostream OS(Output); 412 // use the after banner for all cases so it will match 413 SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); 414 unwrapAndPrint(OS, IR, Banner, forcePrintModuleIR(), 415 /*Brief=*/false, /*ShouldPreserveUseListOrder=*/true); 416 417 OS.str(); 418 } 419 420 void IRChangedPrinter::handleAfter(StringRef PassID, std::string &Name, 421 const std::string &Before, 422 const std::string &After, Any) { 423 assert(After.find("*** IR Dump") == 0 && "Unexpected banner format."); 424 StringRef AfterRef = After; 425 StringRef Banner = 426 AfterRef.take_until([](char C) -> bool { return C == '\n'; }); 427 428 // Report the IR before the changes when requested. 429 if (PrintChangedBefore) { 430 Out << "*** IR Dump Before" << Banner.substr(17); 431 // LazyCallGraph::SCC already has "(scc:..." in banner so only add 432 // in the name if it isn't already there. 433 if (Name.substr(0, 6) != " (scc:" && !llvm::forcePrintModuleIR()) 434 Out << Name; 435 436 StringRef BeforeRef = Before; 437 Out << BeforeRef.substr(Banner.size()); 438 } 439 440 Out << Banner; 441 442 // LazyCallGraph::SCC already has "(scc:..." in banner so only add 443 // in the name if it isn't already there. 444 if (Name.substr(0, 6) != " (scc:" && !llvm::forcePrintModuleIR()) 445 Out << Name; 446 447 Out << After.substr(Banner.size()); 448 } 449 450 bool IRChangedPrinter::same(const std::string &S1, const std::string &S2) { 451 return S1 == S2; 452 } 453 454 PrintIRInstrumentation::~PrintIRInstrumentation() { 455 assert(ModuleDescStack.empty() && "ModuleDescStack is not empty at exit"); 456 } 457 458 void PrintIRInstrumentation::pushModuleDesc(StringRef PassID, Any IR) { 459 assert(StoreModuleDesc); 460 const Module *M = nullptr; 461 std::string Extra; 462 if (auto UnwrappedModule = unwrapModule(IR)) 463 std::tie(M, Extra) = UnwrappedModule.getValue(); 464 ModuleDescStack.emplace_back(M, Extra, PassID); 465 } 466 467 PrintIRInstrumentation::PrintModuleDesc 468 PrintIRInstrumentation::popModuleDesc(StringRef PassID) { 469 assert(!ModuleDescStack.empty() && "empty ModuleDescStack"); 470 PrintModuleDesc ModuleDesc = ModuleDescStack.pop_back_val(); 471 assert(std::get<2>(ModuleDesc).equals(PassID) && "malformed ModuleDescStack"); 472 return ModuleDesc; 473 } 474 475 void PrintIRInstrumentation::printBeforePass(StringRef PassID, Any IR) { 476 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) 477 return; 478 479 // Saving Module for AfterPassInvalidated operations. 480 // Note: here we rely on a fact that we do not change modules while 481 // traversing the pipeline, so the latest captured module is good 482 // for all print operations that has not happen yet. 483 if (StoreModuleDesc && llvm::shouldPrintAfterPass(PassID)) 484 pushModuleDesc(PassID, IR); 485 486 if (!llvm::shouldPrintBeforePass(PassID)) 487 return; 488 489 SmallString<20> Banner = formatv("*** IR Dump Before {0} ***", PassID); 490 unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR()); 491 return; 492 } 493 494 void PrintIRInstrumentation::printAfterPass(StringRef PassID, Any IR) { 495 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) 496 return; 497 498 if (!llvm::shouldPrintAfterPass(PassID)) 499 return; 500 501 if (StoreModuleDesc) 502 popModuleDesc(PassID); 503 504 SmallString<20> Banner = formatv("*** IR Dump After {0} ***", PassID); 505 unwrapAndPrint(dbgs(), IR, Banner, llvm::forcePrintModuleIR()); 506 } 507 508 void PrintIRInstrumentation::printAfterPassInvalidated(StringRef PassID) { 509 if (!StoreModuleDesc || !llvm::shouldPrintAfterPass(PassID)) 510 return; 511 512 if (PassID.startswith("PassManager<") || PassID.contains("PassAdaptor<")) 513 return; 514 515 const Module *M; 516 std::string Extra; 517 StringRef StoredPassID; 518 std::tie(M, Extra, StoredPassID) = popModuleDesc(PassID); 519 // Additional filtering (e.g. -filter-print-func) can lead to module 520 // printing being skipped. 521 if (!M) 522 return; 523 524 SmallString<20> Banner = 525 formatv("*** IR Dump After {0} *** invalidated: ", PassID); 526 printIR(dbgs(), M, Banner, Extra); 527 } 528 529 void PrintIRInstrumentation::registerCallbacks( 530 PassInstrumentationCallbacks &PIC) { 531 // BeforePass callback is not just for printing, it also saves a Module 532 // for later use in AfterPassInvalidated. 533 StoreModuleDesc = llvm::forcePrintModuleIR() && llvm::shouldPrintAfterPass(); 534 if (llvm::shouldPrintBeforePass() || StoreModuleDesc) 535 PIC.registerBeforeNonSkippedPassCallback( 536 [this](StringRef P, Any IR) { this->printBeforePass(P, IR); }); 537 538 if (llvm::shouldPrintAfterPass()) { 539 PIC.registerAfterPassCallback( 540 [this](StringRef P, Any IR, const PreservedAnalyses &) { 541 this->printAfterPass(P, IR); 542 }); 543 PIC.registerAfterPassInvalidatedCallback( 544 [this](StringRef P, const PreservedAnalyses &) { 545 this->printAfterPassInvalidated(P); 546 }); 547 } 548 } 549 550 void OptNoneInstrumentation::registerCallbacks( 551 PassInstrumentationCallbacks &PIC) { 552 PIC.registerShouldRunOptionalPassCallback( 553 [this](StringRef P, Any IR) { return this->shouldRun(P, IR); }); 554 } 555 556 bool OptNoneInstrumentation::shouldRun(StringRef PassID, Any IR) { 557 const Function *F = nullptr; 558 if (any_isa<const Function *>(IR)) { 559 F = any_cast<const Function *>(IR); 560 } else if (any_isa<const Loop *>(IR)) { 561 F = any_cast<const Loop *>(IR)->getHeader()->getParent(); 562 } 563 bool ShouldRun = !(F && F->hasOptNone()); 564 if (!ShouldRun && DebugLogging) { 565 errs() << "Skipping pass " << PassID << " on " << F->getName() 566 << " due to optnone attribute\n"; 567 } 568 return ShouldRun; 569 } 570 571 static std::string getBisectDescription(Any IR) { 572 if (any_isa<const Module *>(IR)) { 573 const Module *M = any_cast<const Module *>(IR); 574 assert(M && "module should be valid for printing"); 575 return "module (" + M->getName().str() + ")"; 576 } 577 578 if (any_isa<const Function *>(IR)) { 579 const Function *F = any_cast<const Function *>(IR); 580 assert(F && "function should be valid for printing"); 581 return "function (" + F->getName().str() + ")"; 582 } 583 584 if (any_isa<const LazyCallGraph::SCC *>(IR)) { 585 const LazyCallGraph::SCC *C = any_cast<const LazyCallGraph::SCC *>(IR); 586 assert(C && "scc should be valid for printing"); 587 return "SCC " + C->getName(); 588 } 589 590 if (any_isa<const Loop *>(IR)) { 591 return "loop"; 592 } 593 594 llvm_unreachable("Unknown wrapped IR type"); 595 } 596 597 void OptBisectInstrumentation::registerCallbacks( 598 PassInstrumentationCallbacks &PIC) { 599 if (!isEnabled()) 600 return; 601 602 std::vector<StringRef> SpecialPasses = {"PassManager", "PassAdaptor"}; 603 604 PIC.registerShouldRunOptionalPassCallback( 605 [this, SpecialPasses](StringRef PassID, Any IR) { 606 return isSpecialPass(PassID, SpecialPasses) || 607 checkPass(PassID, getBisectDescription(IR)); 608 }); 609 } 610 611 void PrintPassInstrumentation::registerCallbacks( 612 PassInstrumentationCallbacks &PIC) { 613 if (!DebugLogging) 614 return; 615 616 std::vector<StringRef> SpecialPasses = {"PassManager"}; 617 if (!DebugPMVerbose) 618 SpecialPasses.emplace_back("PassAdaptor"); 619 620 PIC.registerBeforeSkippedPassCallback( 621 [SpecialPasses](StringRef PassID, Any IR) { 622 assert(!isSpecialPass(PassID, SpecialPasses) && 623 "Unexpectedly skipping special pass"); 624 625 dbgs() << "Skipping pass: " << PassID << " on "; 626 unwrapAndPrint(dbgs(), IR, "", false, true); 627 }); 628 629 PIC.registerBeforeNonSkippedPassCallback( 630 [SpecialPasses](StringRef PassID, Any IR) { 631 if (isSpecialPass(PassID, SpecialPasses)) 632 return; 633 634 dbgs() << "Running pass: " << PassID << " on "; 635 unwrapAndPrint(dbgs(), IR, "", false, true); 636 }); 637 638 PIC.registerBeforeAnalysisCallback([](StringRef PassID, Any IR) { 639 dbgs() << "Running analysis: " << PassID << " on "; 640 unwrapAndPrint(dbgs(), IR, "", false, true); 641 }); 642 } 643 644 PreservedCFGCheckerInstrumentation::CFG::CFG(const Function *F, 645 bool TrackBBLifetime) { 646 if (TrackBBLifetime) 647 BBGuards = DenseMap<intptr_t, BBGuard>(F->size()); 648 for (const auto &BB : *F) { 649 if (BBGuards) 650 BBGuards->try_emplace(intptr_t(&BB), &BB); 651 for (auto *Succ : successors(&BB)) { 652 Graph[&BB][Succ]++; 653 if (BBGuards) 654 BBGuards->try_emplace(intptr_t(Succ), Succ); 655 } 656 } 657 } 658 659 static void printBBName(raw_ostream &out, const BasicBlock *BB) { 660 if (BB->hasName()) { 661 out << BB->getName() << "<" << BB << ">"; 662 return; 663 } 664 665 if (!BB->getParent()) { 666 out << "unnamed_removed<" << BB << ">"; 667 return; 668 } 669 670 if (BB == &BB->getParent()->getEntryBlock()) { 671 out << "entry" 672 << "<" << BB << ">"; 673 return; 674 } 675 676 unsigned FuncOrderBlockNum = 0; 677 for (auto &FuncBB : *BB->getParent()) { 678 if (&FuncBB == BB) 679 break; 680 FuncOrderBlockNum++; 681 } 682 out << "unnamed_" << FuncOrderBlockNum << "<" << BB << ">"; 683 } 684 685 void PreservedCFGCheckerInstrumentation::CFG::printDiff(raw_ostream &out, 686 const CFG &Before, 687 const CFG &After) { 688 assert(!After.isPoisoned()); 689 690 // Print function name. 691 const CFG *FuncGraph = nullptr; 692 if (!After.Graph.empty()) 693 FuncGraph = &After; 694 else if (!Before.isPoisoned() && !Before.Graph.empty()) 695 FuncGraph = &Before; 696 697 if (FuncGraph) 698 out << "In function @" 699 << FuncGraph->Graph.begin()->first->getParent()->getName() << "\n"; 700 701 if (Before.isPoisoned()) { 702 out << "Some blocks were deleted\n"; 703 return; 704 } 705 706 // Find and print graph differences. 707 if (Before.Graph.size() != After.Graph.size()) 708 out << "Different number of non-leaf basic blocks: before=" 709 << Before.Graph.size() << ", after=" << After.Graph.size() << "\n"; 710 711 for (auto &BB : Before.Graph) { 712 auto BA = After.Graph.find(BB.first); 713 if (BA == After.Graph.end()) { 714 out << "Non-leaf block "; 715 printBBName(out, BB.first); 716 out << " is removed (" << BB.second.size() << " successors)\n"; 717 } 718 } 719 720 for (auto &BA : After.Graph) { 721 auto BB = Before.Graph.find(BA.first); 722 if (BB == Before.Graph.end()) { 723 out << "Non-leaf block "; 724 printBBName(out, BA.first); 725 out << " is added (" << BA.second.size() << " successors)\n"; 726 continue; 727 } 728 729 if (BB->second == BA.second) 730 continue; 731 732 out << "Different successors of block "; 733 printBBName(out, BA.first); 734 out << " (unordered):\n"; 735 out << "- before (" << BB->second.size() << "): "; 736 for (auto &SuccB : BB->second) { 737 printBBName(out, SuccB.first); 738 if (SuccB.second != 1) 739 out << "(" << SuccB.second << "), "; 740 else 741 out << ", "; 742 } 743 out << "\n"; 744 out << "- after (" << BA.second.size() << "): "; 745 for (auto &SuccA : BA.second) { 746 printBBName(out, SuccA.first); 747 if (SuccA.second != 1) 748 out << "(" << SuccA.second << "), "; 749 else 750 out << ", "; 751 } 752 out << "\n"; 753 } 754 } 755 756 void PreservedCFGCheckerInstrumentation::registerCallbacks( 757 PassInstrumentationCallbacks &PIC) { 758 if (!VerifyPreservedCFG) 759 return; 760 761 PIC.registerBeforeNonSkippedPassCallback([this](StringRef P, Any IR) { 762 if (any_isa<const Function *>(IR)) 763 GraphStackBefore.emplace_back(P, CFG(any_cast<const Function *>(IR))); 764 else 765 GraphStackBefore.emplace_back(P, None); 766 }); 767 768 PIC.registerAfterPassInvalidatedCallback( 769 [this](StringRef P, const PreservedAnalyses &PassPA) { 770 auto Before = GraphStackBefore.pop_back_val(); 771 assert(Before.first == P && 772 "Before and After callbacks must correspond"); 773 (void)Before; 774 }); 775 776 PIC.registerAfterPassCallback([this](StringRef P, Any IR, 777 const PreservedAnalyses &PassPA) { 778 auto Before = GraphStackBefore.pop_back_val(); 779 assert(Before.first == P && "Before and After callbacks must correspond"); 780 auto &GraphBefore = Before.second; 781 782 if (!PassPA.allAnalysesInSetPreserved<CFGAnalyses>()) 783 return; 784 785 if (any_isa<const Function *>(IR)) { 786 assert(GraphBefore && "Must be built in BeforePassCallback"); 787 CFG GraphAfter(any_cast<const Function *>(IR), false /* NeedsGuard */); 788 if (GraphAfter == *GraphBefore) 789 return; 790 791 dbgs() << "Error: " << P 792 << " reported it preserved CFG, but changes detected:\n"; 793 CFG::printDiff(dbgs(), *GraphBefore, GraphAfter); 794 report_fatal_error(Twine("Preserved CFG changed by ", P)); 795 } 796 }); 797 } 798 799 void VerifyInstrumentation::registerCallbacks( 800 PassInstrumentationCallbacks &PIC) { 801 PIC.registerAfterPassCallback( 802 [this](StringRef P, Any IR, const PreservedAnalyses &PassPA) { 803 if (isIgnored(P) || P == "VerifierPass") 804 return; 805 if (any_isa<const Function *>(IR) || any_isa<const Loop *>(IR)) { 806 const Function *F; 807 if (any_isa<const Loop *>(IR)) 808 F = any_cast<const Loop *>(IR)->getHeader()->getParent(); 809 else 810 F = any_cast<const Function *>(IR); 811 if (DebugLogging) 812 dbgs() << "Verifying function " << F->getName() << "\n"; 813 814 if (verifyFunction(*F)) 815 report_fatal_error("Broken function found, compilation aborted!"); 816 } else if (any_isa<const Module *>(IR) || 817 any_isa<const LazyCallGraph::SCC *>(IR)) { 818 const Module *M; 819 if (any_isa<const LazyCallGraph::SCC *>(IR)) 820 M = any_cast<const LazyCallGraph::SCC *>(IR) 821 ->begin() 822 ->getFunction() 823 .getParent(); 824 else 825 M = any_cast<const Module *>(IR); 826 if (DebugLogging) 827 dbgs() << "Verifying module " << M->getName() << "\n"; 828 829 if (verifyModule(*M)) 830 report_fatal_error("Broken module found, compilation aborted!"); 831 } 832 }); 833 } 834 835 void StandardInstrumentations::registerCallbacks( 836 PassInstrumentationCallbacks &PIC) { 837 PrintIR.registerCallbacks(PIC); 838 PrintPass.registerCallbacks(PIC); 839 TimePasses.registerCallbacks(PIC); 840 OptNone.registerCallbacks(PIC); 841 OptBisect.registerCallbacks(PIC); 842 PreservedCFGChecker.registerCallbacks(PIC); 843 PrintChangedIR.registerCallbacks(PIC); 844 if (VerifyEach) 845 Verify.registerCallbacks(PIC); 846 } 847 848 namespace llvm { 849 850 template class ChangeReporter<std::string>; 851 template class TextChangeReporter<std::string>; 852 853 } // namespace llvm 854