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