1 //===---------------------- CustomBehaviour.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 /// This file defines the base class CustomBehaviour which can be inherited from
11 /// by specific targets (ex. llvm/tools/llvm-mca/lib/X86CustomBehaviour.h).
12 /// CustomBehaviour is designed to enforce custom behaviour and dependencies
13 /// within the llvm-mca pipeline simulation that llvm-mca isn't already capable
14 /// of extracting from the Scheduling Models.
15 ///
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_MCA_CUSTOMBEHAVIOUR_H
19 #define LLVM_MCA_CUSTOMBEHAVIOUR_H
20 
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MCA/SourceMgr.h"
26 #include "llvm/MCA/View.h"
27 
28 namespace llvm {
29 namespace mca {
30 
31 /// Class which can be overriden by targets to modify the
32 /// mca::Instruction objects before the pipeline starts.
33 /// A common usage of this class is to add immediate operands to certain
34 /// instructions or to remove Defs/Uses from an instruction where the
35 /// schedulinng model is incorrect.
36 class InstrPostProcess {
37 protected:
38   const MCSubtargetInfo &STI;
39   const MCInstrInfo &MCII;
40 
41 public:
42   InstrPostProcess(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
43       : STI(STI), MCII(MCII) {}
44 
45   virtual ~InstrPostProcess() = default;
46 
47   /// This method can be overriden by targets to modify the mca::Instruction
48   /// object after it has been lowered from the MCInst.
49   /// This is generally a less disruptive alternative to modifying the
50   /// scheduling model.
51   virtual void postProcessInstruction(std::unique_ptr<Instruction> &Inst,
52                                       const MCInst &MCI) {}
53 
54   // The resetState() method gets invoked at the beginning of each code region
55   // so that targets that override this function can clear any state that they
56   // have left from the previous code region.
57   virtual void resetState() {}
58 };
59 
60 /// Class which can be overriden by targets to enforce instruction
61 /// dependencies and behaviours that aren't expressed well enough
62 /// within the scheduling model for mca to automatically simulate
63 /// them properly.
64 /// If you implement this class for your target, make sure to also implement
65 /// a target specific InstrPostProcess class as well.
66 class CustomBehaviour {
67 protected:
68   const MCSubtargetInfo &STI;
69   const mca::SourceMgr &SrcMgr;
70   const MCInstrInfo &MCII;
71 
72 public:
73   CustomBehaviour(const MCSubtargetInfo &STI, const mca::SourceMgr &SrcMgr,
74                   const MCInstrInfo &MCII)
75       : STI(STI), SrcMgr(SrcMgr), MCII(MCII) {}
76 
77   virtual ~CustomBehaviour();
78 
79   /// Before the llvm-mca pipeline dispatches an instruction, it first checks
80   /// for any register or resource dependencies / hazards. If it doesn't find
81   /// any, this method will be invoked to determine if there are any custom
82   /// hazards that the instruction needs to wait for.
83   /// The return value of this method is the number of cycles that the
84   /// instruction needs to wait for.
85   /// It's safe to underestimate the number of cycles to wait for since these
86   /// checks will be invoked again before the intruction gets dispatched.
87   /// However, it's not safe (accurate) to overestimate the number of cycles
88   /// to wait for since the instruction will wait for AT LEAST that number of
89   /// cycles before attempting to be dispatched again.
90   virtual unsigned checkCustomHazard(ArrayRef<InstRef> IssuedInst,
91                                      const InstRef &IR);
92 
93   // Functions that target CBs can override to return a list of
94   // target specific Views that need to live within /lib/Target/ so that
95   // they can benefit from the target CB or from backend functionality that is
96   // not already exposed through MC-layer classes. Keep in mind that how this
97   // function is used is that the function is called within llvm-mca.cpp and
98   // then each unique_ptr<View> is passed into the PipelinePrinter::addView()
99   // function. This function will then std::move the View into its own vector of
100   // Views. So any CB that overrides this function needs to make sure that they
101   // are not relying on the current address or reference of the View
102   // unique_ptrs. If you do need the CB and View to be able to communicate with
103   // each other, consider giving the View a reference or pointer to the CB when
104   // the View is constructed. Then the View can query the CB for information
105   // when it needs it.
106   /// Return a vector of Views that will be added before all other Views.
107   virtual std::vector<std::unique_ptr<View>>
108   getStartViews(llvm::MCInstPrinter &IP, llvm::ArrayRef<llvm::MCInst> Insts);
109   /// Return a vector of Views that will be added after the InstructionInfoView.
110   virtual std::vector<std::unique_ptr<View>>
111   getPostInstrInfoViews(llvm::MCInstPrinter &IP,
112                         llvm::ArrayRef<llvm::MCInst> Insts);
113   /// Return a vector of Views that will be added after all other Views.
114   virtual std::vector<std::unique_ptr<View>>
115   getEndViews(llvm::MCInstPrinter &IP, llvm::ArrayRef<llvm::MCInst> Insts);
116 };
117 
118 class Instrument {
119   /// The description of Instrument kind
120   const StringRef Desc;
121 
122   /// The instrumentation data
123   const StringRef Data;
124 
125 public:
126   Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) {}
127 
128   Instrument() : Instrument("", "") {}
129 
130   virtual ~Instrument() = default;
131 
132   StringRef getDesc() const { return Desc; }
133   StringRef getData() const { return Data; }
134 };
135 
136 using UniqueInstrument = std::unique_ptr<Instrument>;
137 
138 /// This class allows targets to optionally customize the logic that resolves
139 /// scheduling class IDs. Targets can use information encoded in Instrument
140 /// objects to make more informed scheduling decisions.
141 class InstrumentManager {
142 protected:
143   const MCSubtargetInfo &STI;
144   const MCInstrInfo &MCII;
145 
146 public:
147   InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
148       : STI(STI), MCII(MCII) {}
149 
150   virtual ~InstrumentManager() = default;
151 
152   /// Returns true if llvm-mca should ignore instruments.
153   virtual bool shouldIgnoreInstruments() const { return true; }
154 
155   // Returns true if this supports processing Instrument with
156   // Instrument.Desc equal to Type
157   virtual bool supportsInstrumentType(StringRef Type) const { return false; }
158 
159   /// Allocate an Instrument, and return a unique pointer to it. This function
160   /// may be useful to create instruments coming from comments in the assembly.
161   /// See createInstruments to create Instruments from MCInst
162   virtual UniqueInstrument createInstrument(StringRef Desc, StringRef Data);
163 
164   /// Return a list of unique pointers to Instruments, where each Instrument
165   /// is allocated by this function. See createInstrument to create Instrument
166   /// from a description and data.
167   virtual SmallVector<UniqueInstrument> createInstruments(const MCInst &Inst);
168 
169   /// Given an MCInst and a vector of Instrument, a target can
170   /// return a SchedClassID. This can be used by a subtarget to return a
171   /// PseudoInstruction SchedClassID instead of the one that belongs to the
172   /// BaseInstruction This can be useful when a BaseInstruction does not convey
173   /// the correct scheduling information without additional data. By default,
174   /// it returns the SchedClassID that belongs to MCI.
175   virtual unsigned getSchedClassID(const MCInstrInfo &MCII, const MCInst &MCI,
176                                    const SmallVector<Instrument *> &IVec) const;
177 };
178 
179 } // namespace mca
180 } // namespace llvm
181 
182 #endif /* LLVM_MCA_CUSTOMBEHAVIOUR_H */
183