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 | |
15 | const Target *MCATestBase::getLLVMTarget() const { |
16 | std::string Error; |
17 | return TargetRegistry::lookupTarget(Triple: TheTriple.getTriple(), Error); |
18 | } |
19 | |
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 | |
30 | void MCATestBase::SetUp() { |
31 | TheTarget = getLLVMTarget(); |
32 | ASSERT_NE(TheTarget, nullptr); |
33 | |
34 | StringRef TripleName = TheTriple.getTriple(); |
35 | |
36 | STI.reset(p: TheTarget->createMCSubtargetInfo(TheTriple: TripleName, CPU: CPUName, Features: MAttr)); |
37 | ASSERT_TRUE(STI); |
38 | ASSERT_TRUE(STI->isCPUStringValid(CPUName)); |
39 | |
40 | MRI.reset(p: TheTarget->createMCRegInfo(TT: TripleName)); |
41 | ASSERT_TRUE(MRI); |
42 | |
43 | auto MCOptions = getMCTargetOptions(); |
44 | MAI.reset(p: TheTarget->createMCAsmInfo(MRI: *MRI, TheTriple: TripleName, Options: MCOptions)); |
45 | ASSERT_TRUE(MAI); |
46 | |
47 | Ctx = std::make_unique<MCContext>(args: TheTriple, args: MAI.get(), args: MRI.get(), args: STI.get()); |
48 | MOFI.reset(p: TheTarget->createMCObjectFileInfo(Ctx&: *Ctx, /*PIC=*/false)); |
49 | Ctx->setObjectFileInfo(MOFI.get()); |
50 | |
51 | MCII.reset(p: TheTarget->createMCInstrInfo()); |
52 | ASSERT_TRUE(MCII); |
53 | |
54 | MCIA.reset(p: TheTarget->createMCInstrAnalysis(Info: MCII.get())); |
55 | ASSERT_TRUE(MCIA); |
56 | |
57 | IP.reset(p: TheTarget->createMCInstPrinter(T: TheTriple, /*AssemblerDialect=*/SyntaxVariant: 0, |
58 | MAI: *MAI, MII: *MCII, MRI: *MRI)); |
59 | ASSERT_TRUE(IP); |
60 | } |
61 | |
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>(args&: *STI, args&: *MCII); |
69 | mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM); |
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, IVec: Instruments); |
76 | if (!Inst) { |
77 | if (auto NewE = |
78 | handleErrors(E: Inst.takeError(), |
79 | Hs: [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(MI: &IE.Inst, Address: 0, Annot: "" , STI: *STI, OS&: SS); |
84 | WithColor::note() |
85 | << "instruction: " << InstructionStr << '\n'; |
86 | })) { |
87 | // Default case. |
88 | return NewE; |
89 | } |
90 | } else { |
91 | LoweredInsts.emplace_back(Args: 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>(args&: *STI, args&: SM, args&: *MCII); |
99 | |
100 | mca::PipelineOptions ThePO = PO ? *PO : getDefaultPipelineOptions(); |
101 | auto P = MCA.createDefaultPipeline(Opts: ThePO, SrcMgr&: SM, CB&: *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>(args: STI->getSchedModel(), args&: Insts, |
107 | args&: ThePO.DispatchWidth); |
108 | P->addEventListener(Listener: SV.get()); |
109 | DefaultViews.emplace_back(Args: std::move(SV)); |
110 | } else { |
111 | for (auto *V : Views) |
112 | P->addEventListener(Listener: 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 | |