1 //===-- llvm-mca.cpp - Machine Code Analyzer -------------------*- 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 // 9 // This utility is a simple driver that allows static performance analysis on 10 // machine code similarly to how IACA (Intel Architecture Code Analyzer) works. 11 // 12 // llvm-mca [options] <file-name> 13 // -march <type> 14 // -mcpu <cpu> 15 // -o <file> 16 // 17 // The target defaults to the host target. 18 // The cpu defaults to the 'native' host cpu. 19 // The output defaults to standard output. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #include "CodeRegion.h" 24 #include "CodeRegionGenerator.h" 25 #include "PipelinePrinter.h" 26 #include "Views/BottleneckAnalysis.h" 27 #include "Views/DispatchStatistics.h" 28 #include "Views/InstructionInfoView.h" 29 #include "Views/RegisterFileStatistics.h" 30 #include "Views/ResourcePressureView.h" 31 #include "Views/RetireControlUnitStatistics.h" 32 #include "Views/SchedulerStatistics.h" 33 #include "Views/SummaryView.h" 34 #include "Views/TimelineView.h" 35 #include "llvm/MC/MCAsmBackend.h" 36 #include "llvm/MC/MCAsmInfo.h" 37 #include "llvm/MC/MCCodeEmitter.h" 38 #include "llvm/MC/MCContext.h" 39 #include "llvm/MC/MCObjectFileInfo.h" 40 #include "llvm/MC/MCRegisterInfo.h" 41 #include "llvm/MC/MCSubtargetInfo.h" 42 #include "llvm/MC/MCTargetOptionsCommandFlags.h" 43 #include "llvm/MC/TargetRegistry.h" 44 #include "llvm/MCA/CodeEmitter.h" 45 #include "llvm/MCA/Context.h" 46 #include "llvm/MCA/CustomBehaviour.h" 47 #include "llvm/MCA/InstrBuilder.h" 48 #include "llvm/MCA/Pipeline.h" 49 #include "llvm/MCA/Stages/EntryStage.h" 50 #include "llvm/MCA/Stages/InstructionTables.h" 51 #include "llvm/MCA/Support.h" 52 #include "llvm/Support/CommandLine.h" 53 #include "llvm/Support/ErrorHandling.h" 54 #include "llvm/Support/ErrorOr.h" 55 #include "llvm/Support/FileSystem.h" 56 #include "llvm/Support/Host.h" 57 #include "llvm/Support/InitLLVM.h" 58 #include "llvm/Support/MemoryBuffer.h" 59 #include "llvm/Support/SourceMgr.h" 60 #include "llvm/Support/TargetSelect.h" 61 #include "llvm/Support/ToolOutputFile.h" 62 #include "llvm/Support/WithColor.h" 63 64 using namespace llvm; 65 66 static mc::RegisterMCTargetOptionsFlags MOF; 67 68 static cl::OptionCategory ToolOptions("Tool Options"); 69 static cl::OptionCategory ViewOptions("View Options"); 70 71 static cl::opt<std::string> InputFilename(cl::Positional, 72 cl::desc("<input file>"), 73 cl::cat(ToolOptions), cl::init("-")); 74 75 static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"), 76 cl::init("-"), cl::cat(ToolOptions), 77 cl::value_desc("filename")); 78 79 static cl::opt<std::string> 80 ArchName("march", 81 cl::desc("Target architecture. " 82 "See -version for available targets"), 83 cl::cat(ToolOptions)); 84 85 static cl::opt<std::string> 86 TripleName("mtriple", 87 cl::desc("Target triple. See -version for available targets"), 88 cl::cat(ToolOptions)); 89 90 static cl::opt<std::string> 91 MCPU("mcpu", 92 cl::desc("Target a specific cpu type (-mcpu=help for details)"), 93 cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native")); 94 95 static cl::opt<std::string> MATTR("mattr", 96 cl::desc("Additional target features."), 97 cl::cat(ToolOptions)); 98 99 static cl::opt<bool> PrintJson("json", 100 cl::desc("Print the output in json format"), 101 cl::cat(ToolOptions), cl::init(false)); 102 103 static cl::opt<int> 104 OutputAsmVariant("output-asm-variant", 105 cl::desc("Syntax variant to use for output printing"), 106 cl::cat(ToolOptions), cl::init(-1)); 107 108 static cl::opt<bool> 109 PrintImmHex("print-imm-hex", cl::cat(ToolOptions), cl::init(false), 110 cl::desc("Prefer hex format when printing immediate values")); 111 112 static cl::opt<unsigned> Iterations("iterations", 113 cl::desc("Number of iterations to run"), 114 cl::cat(ToolOptions), cl::init(0)); 115 116 static cl::opt<unsigned> 117 DispatchWidth("dispatch", cl::desc("Override the processor dispatch width"), 118 cl::cat(ToolOptions), cl::init(0)); 119 120 static cl::opt<unsigned> 121 RegisterFileSize("register-file-size", 122 cl::desc("Maximum number of physical registers which can " 123 "be used for register mappings"), 124 cl::cat(ToolOptions), cl::init(0)); 125 126 static cl::opt<unsigned> 127 MicroOpQueue("micro-op-queue-size", cl::Hidden, 128 cl::desc("Number of entries in the micro-op queue"), 129 cl::cat(ToolOptions), cl::init(0)); 130 131 static cl::opt<unsigned> 132 DecoderThroughput("decoder-throughput", cl::Hidden, 133 cl::desc("Maximum throughput from the decoders " 134 "(instructions per cycle)"), 135 cl::cat(ToolOptions), cl::init(0)); 136 137 static cl::opt<bool> 138 PrintRegisterFileStats("register-file-stats", 139 cl::desc("Print register file statistics"), 140 cl::cat(ViewOptions), cl::init(false)); 141 142 static cl::opt<bool> PrintDispatchStats("dispatch-stats", 143 cl::desc("Print dispatch statistics"), 144 cl::cat(ViewOptions), cl::init(false)); 145 146 static cl::opt<bool> 147 PrintSummaryView("summary-view", cl::Hidden, 148 cl::desc("Print summary view (enabled by default)"), 149 cl::cat(ViewOptions), cl::init(true)); 150 151 static cl::opt<bool> PrintSchedulerStats("scheduler-stats", 152 cl::desc("Print scheduler statistics"), 153 cl::cat(ViewOptions), cl::init(false)); 154 155 static cl::opt<bool> 156 PrintRetireStats("retire-stats", 157 cl::desc("Print retire control unit statistics"), 158 cl::cat(ViewOptions), cl::init(false)); 159 160 static cl::opt<bool> PrintResourcePressureView( 161 "resource-pressure", 162 cl::desc("Print the resource pressure view (enabled by default)"), 163 cl::cat(ViewOptions), cl::init(true)); 164 165 static cl::opt<bool> PrintTimelineView("timeline", 166 cl::desc("Print the timeline view"), 167 cl::cat(ViewOptions), cl::init(false)); 168 169 static cl::opt<unsigned> TimelineMaxIterations( 170 "timeline-max-iterations", 171 cl::desc("Maximum number of iterations to print in timeline view"), 172 cl::cat(ViewOptions), cl::init(0)); 173 174 static cl::opt<unsigned> 175 TimelineMaxCycles("timeline-max-cycles", 176 cl::desc("Maximum number of cycles in the timeline view, " 177 "or 0 for unlimited. Defaults to 80 cycles"), 178 cl::cat(ViewOptions), cl::init(80)); 179 180 static cl::opt<bool> 181 AssumeNoAlias("noalias", 182 cl::desc("If set, assume that loads and stores do not alias"), 183 cl::cat(ToolOptions), cl::init(true)); 184 185 static cl::opt<unsigned> LoadQueueSize("lqueue", 186 cl::desc("Size of the load queue"), 187 cl::cat(ToolOptions), cl::init(0)); 188 189 static cl::opt<unsigned> StoreQueueSize("squeue", 190 cl::desc("Size of the store queue"), 191 cl::cat(ToolOptions), cl::init(0)); 192 193 static cl::opt<bool> 194 PrintInstructionTables("instruction-tables", 195 cl::desc("Print instruction tables"), 196 cl::cat(ToolOptions), cl::init(false)); 197 198 static cl::opt<bool> PrintInstructionInfoView( 199 "instruction-info", 200 cl::desc("Print the instruction info view (enabled by default)"), 201 cl::cat(ViewOptions), cl::init(true)); 202 203 static cl::opt<bool> EnableAllStats("all-stats", 204 cl::desc("Print all hardware statistics"), 205 cl::cat(ViewOptions), cl::init(false)); 206 207 static cl::opt<bool> 208 EnableAllViews("all-views", 209 cl::desc("Print all views including hardware statistics"), 210 cl::cat(ViewOptions), cl::init(false)); 211 212 static cl::opt<bool> EnableBottleneckAnalysis( 213 "bottleneck-analysis", 214 cl::desc("Enable bottleneck analysis (disabled by default)"), 215 cl::cat(ViewOptions), cl::init(false)); 216 217 static cl::opt<bool> ShowEncoding( 218 "show-encoding", 219 cl::desc("Print encoding information in the instruction info view"), 220 cl::cat(ViewOptions), cl::init(false)); 221 222 static cl::opt<bool> ShowBarriers( 223 "show-barriers", 224 cl::desc("Print memory barrier information in the instruction info view"), 225 cl::cat(ViewOptions), cl::init(false)); 226 227 static cl::opt<bool> DisableCustomBehaviour( 228 "disable-cb", 229 cl::desc( 230 "Disable custom behaviour (use the default class which does nothing)."), 231 cl::cat(ViewOptions), cl::init(false)); 232 233 namespace { 234 235 const Target *getTarget(const char *ProgName) { 236 if (TripleName.empty()) 237 TripleName = Triple::normalize(sys::getDefaultTargetTriple()); 238 Triple TheTriple(TripleName); 239 240 // Get the target specific parser. 241 std::string Error; 242 const Target *TheTarget = 243 TargetRegistry::lookupTarget(ArchName, TheTriple, Error); 244 if (!TheTarget) { 245 errs() << ProgName << ": " << Error; 246 return nullptr; 247 } 248 249 // Update TripleName with the updated triple from the target lookup. 250 TripleName = TheTriple.str(); 251 252 // Return the found target. 253 return TheTarget; 254 } 255 256 ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() { 257 if (OutputFilename == "") 258 OutputFilename = "-"; 259 std::error_code EC; 260 auto Out = std::make_unique<ToolOutputFile>(OutputFilename, EC, 261 sys::fs::OF_TextWithCRLF); 262 if (!EC) 263 return std::move(Out); 264 return EC; 265 } 266 } // end of anonymous namespace 267 268 static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) { 269 if (!O.getNumOccurrences() || O.getPosition() < Default.getPosition()) 270 O = Default.getValue(); 271 } 272 273 static void processViewOptions(bool IsOutOfOrder) { 274 if (!EnableAllViews.getNumOccurrences() && 275 !EnableAllStats.getNumOccurrences()) 276 return; 277 278 if (EnableAllViews.getNumOccurrences()) { 279 processOptionImpl(PrintSummaryView, EnableAllViews); 280 if (IsOutOfOrder) 281 processOptionImpl(EnableBottleneckAnalysis, EnableAllViews); 282 processOptionImpl(PrintResourcePressureView, EnableAllViews); 283 processOptionImpl(PrintTimelineView, EnableAllViews); 284 processOptionImpl(PrintInstructionInfoView, EnableAllViews); 285 } 286 287 const cl::opt<bool> &Default = 288 EnableAllViews.getPosition() < EnableAllStats.getPosition() 289 ? EnableAllStats 290 : EnableAllViews; 291 processOptionImpl(PrintRegisterFileStats, Default); 292 processOptionImpl(PrintDispatchStats, Default); 293 processOptionImpl(PrintSchedulerStats, Default); 294 if (IsOutOfOrder) 295 processOptionImpl(PrintRetireStats, Default); 296 } 297 298 // Returns true on success. 299 static bool runPipeline(mca::Pipeline &P) { 300 // Handle pipeline errors here. 301 Expected<unsigned> Cycles = P.run(); 302 if (!Cycles) { 303 WithColor::error() << toString(Cycles.takeError()); 304 return false; 305 } 306 return true; 307 } 308 309 int main(int argc, char **argv) { 310 InitLLVM X(argc, argv); 311 312 // Initialize targets and assembly parsers. 313 InitializeAllTargetInfos(); 314 InitializeAllTargetMCs(); 315 InitializeAllAsmParsers(); 316 InitializeAllTargetMCAs(); 317 318 // Enable printing of available targets when flag --version is specified. 319 cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); 320 321 cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions}); 322 323 // Parse flags and initialize target options. 324 cl::ParseCommandLineOptions(argc, argv, 325 "llvm machine code performance analyzer.\n"); 326 327 // Get the target from the triple. If a triple is not specified, then select 328 // the default triple for the host. If the triple doesn't correspond to any 329 // registered target, then exit with an error message. 330 const char *ProgName = argv[0]; 331 const Target *TheTarget = getTarget(ProgName); 332 if (!TheTarget) 333 return 1; 334 335 // GetTarget() may replaced TripleName with a default triple. 336 // For safety, reconstruct the Triple object. 337 Triple TheTriple(TripleName); 338 339 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr = 340 MemoryBuffer::getFileOrSTDIN(InputFilename); 341 if (std::error_code EC = BufferPtr.getError()) { 342 WithColor::error() << InputFilename << ": " << EC.message() << '\n'; 343 return 1; 344 } 345 346 if (MCPU == "native") 347 MCPU = std::string(llvm::sys::getHostCPUName()); 348 349 std::unique_ptr<MCSubtargetInfo> STI( 350 TheTarget->createMCSubtargetInfo(TripleName, MCPU, MATTR)); 351 assert(STI && "Unable to create subtarget info!"); 352 if (!STI->isCPUStringValid(MCPU)) 353 return 1; 354 355 if (!STI->getSchedModel().hasInstrSchedModel()) { 356 WithColor::error() 357 << "unable to find instruction-level scheduling information for" 358 << " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU 359 << "'.\n"; 360 361 if (STI->getSchedModel().InstrItineraries) 362 WithColor::note() 363 << "cpu '" << MCPU << "' provides itineraries. However, " 364 << "instruction itineraries are currently unsupported.\n"; 365 return 1; 366 } 367 368 // Apply overrides to llvm-mca specific options. 369 bool IsOutOfOrder = STI->getSchedModel().isOutOfOrder(); 370 processViewOptions(IsOutOfOrder); 371 372 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); 373 assert(MRI && "Unable to create target register info!"); 374 375 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); 376 std::unique_ptr<MCAsmInfo> MAI( 377 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 378 assert(MAI && "Unable to create target asm info!"); 379 380 SourceMgr SrcMgr; 381 382 // Tell SrcMgr about this buffer, which is what the parser will pick up. 383 SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); 384 385 MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr); 386 std::unique_ptr<MCObjectFileInfo> MOFI( 387 TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false)); 388 Ctx.setObjectFileInfo(MOFI.get()); 389 390 std::unique_ptr<buffer_ostream> BOS; 391 392 std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); 393 assert(MCII && "Unable to create instruction info!"); 394 395 std::unique_ptr<MCInstrAnalysis> MCIA( 396 TheTarget->createMCInstrAnalysis(MCII.get())); 397 398 // Need to initialize an MCInstPrinter as it is 399 // required for initializing the MCTargetStreamer 400 // which needs to happen within the CRG.parseCodeRegions() call below. 401 // Without an MCTargetStreamer, certain assembly directives can trigger a 402 // segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if 403 // we don't initialize the MCTargetStreamer.) 404 unsigned IPtempOutputAsmVariant = 405 OutputAsmVariant == -1 ? 0 : OutputAsmVariant; 406 std::unique_ptr<MCInstPrinter> IPtemp(TheTarget->createMCInstPrinter( 407 Triple(TripleName), IPtempOutputAsmVariant, *MAI, *MCII, *MRI)); 408 if (!IPtemp) { 409 WithColor::error() 410 << "unable to create instruction printer for target triple '" 411 << TheTriple.normalize() << "' with assembly variant " 412 << IPtempOutputAsmVariant << ".\n"; 413 return 1; 414 } 415 416 // Parse the input and create CodeRegions that llvm-mca can analyze. 417 mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII); 418 Expected<const mca::CodeRegions &> RegionsOrErr = 419 CRG.parseCodeRegions(std::move(IPtemp)); 420 if (!RegionsOrErr) { 421 if (auto Err = 422 handleErrors(RegionsOrErr.takeError(), [](const StringError &E) { 423 WithColor::error() << E.getMessage() << '\n'; 424 })) { 425 // Default case. 426 WithColor::error() << toString(std::move(Err)) << '\n'; 427 } 428 return 1; 429 } 430 const mca::CodeRegions &Regions = *RegionsOrErr; 431 432 // Early exit if errors were found by the code region parsing logic. 433 if (!Regions.isValid()) 434 return 1; 435 436 if (Regions.empty()) { 437 WithColor::error() << "no assembly instructions found.\n"; 438 return 1; 439 } 440 441 // Now initialize the output file. 442 auto OF = getOutputStream(); 443 if (std::error_code EC = OF.getError()) { 444 WithColor::error() << EC.message() << '\n'; 445 return 1; 446 } 447 448 unsigned AssemblerDialect = CRG.getAssemblerDialect(); 449 if (OutputAsmVariant >= 0) 450 AssemblerDialect = static_cast<unsigned>(OutputAsmVariant); 451 std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( 452 Triple(TripleName), AssemblerDialect, *MAI, *MCII, *MRI)); 453 if (!IP) { 454 WithColor::error() 455 << "unable to create instruction printer for target triple '" 456 << TheTriple.normalize() << "' with assembly variant " 457 << AssemblerDialect << ".\n"; 458 return 1; 459 } 460 461 // Set the display preference for hex vs. decimal immediates. 462 IP->setPrintImmHex(PrintImmHex); 463 464 std::unique_ptr<ToolOutputFile> TOF = std::move(*OF); 465 466 const MCSchedModel &SM = STI->getSchedModel(); 467 468 // Create an instruction builder. 469 mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get()); 470 471 // Create a context to control ownership of the pipeline hardware. 472 mca::Context MCA(*MRI, *STI); 473 474 mca::PipelineOptions PO(MicroOpQueue, DecoderThroughput, DispatchWidth, 475 RegisterFileSize, LoadQueueSize, StoreQueueSize, 476 AssumeNoAlias, EnableBottleneckAnalysis); 477 478 // Number each region in the sequence. 479 unsigned RegionIdx = 0; 480 481 std::unique_ptr<MCCodeEmitter> MCE( 482 TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); 483 assert(MCE && "Unable to create code emitter!"); 484 485 std::unique_ptr<MCAsmBackend> MAB(TheTarget->createMCAsmBackend( 486 *STI, *MRI, mc::InitMCTargetOptionsFromFlags())); 487 assert(MAB && "Unable to create asm backend!"); 488 489 json::Object JSONOutput; 490 for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) { 491 // Skip empty code regions. 492 if (Region->empty()) 493 continue; 494 495 IB.clear(); 496 497 // Lower the MCInst sequence into an mca::Instruction sequence. 498 ArrayRef<MCInst> Insts = Region->getInstructions(); 499 mca::CodeEmitter CE(*STI, *MAB, *MCE, Insts); 500 501 std::unique_ptr<mca::InstrPostProcess> IPP; 502 if (!DisableCustomBehaviour) { 503 IPP = std::unique_ptr<mca::InstrPostProcess>( 504 TheTarget->createInstrPostProcess(*STI, *MCII)); 505 } 506 if (!IPP) 507 // If the target doesn't have its own IPP implemented (or the 508 // -disable-cb flag is set) then we use the base class 509 // (which does nothing). 510 IPP = std::make_unique<mca::InstrPostProcess>(*STI, *MCII); 511 512 SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence; 513 for (const MCInst &MCI : Insts) { 514 Expected<std::unique_ptr<mca::Instruction>> Inst = 515 IB.createInstruction(MCI); 516 if (!Inst) { 517 if (auto NewE = handleErrors( 518 Inst.takeError(), 519 [&IP, &STI](const mca::InstructionError<MCInst> &IE) { 520 std::string InstructionStr; 521 raw_string_ostream SS(InstructionStr); 522 WithColor::error() << IE.Message << '\n'; 523 IP->printInst(&IE.Inst, 0, "", *STI, SS); 524 SS.flush(); 525 WithColor::note() 526 << "instruction: " << InstructionStr << '\n'; 527 })) { 528 // Default case. 529 WithColor::error() << toString(std::move(NewE)); 530 } 531 return 1; 532 } 533 534 IPP->postProcessInstruction(Inst.get(), MCI); 535 536 LoweredSequence.emplace_back(std::move(Inst.get())); 537 } 538 539 mca::SourceMgr S(LoweredSequence, PrintInstructionTables ? 1 : Iterations); 540 541 if (PrintInstructionTables) { 542 // Create a pipeline, stages, and a printer. 543 auto P = std::make_unique<mca::Pipeline>(); 544 P->appendStage(std::make_unique<mca::EntryStage>(S)); 545 P->appendStage(std::make_unique<mca::InstructionTables>(SM)); 546 547 mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO); 548 if (PrintJson) { 549 Printer.addView( 550 std::make_unique<mca::InstructionView>(*STI, *IP, Insts)); 551 } 552 553 // Create the views for this pipeline, execute, and emit a report. 554 if (PrintInstructionInfoView) { 555 Printer.addView(std::make_unique<mca::InstructionInfoView>( 556 *STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence, 557 ShowBarriers)); 558 } 559 Printer.addView( 560 std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); 561 562 if (!runPipeline(*P)) 563 return 1; 564 565 if (PrintJson) { 566 Printer.printReport(JSONOutput); 567 } else { 568 Printer.printReport(TOF->os()); 569 } 570 571 ++RegionIdx; 572 continue; 573 } 574 575 // Create the CustomBehaviour object for enforcing Target Specific 576 // behaviours and dependencies that aren't expressed well enough 577 // in the tablegen. CB cannot depend on the list of MCInst or 578 // the source code (but it can depend on the list of 579 // mca::Instruction or any objects that can be reconstructed 580 // from the target information). 581 std::unique_ptr<mca::CustomBehaviour> CB; 582 if (!DisableCustomBehaviour) 583 CB = std::unique_ptr<mca::CustomBehaviour>( 584 TheTarget->createCustomBehaviour(*STI, S, *MCII)); 585 if (!CB) 586 // If the target doesn't have its own CB implemented (or the -disable-cb 587 // flag is set) then we use the base class (which does nothing). 588 CB = std::make_unique<mca::CustomBehaviour>(*STI, S, *MCII); 589 590 // Create a basic pipeline simulating an out-of-order backend. 591 auto P = MCA.createDefaultPipeline(PO, S, *CB); 592 593 mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO); 594 595 // Targets can define their own custom Views that exist within their 596 // /lib/Target/ directory so that the View can utilize their CustomBehaviour 597 // or other backend symbols / functionality that are not already exposed 598 // through one of the MC-layer classes. These Views will be initialized 599 // using the CustomBehaviour::getViews() variants. 600 // If a target makes a custom View that does not depend on their target 601 // CB or their backend, they should put the View within 602 // /tools/llvm-mca/Views/ instead. 603 if (!DisableCustomBehaviour) { 604 std::vector<std::unique_ptr<mca::View>> CBViews = 605 CB->getStartViews(*IP, Insts); 606 for (auto &CBView : CBViews) 607 Printer.addView(std::move(CBView)); 608 } 609 610 // When we output JSON, we add a view that contains the instructions 611 // and CPU resource information. 612 if (PrintJson) { 613 auto IV = std::make_unique<mca::InstructionView>(*STI, *IP, Insts); 614 Printer.addView(std::move(IV)); 615 } 616 617 if (PrintSummaryView) 618 Printer.addView( 619 std::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth)); 620 621 if (EnableBottleneckAnalysis) { 622 if (!IsOutOfOrder) { 623 WithColor::warning() 624 << "bottleneck analysis is not supported for in-order CPU '" << MCPU 625 << "'.\n"; 626 } 627 Printer.addView(std::make_unique<mca::BottleneckAnalysis>( 628 *STI, *IP, Insts, S.getNumIterations())); 629 } 630 631 if (PrintInstructionInfoView) 632 Printer.addView(std::make_unique<mca::InstructionInfoView>( 633 *STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence, 634 ShowBarriers)); 635 636 // Fetch custom Views that are to be placed after the InstructionInfoView. 637 // Refer to the comment paired with the CB->getStartViews(*IP, Insts); line 638 // for more info. 639 if (!DisableCustomBehaviour) { 640 std::vector<std::unique_ptr<mca::View>> CBViews = 641 CB->getPostInstrInfoViews(*IP, Insts); 642 for (auto &CBView : CBViews) 643 Printer.addView(std::move(CBView)); 644 } 645 646 if (PrintDispatchStats) 647 Printer.addView(std::make_unique<mca::DispatchStatistics>()); 648 649 if (PrintSchedulerStats) 650 Printer.addView(std::make_unique<mca::SchedulerStatistics>(*STI)); 651 652 if (PrintRetireStats) 653 Printer.addView(std::make_unique<mca::RetireControlUnitStatistics>(SM)); 654 655 if (PrintRegisterFileStats) 656 Printer.addView(std::make_unique<mca::RegisterFileStatistics>(*STI)); 657 658 if (PrintResourcePressureView) 659 Printer.addView( 660 std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); 661 662 if (PrintTimelineView) { 663 unsigned TimelineIterations = 664 TimelineMaxIterations ? TimelineMaxIterations : 10; 665 Printer.addView(std::make_unique<mca::TimelineView>( 666 *STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()), 667 TimelineMaxCycles)); 668 } 669 670 // Fetch custom Views that are to be placed after all other Views. 671 // Refer to the comment paired with the CB->getStartViews(*IP, Insts); line 672 // for more info. 673 if (!DisableCustomBehaviour) { 674 std::vector<std::unique_ptr<mca::View>> CBViews = 675 CB->getEndViews(*IP, Insts); 676 for (auto &CBView : CBViews) 677 Printer.addView(std::move(CBView)); 678 } 679 680 if (!runPipeline(*P)) 681 return 1; 682 683 if (PrintJson) { 684 Printer.printReport(JSONOutput); 685 } else { 686 Printer.printReport(TOF->os()); 687 } 688 689 ++RegionIdx; 690 } 691 692 if (PrintJson) 693 TOF->os() << formatv("{0:2}", json::Value(std::move(JSONOutput))) << "\n"; 694 695 TOF->keep(); 696 return 0; 697 } 698