xref: /llvm-project/llvm/unittests/tools/llvm-mca/MCATestBase.cpp (revision 848bef5d8549cdc79bb0eb3c5a8e0495e432b577)
1 #include "MCATestBase.h"
2 #include "Views/SummaryView.h"
3 #include "llvm/MCA/CustomBehaviour.h"
4 #include "llvm/MCA/InstrBuilder.h"
5 #include "llvm/MCA/Pipeline.h"
6 #include "llvm/MCA/SourceMgr.h"
7 #include "llvm/MCA/View.h"
8 #include "llvm/Support/JSON.h"
9 #include "llvm/Support/WithColor.h"
10 #include <string>
11 
12 using namespace llvm;
13 using namespace mca;
14 
getLLVMTarget() const15 const Target *MCATestBase::getLLVMTarget() const {
16   std::string Error;
17   return TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
18 }
19 
getDefaultPipelineOptions()20 mca::PipelineOptions MCATestBase::getDefaultPipelineOptions() {
21   mca::PipelineOptions PO(/*MicroOpQueue=*/0, /*DecoderThroughput=*/0,
22                           /*DispatchWidth=*/0,
23                           /*RegisterFileSize=*/0,
24                           /*LoadQueueSize=*/0, /*StoreQueueSize=*/0,
25                           /*AssumeNoAlias=*/true,
26                           /*EnableBottleneckAnalysis=*/false);
27   return PO;
28 }
29 
SetUp()30 void MCATestBase::SetUp() {
31   TheTarget = getLLVMTarget();
32   ASSERT_NE(TheTarget, nullptr);
33 
34   StringRef TripleName = TheTriple.getTriple();
35 
36   STI.reset(TheTarget->createMCSubtargetInfo(TripleName, CPUName, MAttr));
37   ASSERT_TRUE(STI);
38   ASSERT_TRUE(STI->isCPUStringValid(CPUName));
39 
40   MRI.reset(TheTarget->createMCRegInfo(TripleName));
41   ASSERT_TRUE(MRI);
42 
43   auto MCOptions = getMCTargetOptions();
44   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
45   ASSERT_TRUE(MAI);
46 
47   Ctx = std::make_unique<MCContext>(TheTriple, MAI.get(), MRI.get(), STI.get());
48   MOFI.reset(TheTarget->createMCObjectFileInfo(*Ctx, /*PIC=*/false));
49   Ctx->setObjectFileInfo(MOFI.get());
50 
51   MCII.reset(TheTarget->createMCInstrInfo());
52   ASSERT_TRUE(MCII);
53 
54   MCIA.reset(TheTarget->createMCInstrAnalysis(MCII.get()));
55   ASSERT_TRUE(MCIA);
56 
57   IP.reset(TheTarget->createMCInstPrinter(TheTriple, /*AssemblerDialect=*/0,
58                                           *MAI, *MCII, *MRI));
59   ASSERT_TRUE(IP);
60 }
61 
runBaselineMCA(json::Object & Result,ArrayRef<MCInst> Insts,ArrayRef<mca::View * > Views,const mca::PipelineOptions * PO)62 Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef<MCInst> Insts,
63                                   ArrayRef<mca::View *> Views,
64                                   const mca::PipelineOptions *PO) {
65   mca::Context MCA(*MRI, *STI);
66 
67   // Default InstrumentManager
68   auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
69   mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, /*CallLatency=*/100);
70 
71   const SmallVector<mca::Instrument *> Instruments;
72   SmallVector<std::unique_ptr<mca::Instruction>> LoweredInsts;
73   for (const auto &MCI : Insts) {
74     Expected<std::unique_ptr<mca::Instruction>> Inst =
75         IB.createInstruction(MCI, Instruments);
76     if (!Inst) {
77       if (auto NewE =
78               handleErrors(Inst.takeError(),
79                            [this](const mca::InstructionError<MCInst> &IE) {
80                              std::string InstructionStr;
81                              raw_string_ostream SS(InstructionStr);
82                              WithColor::error() << IE.Message << '\n';
83                              IP->printInst(&IE.Inst, 0, "", *STI, SS);
84                              WithColor::note()
85                                  << "instruction: " << InstructionStr << '\n';
86                            })) {
87         // Default case.
88         return NewE;
89       }
90     } else {
91       LoweredInsts.emplace_back(std::move(Inst.get()));
92     }
93   }
94 
95   mca::CircularSourceMgr SM(LoweredInsts, /*Iterations=*/1);
96 
97   // Empty CustomBehaviour.
98   auto CB = std::make_unique<mca::CustomBehaviour>(*STI, SM, *MCII);
99 
100   mca::PipelineOptions ThePO = PO ? *PO : getDefaultPipelineOptions();
101   auto P = MCA.createDefaultPipeline(ThePO, SM, *CB);
102 
103   SmallVector<std::unique_ptr<mca::View>, 1> DefaultViews;
104   if (Views.empty()) {
105     // By default, we only add SummaryView.
106     auto SV = std::make_unique<SummaryView>(STI->getSchedModel(), Insts,
107                                             ThePO.DispatchWidth);
108     P->addEventListener(SV.get());
109     DefaultViews.emplace_back(std::move(SV));
110   } else {
111     for (auto *V : Views)
112       P->addEventListener(V);
113   }
114 
115   // Run the pipeline.
116   Expected<unsigned> Cycles = P->run();
117   if (!Cycles)
118     return Cycles.takeError();
119 
120   for (const auto *V : Views)
121     Result[V->getNameAsString()] = V->toJSON();
122   for (const auto &V : DefaultViews)
123     Result[V->getNameAsString()] = V->toJSON();
124 
125   return Error::success();
126 }
127