xref: /aosp_15_r20/external/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===----- HexagonShuffler.h - Instruction bundle shuffling ---------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This implements the shuffling of insns inside a bundle according to the
11*9880d681SAndroid Build Coastguard Worker // packet formation rules of the Hexagon ISA.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker 
15*9880d681SAndroid Build Coastguard Worker #ifndef HEXAGONSHUFFLER_H
16*9880d681SAndroid Build Coastguard Worker #define HEXAGONSHUFFLER_H
17*9880d681SAndroid Build Coastguard Worker 
18*9880d681SAndroid Build Coastguard Worker #include "Hexagon.h"
19*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/HexagonMCInstrInfo.h"
20*9880d681SAndroid Build Coastguard Worker 
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
24*9880d681SAndroid Build Coastguard Worker 
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker 
27*9880d681SAndroid Build Coastguard Worker namespace llvm {
28*9880d681SAndroid Build Coastguard Worker // Insn resources.
29*9880d681SAndroid Build Coastguard Worker class HexagonResource {
30*9880d681SAndroid Build Coastguard Worker   // Mask of the slots or units that may execute the insn and
31*9880d681SAndroid Build Coastguard Worker   // the weight or priority that the insn requires to be assigned a slot.
32*9880d681SAndroid Build Coastguard Worker   unsigned Slots, Weight;
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker public:
HexagonResource(unsigned s)35*9880d681SAndroid Build Coastguard Worker   HexagonResource(unsigned s) { setUnits(s); };
36*9880d681SAndroid Build Coastguard Worker 
setUnits(unsigned s)37*9880d681SAndroid Build Coastguard Worker   void setUnits(unsigned s) {
38*9880d681SAndroid Build Coastguard Worker     Slots = s & ~(~0U << HEXAGON_PACKET_SIZE);
39*9880d681SAndroid Build Coastguard Worker   };
40*9880d681SAndroid Build Coastguard Worker   unsigned setWeight(unsigned s);
41*9880d681SAndroid Build Coastguard Worker 
getUnits()42*9880d681SAndroid Build Coastguard Worker   unsigned getUnits() const { return (Slots); };
getWeight()43*9880d681SAndroid Build Coastguard Worker   unsigned getWeight() const { return (Weight); };
44*9880d681SAndroid Build Coastguard Worker 
45*9880d681SAndroid Build Coastguard Worker   // Check if the resources are in ascending slot order.
lessUnits(const HexagonResource & A,const HexagonResource & B)46*9880d681SAndroid Build Coastguard Worker   static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
47*9880d681SAndroid Build Coastguard Worker     return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
48*9880d681SAndroid Build Coastguard Worker   };
49*9880d681SAndroid Build Coastguard Worker   // Check if the resources are in ascending weight order.
lessWeight(const HexagonResource & A,const HexagonResource & B)50*9880d681SAndroid Build Coastguard Worker   static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
51*9880d681SAndroid Build Coastguard Worker     return (A.getWeight() < B.getWeight());
52*9880d681SAndroid Build Coastguard Worker   };
53*9880d681SAndroid Build Coastguard Worker };
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker // HVX insn resources.
56*9880d681SAndroid Build Coastguard Worker class HexagonCVIResource : public HexagonResource {
57*9880d681SAndroid Build Coastguard Worker public:
58*9880d681SAndroid Build Coastguard Worker   typedef std::pair<unsigned, unsigned> UnitsAndLanes;
59*9880d681SAndroid Build Coastguard Worker   typedef llvm::DenseMap<unsigned, UnitsAndLanes> TypeUnitsAndLanes;
60*9880d681SAndroid Build Coastguard Worker 
61*9880d681SAndroid Build Coastguard Worker private:
62*9880d681SAndroid Build Coastguard Worker   // Available HVX slots.
63*9880d681SAndroid Build Coastguard Worker   enum {
64*9880d681SAndroid Build Coastguard Worker     CVI_NONE = 0,
65*9880d681SAndroid Build Coastguard Worker     CVI_XLANE = 1 << 0,
66*9880d681SAndroid Build Coastguard Worker     CVI_SHIFT = 1 << 1,
67*9880d681SAndroid Build Coastguard Worker     CVI_MPY0 = 1 << 2,
68*9880d681SAndroid Build Coastguard Worker     CVI_MPY1 = 1 << 3
69*9880d681SAndroid Build Coastguard Worker   };
70*9880d681SAndroid Build Coastguard Worker 
71*9880d681SAndroid Build Coastguard Worker   TypeUnitsAndLanes *TUL;
72*9880d681SAndroid Build Coastguard Worker 
73*9880d681SAndroid Build Coastguard Worker   // Count of adjacent slots that the insn requires to be executed.
74*9880d681SAndroid Build Coastguard Worker   unsigned Lanes;
75*9880d681SAndroid Build Coastguard Worker   // Flag whether the insn is a load or a store.
76*9880d681SAndroid Build Coastguard Worker   bool Load, Store;
77*9880d681SAndroid Build Coastguard Worker   // Flag whether the HVX resources are valid.
78*9880d681SAndroid Build Coastguard Worker   bool Valid;
79*9880d681SAndroid Build Coastguard Worker 
setLanes(unsigned l)80*9880d681SAndroid Build Coastguard Worker   void setLanes(unsigned l) { Lanes = l; };
81*9880d681SAndroid Build Coastguard Worker   void setLoad(bool f = true) { Load = f; };
82*9880d681SAndroid Build Coastguard Worker   void setStore(bool f = true) { Store = f; };
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker public:
85*9880d681SAndroid Build Coastguard Worker   HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII,
86*9880d681SAndroid Build Coastguard Worker                      unsigned s, MCInst const *id);
87*9880d681SAndroid Build Coastguard Worker   static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
88*9880d681SAndroid Build Coastguard Worker 
isValid()89*9880d681SAndroid Build Coastguard Worker   bool isValid() const { return (Valid); };
getLanes()90*9880d681SAndroid Build Coastguard Worker   unsigned getLanes() const { return (Lanes); };
mayLoad()91*9880d681SAndroid Build Coastguard Worker   bool mayLoad() const { return (Load); };
mayStore()92*9880d681SAndroid Build Coastguard Worker   bool mayStore() const { return (Store); };
93*9880d681SAndroid Build Coastguard Worker };
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker // Handle to an insn used by the shuffling algorithm.
96*9880d681SAndroid Build Coastguard Worker class HexagonInstr {
97*9880d681SAndroid Build Coastguard Worker   friend class HexagonShuffler;
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker   MCInst const *ID;
100*9880d681SAndroid Build Coastguard Worker   MCInst const *Extender;
101*9880d681SAndroid Build Coastguard Worker   HexagonResource Core;
102*9880d681SAndroid Build Coastguard Worker   HexagonCVIResource CVI;
103*9880d681SAndroid Build Coastguard Worker   bool SoloException;
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker public:
106*9880d681SAndroid Build Coastguard Worker   HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
107*9880d681SAndroid Build Coastguard Worker                MCInstrInfo const &MCII, MCInst const *id,
108*9880d681SAndroid Build Coastguard Worker                MCInst const *Extender, unsigned s, bool x = false)
ID(id)109*9880d681SAndroid Build Coastguard Worker       : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id),
110*9880d681SAndroid Build Coastguard Worker         SoloException(x) {};
111*9880d681SAndroid Build Coastguard Worker 
getDesc()112*9880d681SAndroid Build Coastguard Worker   MCInst const *getDesc() const { return (ID); };
113*9880d681SAndroid Build Coastguard Worker 
getExtender()114*9880d681SAndroid Build Coastguard Worker   MCInst const *getExtender() const { return Extender; }
115*9880d681SAndroid Build Coastguard Worker 
isSoloException()116*9880d681SAndroid Build Coastguard Worker   unsigned isSoloException() const { return (SoloException); };
117*9880d681SAndroid Build Coastguard Worker 
118*9880d681SAndroid Build Coastguard Worker   // Check if the handles are in ascending order for shuffling purposes.
119*9880d681SAndroid Build Coastguard Worker   bool operator<(const HexagonInstr &B) const {
120*9880d681SAndroid Build Coastguard Worker     return (HexagonResource::lessWeight(B.Core, Core));
121*9880d681SAndroid Build Coastguard Worker   };
122*9880d681SAndroid Build Coastguard Worker   // Check if the handles are in ascending order by core slots.
lessCore(const HexagonInstr & A,const HexagonInstr & B)123*9880d681SAndroid Build Coastguard Worker   static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
124*9880d681SAndroid Build Coastguard Worker     return (HexagonResource::lessUnits(A.Core, B.Core));
125*9880d681SAndroid Build Coastguard Worker   };
126*9880d681SAndroid Build Coastguard Worker   // Check if the handles are in ascending order by HVX slots.
lessCVI(const HexagonInstr & A,const HexagonInstr & B)127*9880d681SAndroid Build Coastguard Worker   static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
128*9880d681SAndroid Build Coastguard Worker     return (HexagonResource::lessUnits(A.CVI, B.CVI));
129*9880d681SAndroid Build Coastguard Worker   };
130*9880d681SAndroid Build Coastguard Worker };
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker // Bundle shuffler.
133*9880d681SAndroid Build Coastguard Worker class HexagonShuffler {
134*9880d681SAndroid Build Coastguard Worker   typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>
135*9880d681SAndroid Build Coastguard Worker       HexagonPacket;
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker   // Insn handles in a bundle.
138*9880d681SAndroid Build Coastguard Worker   HexagonPacket Packet;
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker   // Shuffling error code.
141*9880d681SAndroid Build Coastguard Worker   unsigned Error;
142*9880d681SAndroid Build Coastguard Worker 
143*9880d681SAndroid Build Coastguard Worker   HexagonCVIResource::TypeUnitsAndLanes TUL;
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker protected:
146*9880d681SAndroid Build Coastguard Worker   int64_t BundleFlags;
147*9880d681SAndroid Build Coastguard Worker   MCInstrInfo const &MCII;
148*9880d681SAndroid Build Coastguard Worker   MCSubtargetInfo const &STI;
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker public:
151*9880d681SAndroid Build Coastguard Worker   typedef HexagonPacket::iterator iterator;
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   enum {
154*9880d681SAndroid Build Coastguard Worker     SHUFFLE_SUCCESS = 0,    ///< Successful operation.
155*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_INVALID,  ///< Invalid bundle.
156*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_STORES,   ///< No free slots for store insns.
157*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_LOADS,    ///< No free slots for load insns.
158*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.
159*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_NOSLOTS,  ///< No free slots for other insns.
160*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_SLOTS,    ///< Over-subscribed slots.
161*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_ERRATA2, ///< Errata violation (v60).
162*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_STORE_LOAD_CONFLICT, ///< store/load conflict
163*9880d681SAndroid Build Coastguard Worker     SHUFFLE_ERROR_UNKNOWN   ///< Unknown error.
164*9880d681SAndroid Build Coastguard Worker   };
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker   explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker   // Reset to initial state.
169*9880d681SAndroid Build Coastguard Worker   void reset();
170*9880d681SAndroid Build Coastguard Worker   // Check if the bundle may be validly shuffled.
171*9880d681SAndroid Build Coastguard Worker   bool check();
172*9880d681SAndroid Build Coastguard Worker   // Reorder the insn handles in the bundle.
173*9880d681SAndroid Build Coastguard Worker   bool shuffle();
174*9880d681SAndroid Build Coastguard Worker 
size()175*9880d681SAndroid Build Coastguard Worker   unsigned size() const { return (Packet.size()); };
176*9880d681SAndroid Build Coastguard Worker 
begin()177*9880d681SAndroid Build Coastguard Worker   iterator begin() { return (Packet.begin()); };
end()178*9880d681SAndroid Build Coastguard Worker   iterator end() { return (Packet.end()); };
179*9880d681SAndroid Build Coastguard Worker 
180*9880d681SAndroid Build Coastguard Worker   // Add insn handle to the bundle .
181*9880d681SAndroid Build Coastguard Worker   void append(MCInst const *ID, MCInst const *Extender, unsigned S,
182*9880d681SAndroid Build Coastguard Worker               bool X = false);
183*9880d681SAndroid Build Coastguard Worker 
184*9880d681SAndroid Build Coastguard Worker   // Return the error code for the last check or shuffling of the bundle.
setError(unsigned Err)185*9880d681SAndroid Build Coastguard Worker   void setError(unsigned Err) { Error = Err; };
getError()186*9880d681SAndroid Build Coastguard Worker   unsigned getError() const { return (Error); };
187*9880d681SAndroid Build Coastguard Worker };
188*9880d681SAndroid Build Coastguard Worker }
189*9880d681SAndroid Build Coastguard Worker 
190*9880d681SAndroid Build Coastguard Worker #endif // HEXAGONSHUFFLER_H
191