brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.6 KiB · a64539c Raw
852 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This utility is a simple driver that allows static performance analysis on10// 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/InitLLVM.h"57#include "llvm/Support/MemoryBuffer.h"58#include "llvm/Support/SourceMgr.h"59#include "llvm/Support/TargetSelect.h"60#include "llvm/Support/ToolOutputFile.h"61#include "llvm/Support/WithColor.h"62#include "llvm/TargetParser/Host.h"63 64using namespace llvm;65 66static mc::RegisterMCTargetOptionsFlags MOF;67 68static cl::OptionCategory ToolOptions("Tool Options");69static cl::OptionCategory ViewOptions("View Options");70 71static cl::opt<std::string> InputFilename(cl::Positional,72                                          cl::desc("<input file>"),73                                          cl::cat(ToolOptions), cl::init("-"));74 75static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),76                                           cl::init("-"), cl::cat(ToolOptions),77                                           cl::value_desc("filename"));78 79static cl::opt<std::string>80    ArchName("march",81             cl::desc("Target architecture. "82                      "See -version for available targets"),83             cl::cat(ToolOptions));84 85static cl::opt<std::string>86    TripleNameOpt("mtriple",87                  cl::desc("Target triple. See -version for available targets"),88                  cl::cat(ToolOptions));89 90static 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 95static cl::list<std::string>96    MATTRS("mattr", cl::CommaSeparated,97           cl::desc("Target specific attributes (-mattr=help for details)"),98           cl::value_desc("a1,+a2,-a3,..."), cl::cat(ToolOptions));99 100static cl::opt<bool> PrintJson("json",101                               cl::desc("Print the output in json format"),102                               cl::cat(ToolOptions), cl::init(false));103 104static cl::opt<int>105    OutputAsmVariant("output-asm-variant",106                     cl::desc("Syntax variant to use for output printing"),107                     cl::cat(ToolOptions), cl::init(-1));108 109static cl::opt<bool>110    PrintImmHex("print-imm-hex", cl::cat(ToolOptions), cl::init(false),111                cl::desc("Prefer hex format when printing immediate values"));112 113static cl::opt<unsigned> Iterations("iterations",114                                    cl::desc("Number of iterations to run"),115                                    cl::cat(ToolOptions), cl::init(0));116 117static cl::opt<unsigned>118    DispatchWidth("dispatch", cl::desc("Override the processor dispatch width"),119                  cl::cat(ToolOptions), cl::init(0));120 121static cl::opt<unsigned>122    RegisterFileSize("register-file-size",123                     cl::desc("Maximum number of physical registers which can "124                              "be used for register mappings"),125                     cl::cat(ToolOptions), cl::init(0));126 127static cl::opt<unsigned>128    MicroOpQueue("micro-op-queue-size", cl::Hidden,129                 cl::desc("Number of entries in the micro-op queue"),130                 cl::cat(ToolOptions), cl::init(0));131 132static cl::opt<unsigned>133    DecoderThroughput("decoder-throughput", cl::Hidden,134                      cl::desc("Maximum throughput from the decoders "135                               "(instructions per cycle)"),136                      cl::cat(ToolOptions), cl::init(0));137 138static cl::opt<unsigned>139    CallLatency("call-latency", cl::Hidden,140                cl::desc("Number of cycles to assume for a call instruction"),141                cl::cat(ToolOptions), cl::init(100U));142 143enum class SkipType { NONE, LACK_SCHED, PARSE_FAILURE, ANY_FAILURE };144 145static cl::opt<enum SkipType> SkipUnsupportedInstructions(146    "skip-unsupported-instructions",147    cl::desc("Force analysis to continue in the presence of unsupported "148             "instructions"),149    cl::values(150        clEnumValN(SkipType::NONE, "none",151                   "Exit with an error when an instruction is unsupported for "152                   "any reason (default)"),153        clEnumValN(154            SkipType::LACK_SCHED, "lack-sched",155            "Skip instructions on input which lack scheduling information"),156        clEnumValN(157            SkipType::PARSE_FAILURE, "parse-failure",158            "Skip lines on the input which fail to parse for any reason"),159        clEnumValN(SkipType::ANY_FAILURE, "any",160                   "Skip instructions or lines on input which are unsupported "161                   "for any reason")),162    cl::init(SkipType::NONE), cl::cat(ViewOptions));163 164bool shouldSkip(enum SkipType skipType) {165  if (SkipUnsupportedInstructions == SkipType::NONE)166    return false;167  if (SkipUnsupportedInstructions == SkipType::ANY_FAILURE)168    return true;169  return skipType == SkipUnsupportedInstructions;170}171 172static cl::opt<bool>173    PrintRegisterFileStats("register-file-stats",174                           cl::desc("Print register file statistics"),175                           cl::cat(ViewOptions), cl::init(false));176 177static cl::opt<bool> PrintDispatchStats("dispatch-stats",178                                        cl::desc("Print dispatch statistics"),179                                        cl::cat(ViewOptions), cl::init(false));180 181static cl::opt<bool>182    PrintSummaryView("summary-view", cl::Hidden,183                     cl::desc("Print summary view (enabled by default)"),184                     cl::cat(ViewOptions), cl::init(true));185 186static cl::opt<bool> PrintSchedulerStats("scheduler-stats",187                                         cl::desc("Print scheduler statistics"),188                                         cl::cat(ViewOptions), cl::init(false));189 190static cl::opt<bool>191    PrintRetireStats("retire-stats",192                     cl::desc("Print retire control unit statistics"),193                     cl::cat(ViewOptions), cl::init(false));194 195static cl::opt<bool> PrintResourcePressureView(196    "resource-pressure",197    cl::desc("Print the resource pressure view (enabled by default)"),198    cl::cat(ViewOptions), cl::init(true));199 200static cl::opt<bool> PrintTimelineView("timeline",201                                       cl::desc("Print the timeline view"),202                                       cl::cat(ViewOptions), cl::init(false));203 204static cl::opt<unsigned> TimelineMaxIterations(205    "timeline-max-iterations",206    cl::desc("Maximum number of iterations to print in timeline view"),207    cl::cat(ViewOptions), cl::init(0));208 209static cl::opt<unsigned>210    TimelineMaxCycles("timeline-max-cycles",211                      cl::desc("Maximum number of cycles in the timeline view, "212                               "or 0 for unlimited. Defaults to 80 cycles"),213                      cl::cat(ViewOptions), cl::init(80));214 215static cl::opt<bool>216    AssumeNoAlias("noalias",217                  cl::desc("If set, assume that loads and stores do not alias"),218                  cl::cat(ToolOptions), cl::init(true));219 220static cl::opt<unsigned> LoadQueueSize("lqueue",221                                       cl::desc("Size of the load queue"),222                                       cl::cat(ToolOptions), cl::init(0));223 224static cl::opt<unsigned> StoreQueueSize("squeue",225                                        cl::desc("Size of the store queue"),226                                        cl::cat(ToolOptions), cl::init(0));227 228enum class InstructionTablesType { NONE, NORMAL, FULL };229 230static cl::opt<enum InstructionTablesType> InstructionTablesOption(231    "instruction-tables", cl::desc("Print instruction tables"),232    cl::values(clEnumValN(InstructionTablesType::NONE, "none",233                          "Do not print instruction tables"),234               clEnumValN(InstructionTablesType::NORMAL, "normal",235                          "Print instruction tables"),236               clEnumValN(InstructionTablesType::NORMAL, "", ""),237               clEnumValN(InstructionTablesType::FULL, "full",238                          "Print instruction tables with additional"239                          " information: bypass latency, LLVM opcode,"240                          " used resources")),241    cl::cat(ToolOptions), cl::init(InstructionTablesType::NONE),242    cl::ValueOptional);243 244static bool shouldPrintInstructionTables(enum InstructionTablesType ITType) {245  return InstructionTablesOption == ITType;246}247 248static bool shouldPrintInstructionTables() {249  return !shouldPrintInstructionTables(InstructionTablesType::NONE);250}251 252static cl::opt<bool> PrintInstructionInfoView(253    "instruction-info",254    cl::desc("Print the instruction info view (enabled by default)"),255    cl::cat(ViewOptions), cl::init(true));256 257static cl::opt<bool> EnableAllStats("all-stats",258                                    cl::desc("Print all hardware statistics"),259                                    cl::cat(ViewOptions), cl::init(false));260 261static cl::opt<bool>262    EnableAllViews("all-views",263                   cl::desc("Print all views including hardware statistics"),264                   cl::cat(ViewOptions), cl::init(false));265 266static cl::opt<bool> EnableBottleneckAnalysis(267    "bottleneck-analysis",268    cl::desc("Enable bottleneck analysis (disabled by default)"),269    cl::cat(ViewOptions), cl::init(false));270 271static cl::opt<bool> ShowEncoding(272    "show-encoding",273    cl::desc("Print encoding information in the instruction info view"),274    cl::cat(ViewOptions), cl::init(false));275 276static cl::opt<bool> ShowBarriers(277    "show-barriers",278    cl::desc("Print memory barrier information in the instruction info view"),279    cl::cat(ViewOptions), cl::init(false));280 281static cl::opt<bool> DisableCustomBehaviour(282    "disable-cb",283    cl::desc(284        "Disable custom behaviour (use the default class which does nothing)."),285    cl::cat(ViewOptions), cl::init(false));286 287static cl::opt<bool> DisableInstrumentManager(288    "disable-im",289    cl::desc("Disable instrumentation manager (use the default class which "290             "ignores instruments.)."),291    cl::cat(ViewOptions), cl::init(false));292 293namespace {294 295const Target *getTarget(Triple &TheTriple, const char *ProgName) {296  // Get the target specific parser.297  std::string Error;298  const Target *TheTarget =299      TargetRegistry::lookupTarget(ArchName, TheTriple, Error);300  if (!TheTarget) {301    errs() << ProgName << ": " << Error;302    return nullptr;303  }304 305  // Return the found target.306  return TheTarget;307}308 309ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {310  if (OutputFilename == "")311    OutputFilename = "-";312  std::error_code EC;313  auto Out = std::make_unique<ToolOutputFile>(OutputFilename, EC,314                                              sys::fs::OF_TextWithCRLF);315  if (!EC)316    return std::move(Out);317  return EC;318}319} // end of anonymous namespace320 321static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) {322  if (!O.getNumOccurrences() || O.getPosition() < Default.getPosition())323    O = Default.getValue();324}325 326static void processViewOptions(bool IsOutOfOrder) {327  if (!EnableAllViews.getNumOccurrences() &&328      !EnableAllStats.getNumOccurrences())329    return;330 331  if (EnableAllViews.getNumOccurrences()) {332    processOptionImpl(PrintSummaryView, EnableAllViews);333    if (IsOutOfOrder)334      processOptionImpl(EnableBottleneckAnalysis, EnableAllViews);335    processOptionImpl(PrintResourcePressureView, EnableAllViews);336    processOptionImpl(PrintTimelineView, EnableAllViews);337    processOptionImpl(PrintInstructionInfoView, EnableAllViews);338  }339 340  const cl::opt<bool> &Default =341      EnableAllViews.getPosition() < EnableAllStats.getPosition()342          ? EnableAllStats343          : EnableAllViews;344  processOptionImpl(PrintRegisterFileStats, Default);345  processOptionImpl(PrintDispatchStats, Default);346  processOptionImpl(PrintSchedulerStats, Default);347  if (IsOutOfOrder)348    processOptionImpl(PrintRetireStats, Default);349}350 351// Returns true on success.352static bool runPipeline(mca::Pipeline &P) {353  // Handle pipeline errors here.354  Expected<unsigned> Cycles = P.run();355  if (!Cycles) {356    WithColor::error() << toString(Cycles.takeError());357    return false;358  }359  return true;360}361 362int main(int argc, char **argv) {363  InitLLVM X(argc, argv);364 365  // Initialize targets and assembly parsers.366  InitializeAllTargetInfos();367  InitializeAllTargetMCs();368  InitializeAllAsmParsers();369  InitializeAllTargetMCAs();370 371  // Register the Target and CPU printer for --version.372  cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);373 374  // Enable printing of available targets when flag --version is specified.375  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);376 377  cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions});378 379  // Parse flags and initialize target options.380  cl::ParseCommandLineOptions(argc, argv,381                              "llvm machine code performance analyzer.\n");382 383  Triple TheTriple(TripleNameOpt.empty()384                       ? Triple::normalize(sys::getDefaultTargetTriple())385                       : TripleNameOpt);386 387  // Get the target from the triple. If a triple is not specified, then select388  // the default triple for the host. If the triple doesn't correspond to any389  // registered target, then exit with an error message.390  const char *ProgName = argv[0];391  const Target *TheTarget = getTarget(TheTriple, ProgName);392  if (!TheTarget)393    return 1;394 395  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =396      MemoryBuffer::getFileOrSTDIN(InputFilename);397  if (std::error_code EC = BufferPtr.getError()) {398    WithColor::error() << InputFilename << ": " << EC.message() << '\n';399    return 1;400  }401 402  if (MCPU == "native")403    MCPU = std::string(llvm::sys::getHostCPUName());404 405  // Package up features to be passed to target/subtarget406  std::string FeaturesStr;407  if (MATTRS.size()) {408    SubtargetFeatures Features;409    for (std::string &MAttr : MATTRS)410      Features.AddFeature(MAttr);411    FeaturesStr = Features.getString();412  }413 414  std::unique_ptr<MCSubtargetInfo> STI(415      TheTarget->createMCSubtargetInfo(TheTriple, MCPU, FeaturesStr));416  if (!STI) {417    WithColor::error() << "unable to create subtarget info\n";418    return 1;419  }420 421  if (!STI->isCPUStringValid(MCPU))422    return 1;423 424  if (!STI->getSchedModel().hasInstrSchedModel()) {425    WithColor::error()426        << "unable to find instruction-level scheduling information for"427        << " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU428        << "'.\n";429 430    if (STI->getSchedModel().InstrItineraries)431      WithColor::note()432          << "cpu '" << MCPU << "' provides itineraries. However, "433          << "instruction itineraries are currently unsupported.\n";434    return 1;435  }436 437  // Apply overrides to llvm-mca specific options.438  bool IsOutOfOrder = STI->getSchedModel().isOutOfOrder();439  processViewOptions(IsOutOfOrder);440 441  std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TheTriple));442  assert(MRI && "Unable to create target register info!");443 444  MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();445  std::unique_ptr<MCAsmInfo> MAI(446      TheTarget->createMCAsmInfo(*MRI, TheTriple, MCOptions));447  assert(MAI && "Unable to create target asm info!");448 449  SourceMgr SrcMgr;450 451  // Tell SrcMgr about this buffer, which is what the parser will pick up.452  SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());453 454  std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());455  assert(MCII && "Unable to create instruction info!");456 457  std::unique_ptr<MCInstrAnalysis> MCIA(458      TheTarget->createMCInstrAnalysis(MCII.get()));459 460  // Need to initialize an MCInstPrinter as it is461  // required for initializing the MCTargetStreamer462  // which needs to happen within the CRG.parseAnalysisRegions() call below.463  // Without an MCTargetStreamer, certain assembly directives can trigger a464  // segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if465  // we don't initialize the MCTargetStreamer.)466  unsigned IPtempOutputAsmVariant =467      OutputAsmVariant == -1 ? 0 : OutputAsmVariant;468  std::unique_ptr<MCInstPrinter> IPtemp(TheTarget->createMCInstPrinter(469      TheTriple, IPtempOutputAsmVariant, *MAI, *MCII, *MRI));470  if (!IPtemp) {471    WithColor::error()472        << "unable to create instruction printer for target triple '"473        << TheTriple.normalize() << "' with assembly variant "474        << IPtempOutputAsmVariant << ".\n";475    return 1;476  }477 478  // Parse the input and create CodeRegions that llvm-mca can analyze.479  MCContext ACtx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);480  std::unique_ptr<MCObjectFileInfo> AMOFI(481      TheTarget->createMCObjectFileInfo(ACtx, /*PIC=*/false));482  ACtx.setObjectFileInfo(AMOFI.get());483  mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, ACtx, *MAI, *STI,484                                      *MCII);485  Expected<const mca::AnalysisRegions &> RegionsOrErr =486      CRG.parseAnalysisRegions(std::move(IPtemp),487                               shouldSkip(SkipType::PARSE_FAILURE));488  if (!RegionsOrErr) {489    if (auto Err =490            handleErrors(RegionsOrErr.takeError(), [](const StringError &E) {491              WithColor::error() << E.getMessage() << '\n';492            })) {493      // Default case.494      WithColor::error() << toString(std::move(Err)) << '\n';495    }496    return 1;497  }498  const mca::AnalysisRegions &Regions = *RegionsOrErr;499 500  // Early exit if errors were found by the code region parsing logic.501  if (!Regions.isValid())502    return 1;503 504  if (Regions.empty()) {505    WithColor::error() << "no assembly instructions found.\n";506    return 1;507  }508 509  std::unique_ptr<mca::InstrumentManager> IM;510  if (!DisableInstrumentManager) {511    IM = std::unique_ptr<mca::InstrumentManager>(512        TheTarget->createInstrumentManager(*STI, *MCII));513    if (!IM) {514      // If the target doesn't have its own IM implemented we use base class515      // with instruments enabled.516      IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);517    }518  } else {519    // If the -disable-im flag is set then we use the default base class520    // implementation and disable the instruments.521    IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII,522                                                  /*EnableInstruments=*/false);523  }524 525  // Parse the input and create InstrumentRegion that llvm-mca526  // can use to improve analysis.527  MCContext ICtx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);528  std::unique_ptr<MCObjectFileInfo> IMOFI(529      TheTarget->createMCObjectFileInfo(ICtx, /*PIC=*/false));530  ICtx.setObjectFileInfo(IMOFI.get());531  mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, ICtx, *MAI, *STI,532                                        *MCII, *IM);533  Expected<const mca::InstrumentRegions &> InstrumentRegionsOrErr =534      IRG.parseInstrumentRegions(std::move(IPtemp),535                                 shouldSkip(SkipType::PARSE_FAILURE));536  if (!InstrumentRegionsOrErr) {537    if (auto Err = handleErrors(InstrumentRegionsOrErr.takeError(),538                                [](const StringError &E) {539                                  WithColor::error() << E.getMessage() << '\n';540                                })) {541      // Default case.542      WithColor::error() << toString(std::move(Err)) << '\n';543    }544    return 1;545  }546  const mca::InstrumentRegions &InstrumentRegions = *InstrumentRegionsOrErr;547 548  // Early exit if errors were found by the instrumentation parsing logic.549  if (!InstrumentRegions.isValid())550    return 1;551 552  // Now initialize the output file.553  auto OF = getOutputStream();554  if (std::error_code EC = OF.getError()) {555    WithColor::error() << EC.message() << '\n';556    return 1;557  }558 559  unsigned AssemblerDialect = CRG.getAssemblerDialect();560  if (OutputAsmVariant >= 0)561    AssemblerDialect = static_cast<unsigned>(OutputAsmVariant);562  std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(563      TheTriple, AssemblerDialect, *MAI, *MCII, *MRI));564  if (!IP) {565    WithColor::error()566        << "unable to create instruction printer for target triple '"567        << TheTriple.normalize() << "' with assembly variant "568        << AssemblerDialect << ".\n";569    return 1;570  }571 572  // Set the display preference for hex vs. decimal immediates.573  IP->setPrintImmHex(PrintImmHex);574 575  std::unique_ptr<ToolOutputFile> TOF = std::move(*OF);576 577  const MCSchedModel &SM = STI->getSchedModel();578 579  std::unique_ptr<mca::InstrPostProcess> IPP;580  if (!DisableCustomBehaviour) {581    // TODO: It may be a good idea to separate CB and IPP so that they can582    // be used independently of each other. What I mean by this is to add583    // an extra command-line arg --disable-ipp so that CB and IPP can be584    // toggled without needing to toggle both of them together.585    IPP = std::unique_ptr<mca::InstrPostProcess>(586        TheTarget->createInstrPostProcess(*STI, *MCII));587  }588  if (!IPP) {589    // If the target doesn't have its own IPP implemented (or the -disable-cb590    // flag is set) then we use the base class (which does nothing).591    IPP = std::make_unique<mca::InstrPostProcess>(*STI, *MCII);592  }593 594  // Create an instruction builder.595  mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, CallLatency);596 597  // Create a context to control ownership of the pipeline hardware.598  mca::Context MCA(*MRI, *STI);599 600  mca::PipelineOptions PO(MicroOpQueue, DecoderThroughput, DispatchWidth,601                          RegisterFileSize, LoadQueueSize, StoreQueueSize,602                          AssumeNoAlias, EnableBottleneckAnalysis);603 604  // Number each region in the sequence.605  unsigned RegionIdx = 0;606 607  std::unique_ptr<MCCodeEmitter> MCE(608      TheTarget->createMCCodeEmitter(*MCII, ACtx));609  assert(MCE && "Unable to create code emitter!");610 611  std::unique_ptr<MCAsmBackend> MAB(TheTarget->createMCAsmBackend(612      *STI, *MRI, mc::InitMCTargetOptionsFromFlags()));613  assert(MAB && "Unable to create asm backend!");614 615  json::Object JSONOutput;616  int NonEmptyRegions = 0;617  for (const std::unique_ptr<mca::AnalysisRegion> &Region : Regions) {618    // Skip empty code regions.619    if (Region->empty())620      continue;621 622    IB.clear();623 624    // Lower the MCInst sequence into an mca::Instruction sequence.625    ArrayRef<MCInst> Insts = Region->getInstructions();626    mca::CodeEmitter CE(*STI, *MAB, *MCE, Insts);627 628    IPP->resetState();629 630    DenseMap<const MCInst *, SmallVector<mca::Instrument *>> InstToInstruments;631    SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;632    SmallPtrSet<const MCInst *, 16> DroppedInsts;633    for (const MCInst &MCI : Insts) {634      SMLoc Loc = MCI.getLoc();635      const SmallVector<mca::Instrument *> Instruments =636          InstrumentRegions.getActiveInstruments(Loc);637 638      Expected<std::unique_ptr<mca::Instruction>> Inst =639          IB.createInstruction(MCI, Instruments);640      if (!Inst) {641        if (auto NewE = handleErrors(642                Inst.takeError(),643                [&IP, &STI](const mca::InstructionError<MCInst> &IE) {644                  std::string InstructionStr;645                  raw_string_ostream SS(InstructionStr);646                  if (shouldSkip(SkipType::LACK_SCHED))647                    WithColor::warning()648                        << IE.Message649                        << ", skipping with -skip-unsupported-instructions, "650                           "note accuracy will be impacted:\n";651                  else652                    WithColor::error()653                        << IE.Message654                        << ", use -skip-unsupported-instructions=lack-sched to "655                           "ignore these on the input.\n";656                  IP->printInst(&IE.Inst, 0, "", *STI, SS);657                  SS.flush();658                  WithColor::note()659                      << "instruction: " << InstructionStr << '\n';660                })) {661          // Default case.662          WithColor::error() << toString(std::move(NewE));663        }664        if (shouldSkip(SkipType::LACK_SCHED)) {665          DroppedInsts.insert(&MCI);666          continue;667        }668        return 1;669      }670 671      IPP->postProcessInstruction(*Inst.get(), MCI);672      InstToInstruments.insert({&MCI, Instruments});673      LoweredSequence.emplace_back(std::move(Inst.get()));674    }675 676    Insts = Region->dropInstructions(DroppedInsts);677 678    // Skip empty regions.679    if (Insts.empty())680      continue;681    NonEmptyRegions++;682 683    mca::CircularSourceMgr S(LoweredSequence,684                             shouldPrintInstructionTables() ? 1 : Iterations);685 686    if (shouldPrintInstructionTables()) {687      //  Create a pipeline, stages, and a printer.688      auto P = std::make_unique<mca::Pipeline>();689      P->appendStage(std::make_unique<mca::EntryStage>(S));690      P->appendStage(std::make_unique<mca::InstructionTables>(SM));691 692      mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO);693      if (PrintJson) {694        Printer.addView(695            std::make_unique<mca::InstructionView>(*STI, *IP, Insts));696      }697 698      // Create the views for this pipeline, execute, and emit a report.699      if (PrintInstructionInfoView) {700        Printer.addView(std::make_unique<mca::InstructionInfoView>(701            *STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,702            ShowBarriers,703            shouldPrintInstructionTables(InstructionTablesType::FULL), *IM,704            InstToInstruments));705      }706 707      if (PrintResourcePressureView)708        Printer.addView(709            std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));710 711      if (!runPipeline(*P))712        return 1;713 714      if (PrintJson) {715        Printer.printReport(JSONOutput);716      } else {717        Printer.printReport(TOF->os());718      }719 720      ++RegionIdx;721      continue;722    }723 724    // Create the CustomBehaviour object for enforcing Target Specific725    // behaviours and dependencies that aren't expressed well enough726    // in the tablegen. CB cannot depend on the list of MCInst or727    // the source code (but it can depend on the list of728    // mca::Instruction or any objects that can be reconstructed729    // from the target information).730    std::unique_ptr<mca::CustomBehaviour> CB;731    if (!DisableCustomBehaviour)732      CB = std::unique_ptr<mca::CustomBehaviour>(733          TheTarget->createCustomBehaviour(*STI, S, *MCII));734    if (!CB)735      // If the target doesn't have its own CB implemented (or the -disable-cb736      // flag is set) then we use the base class (which does nothing).737      CB = std::make_unique<mca::CustomBehaviour>(*STI, S, *MCII);738 739    // Create a basic pipeline simulating an out-of-order backend.740    auto P = MCA.createDefaultPipeline(PO, S, *CB);741 742    mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO);743 744    // Targets can define their own custom Views that exist within their745    // /lib/Target/ directory so that the View can utilize their CustomBehaviour746    // or other backend symbols / functionality that are not already exposed747    // through one of the MC-layer classes. These Views will be initialized748    // using the CustomBehaviour::getViews() variants.749    // If a target makes a custom View that does not depend on their target750    // CB or their backend, they should put the View within751    // /tools/llvm-mca/Views/ instead.752    if (!DisableCustomBehaviour) {753      std::vector<std::unique_ptr<mca::View>> CBViews =754          CB->getStartViews(*IP, Insts);755      for (auto &CBView : CBViews)756        Printer.addView(std::move(CBView));757    }758 759    // When we output JSON, we add a view that contains the instructions760    // and CPU resource information.761    if (PrintJson) {762      auto IV = std::make_unique<mca::InstructionView>(*STI, *IP, Insts);763      Printer.addView(std::move(IV));764    }765 766    if (PrintSummaryView)767      Printer.addView(768          std::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth));769 770    if (EnableBottleneckAnalysis) {771      if (!IsOutOfOrder) {772        WithColor::warning()773            << "bottleneck analysis is not supported for in-order CPU '" << MCPU774            << "'.\n";775      }776      Printer.addView(std::make_unique<mca::BottleneckAnalysis>(777          *STI, *IP, Insts, S.getNumIterations()));778    }779 780    if (PrintInstructionInfoView)781      Printer.addView(std::make_unique<mca::InstructionInfoView>(782          *STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,783          ShowBarriers, /*ShouldPrintFullInfo=*/false, *IM, InstToInstruments));784 785    // Fetch custom Views that are to be placed after the InstructionInfoView.786    // Refer to the comment paired with the CB->getStartViews(*IP, Insts); line787    // for more info.788    if (!DisableCustomBehaviour) {789      std::vector<std::unique_ptr<mca::View>> CBViews =790          CB->getPostInstrInfoViews(*IP, Insts);791      for (auto &CBView : CBViews)792        Printer.addView(std::move(CBView));793    }794 795    if (PrintDispatchStats)796      Printer.addView(std::make_unique<mca::DispatchStatistics>());797 798    if (PrintSchedulerStats)799      Printer.addView(std::make_unique<mca::SchedulerStatistics>(*STI));800 801    if (PrintRetireStats)802      Printer.addView(std::make_unique<mca::RetireControlUnitStatistics>(SM));803 804    if (PrintRegisterFileStats)805      Printer.addView(std::make_unique<mca::RegisterFileStatistics>(*STI));806 807    if (PrintResourcePressureView)808      Printer.addView(809          std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));810 811    if (PrintTimelineView) {812      unsigned TimelineIterations =813          TimelineMaxIterations ? TimelineMaxIterations : 10;814      Printer.addView(std::make_unique<mca::TimelineView>(815          *STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()),816          TimelineMaxCycles));817    }818 819    // Fetch custom Views that are to be placed after all other Views.820    // Refer to the comment paired with the CB->getStartViews(*IP, Insts); line821    // for more info.822    if (!DisableCustomBehaviour) {823      std::vector<std::unique_ptr<mca::View>> CBViews =824          CB->getEndViews(*IP, Insts);825      for (auto &CBView : CBViews)826        Printer.addView(std::move(CBView));827    }828 829    if (!runPipeline(*P))830      return 1;831 832    if (PrintJson) {833      Printer.printReport(JSONOutput);834    } else {835      Printer.printReport(TOF->os());836    }837 838    ++RegionIdx;839  }840 841  if (NonEmptyRegions == 0) {842    WithColor::error() << "no assembly instructions found.\n";843    return 1;844  }845 846  if (PrintJson)847    TOF->os() << formatv("{0:2}", json::Value(std::move(JSONOutput))) << "\n";848 849  TOF->keep();850  return 0;851}852