#include "MCATestBase.h" #include "Views/SummaryView.h" #include "llvm/MCA/CustomBehaviour.h" #include "llvm/MCA/InstrBuilder.h" #include "llvm/MCA/Pipeline.h" #include "llvm/MCA/SourceMgr.h" #include "llvm/MCA/View.h" #include "llvm/Support/JSON.h" #include "llvm/Support/WithColor.h" #include using namespace llvm; using namespace mca; const Target *MCATestBase::getLLVMTarget() const { std::string Error; return TargetRegistry::lookupTarget(TheTriple.getTriple(), Error); } mca::PipelineOptions MCATestBase::getDefaultPipelineOptions() { mca::PipelineOptions PO(/*MicroOpQueue=*/0, /*DecoderThroughput=*/0, /*DispatchWidth=*/0, /*RegisterFileSize=*/0, /*LoadQueueSize=*/0, /*StoreQueueSize=*/0, /*AssumeNoAlias=*/true, /*EnableBottleneckAnalysis=*/false); return PO; } void MCATestBase::SetUp() { TheTarget = getLLVMTarget(); ASSERT_NE(TheTarget, nullptr); StringRef TripleName = TheTriple.getTriple(); STI.reset(TheTarget->createMCSubtargetInfo(TripleName, CPUName, MAttr)); ASSERT_TRUE(STI); ASSERT_TRUE(STI->isCPUStringValid(CPUName)); MRI.reset(TheTarget->createMCRegInfo(TripleName)); ASSERT_TRUE(MRI); auto MCOptions = getMCTargetOptions(); MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); ASSERT_TRUE(MAI); Ctx = std::make_unique(TheTriple, MAI.get(), MRI.get(), STI.get()); MOFI.reset(TheTarget->createMCObjectFileInfo(*Ctx, /*PIC=*/false)); Ctx->setObjectFileInfo(MOFI.get()); MCII.reset(TheTarget->createMCInstrInfo()); ASSERT_TRUE(MCII); MCIA.reset(TheTarget->createMCInstrAnalysis(MCII.get())); ASSERT_TRUE(MCIA); IP.reset(TheTarget->createMCInstPrinter(TheTriple, /*AssemblerDialect=*/0, *MAI, *MCII, *MRI)); ASSERT_TRUE(IP); } Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views, const mca::PipelineOptions *PO) { mca::Context MCA(*MRI, *STI); // Default InstrumentManager auto IM = std::make_unique(*STI, *MCII); mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, /*CallLatency=*/100); const SmallVector Instruments; SmallVector> LoweredInsts; for (const auto &MCI : Insts) { Expected> Inst = IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors(Inst.takeError(), [this](const mca::InstructionError &IE) { std::string InstructionStr; raw_string_ostream SS(InstructionStr); WithColor::error() << IE.Message << '\n'; IP->printInst(&IE.Inst, 0, "", *STI, SS); WithColor::note() << "instruction: " << InstructionStr << '\n'; })) { // Default case. return NewE; } } else { LoweredInsts.emplace_back(std::move(Inst.get())); } } mca::CircularSourceMgr SM(LoweredInsts, /*Iterations=*/1); // Empty CustomBehaviour. auto CB = std::make_unique(*STI, SM, *MCII); mca::PipelineOptions ThePO = PO ? *PO : getDefaultPipelineOptions(); auto P = MCA.createDefaultPipeline(ThePO, SM, *CB); SmallVector, 1> DefaultViews; if (Views.empty()) { // By default, we only add SummaryView. auto SV = std::make_unique(STI->getSchedModel(), Insts, ThePO.DispatchWidth); P->addEventListener(SV.get()); DefaultViews.emplace_back(std::move(SV)); } else { for (auto *V : Views) P->addEventListener(V); } // Run the pipeline. Expected Cycles = P->run(); if (!Cycles) return Cycles.takeError(); for (const auto *V : Views) Result[V->getNameAsString()] = V->toJSON(); for (const auto &V : DefaultViews) Result[V->getNameAsString()] = V->toJSON(); return Error::success(); }