1 //===--------------------- InstrBuilder.h -----------------------*- 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 /// \file
9 ///
10 /// A builder class for instructions that are statically analyzed by llvm-mca.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_MCA_INSTRBUILDER_H
15 #define LLVM_MCA_INSTRBUILDER_H
16 
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/MC/MCInstrAnalysis.h"
19 #include "llvm/MC/MCInstrInfo.h"
20 #include "llvm/MC/MCRegisterInfo.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/MCA/CustomBehaviour.h"
23 #include "llvm/MCA/Instruction.h"
24 #include "llvm/MCA/Support.h"
25 #include "llvm/Support/Error.h"
26 
27 namespace llvm {
28 namespace mca {
29 
30 class RecycledInstErr : public ErrorInfo<RecycledInstErr> {
31   Instruction *RecycledInst;
32 
33 public:
34   static char ID;
35 
36   explicit RecycledInstErr(Instruction *Inst) : RecycledInst(Inst) {}
37   // Always need to carry an Instruction
38   RecycledInstErr() = delete;
39 
40   Instruction *getInst() const { return RecycledInst; }
41 
42   void log(raw_ostream &OS) const override {
43     OS << "Instruction is recycled\n";
44   }
45 
46   std::error_code convertToErrorCode() const override {
47     return llvm::inconvertibleErrorCode();
48   }
49 };
50 
51 /// A builder class that knows how to construct Instruction objects.
52 ///
53 /// Every llvm-mca Instruction is described by an object of class InstrDesc.
54 /// An InstrDesc describes which registers are read/written by the instruction,
55 /// as well as the instruction latency and hardware resources consumed.
56 ///
57 /// This class is used by the tool to construct Instructions and instruction
58 /// descriptors (i.e. InstrDesc objects).
59 /// Information from the machine scheduling model is used to identify processor
60 /// resources that are consumed by an instruction.
61 class InstrBuilder {
62   const MCSubtargetInfo &STI;
63   const MCInstrInfo &MCII;
64   const MCRegisterInfo &MRI;
65   const MCInstrAnalysis *MCIA;
66   const InstrumentManager &IM;
67   SmallVector<uint64_t, 8> ProcResourceMasks;
68 
69   // Key is the MCI.Opcode and SchedClassID the describe the value InstrDesc
70   DenseMap<std::pair<unsigned short, unsigned>,
71            std::unique_ptr<const InstrDesc>>
72       Descriptors;
73 
74   // Key is the MCIInst and SchedClassID the describe the value InstrDesc
75   DenseMap<std::pair<const MCInst *, unsigned>,
76            std::unique_ptr<const InstrDesc>>
77       VariantDescriptors;
78 
79   bool FirstCallInst;
80   bool FirstReturnInst;
81 
82   using InstRecycleCallback =
83       llvm::function_ref<Instruction *(const InstrDesc &)>;
84   InstRecycleCallback InstRecycleCB;
85 
86   Expected<const InstrDesc &>
87   createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec);
88   Expected<const InstrDesc &>
89   getOrCreateInstrDesc(const MCInst &MCI,
90                        const SmallVector<Instrument *> &IVec);
91 
92   InstrBuilder(const InstrBuilder &) = delete;
93   InstrBuilder &operator=(const InstrBuilder &) = delete;
94 
95   void populateWrites(InstrDesc &ID, const MCInst &MCI, unsigned SchedClassID);
96   void populateReads(InstrDesc &ID, const MCInst &MCI, unsigned SchedClassID);
97   Error verifyInstrDesc(const InstrDesc &ID, const MCInst &MCI) const;
98 
99 public:
100   InstrBuilder(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
101                const MCRegisterInfo &RI, const MCInstrAnalysis *IA,
102                const InstrumentManager &IM);
103 
104   void clear() {
105     Descriptors.clear();
106     VariantDescriptors.clear();
107     FirstCallInst = true;
108     FirstReturnInst = true;
109   }
110 
111   /// Set a callback which is invoked to retrieve a recycled mca::Instruction
112   /// or null if there isn't any.
113   void setInstRecycleCallback(InstRecycleCallback CB) { InstRecycleCB = CB; }
114 
115   Expected<std::unique_ptr<Instruction>>
116   createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &IVec);
117 };
118 } // namespace mca
119 } // namespace llvm
120 
121 #endif // LLVM_MCA_INSTRBUILDER_H
122