/src/keystone/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
Line | Count | Source |
1 | | //===----- HexagonShuffler.cpp - 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 | | #define DEBUG_TYPE "hexagon-shuffle" |
16 | | |
17 | | #include <algorithm> |
18 | | #include <utility> |
19 | | #include "Hexagon.h" |
20 | | #include "MCTargetDesc/HexagonBaseInfo.h" |
21 | | #include "MCTargetDesc/HexagonMCTargetDesc.h" |
22 | | #include "MCTargetDesc/HexagonMCInstrInfo.h" |
23 | | #include "HexagonShuffler.h" |
24 | | #include "llvm/Support/Debug.h" |
25 | | #include "llvm/Support/MathExtras.h" |
26 | | #include "llvm/Support/raw_ostream.h" |
27 | | |
28 | | using namespace llvm_ks; |
29 | | |
30 | | namespace { |
31 | | // Insn shuffling priority. |
32 | | class HexagonBid { |
33 | | // The priority is directly proportional to how restricted the insn is based |
34 | | // on its flexibility to run on the available slots. So, the fewer slots it |
35 | | // may run on, the higher its priority. |
36 | | enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15. |
37 | | unsigned Bid; |
38 | | |
39 | | public: |
40 | 52.0k | HexagonBid() : Bid(0){}; |
41 | 15.8k | HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }; |
42 | | |
43 | | // Check if the insn priority is overflowed. |
44 | 15.8k | bool isSold() const { return (Bid >= MAX); }; |
45 | | |
46 | 15.8k | HexagonBid &operator+=(const HexagonBid &B) { |
47 | 15.8k | Bid += B.Bid; |
48 | 15.8k | return *this; |
49 | 15.8k | }; |
50 | | }; |
51 | | |
52 | | // Slot shuffling allocation. |
53 | | class HexagonUnitAuction { |
54 | | HexagonBid Scores[HEXAGON_PACKET_SIZE]; |
55 | | // Mask indicating which slot is unavailable. |
56 | | unsigned isSold : HEXAGON_PACKET_SIZE; |
57 | | |
58 | | public: |
59 | 13.0k | HexagonUnitAuction() : isSold(0){}; |
60 | | |
61 | | // Allocate slots. |
62 | 6.83k | bool bid(unsigned B) { |
63 | | // Exclude already auctioned slots from the bid. |
64 | 6.83k | unsigned b = B & ~isSold; |
65 | 6.83k | if (b) { |
66 | 33.8k | for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i) |
67 | 27.0k | if (b & (1 << i)) { |
68 | | // Request candidate slots. |
69 | 15.8k | Scores[i] += HexagonBid(b); |
70 | 15.8k | isSold |= Scores[i].isSold() << i; |
71 | 15.8k | } |
72 | 6.77k | return true; |
73 | 0 | ; |
74 | 0 | } else |
75 | | // Error if the desired slots are already full. |
76 | 66 | return false; |
77 | 6.83k | }; |
78 | | }; |
79 | | } // end anonymous namespace |
80 | | |
81 | 149 | unsigned HexagonResource::setWeight(unsigned s) { |
82 | 149 | const unsigned SlotWeight = 8; |
83 | 149 | const unsigned MaskWeight = SlotWeight - 1; |
84 | 149 | bool Key = (1 << s) & getUnits(); |
85 | | |
86 | | // TODO: Improve this API so that we can prevent misuse statically. |
87 | 149 | assert(SlotWeight * s < 32 && "Argument to setWeight too large."); |
88 | | |
89 | | // Calculate relative weight of the insn for the given slot, weighing it the |
90 | | // heavier the more restrictive the insn is and the lowest the slots that the |
91 | | // insn may be executed in. |
92 | 149 | Weight = |
93 | 149 | (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation(getUnits())) |
94 | 149 | << countTrailingZeros(getUnits())); |
95 | 149 | return (Weight); |
96 | 149 | } |
97 | | |
98 | 15.1k | void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) { |
99 | 15.1k | (*TUL)[HexagonII::TypeCVI_VA] = |
100 | 15.1k | UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); |
101 | 15.1k | (*TUL)[HexagonII::TypeCVI_VA_DV] = UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2); |
102 | 15.1k | (*TUL)[HexagonII::TypeCVI_VX] = UnitsAndLanes(CVI_MPY0 | CVI_MPY1, 1); |
103 | 15.1k | (*TUL)[HexagonII::TypeCVI_VX_DV] = UnitsAndLanes(CVI_MPY0, 2); |
104 | 15.1k | (*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1); |
105 | 15.1k | (*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2); |
106 | 15.1k | (*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1); |
107 | 15.1k | (*TUL)[HexagonII::TypeCVI_VINLANESAT] = UnitsAndLanes(CVI_SHIFT, 1); |
108 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_LD] = |
109 | 15.1k | UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); |
110 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_TMP_LD] = UnitsAndLanes(CVI_NONE, 0); |
111 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_CUR_LD] = |
112 | 15.1k | UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); |
113 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_VP_LDU] = UnitsAndLanes(CVI_XLANE, 1); |
114 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_ST] = |
115 | 15.1k | UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); |
116 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0); |
117 | 15.1k | (*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1); |
118 | 15.1k | (*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4); |
119 | 15.1k | } |
120 | | |
121 | | HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL, |
122 | | MCInstrInfo const &MCII, unsigned s, |
123 | | MCInst const *id) |
124 | 18.2k | : HexagonResource(s), TUL(TUL) { |
125 | 18.2k | unsigned T = HexagonMCInstrInfo::getType(MCII, *id); |
126 | | |
127 | 18.2k | if (TUL->count(T)) { |
128 | | // For an HVX insn. |
129 | 78 | Valid = true; |
130 | 78 | setUnits((*TUL)[T].first); |
131 | 78 | setLanes((*TUL)[T].second); |
132 | 78 | setLoad(HexagonMCInstrInfo::getDesc(MCII, *id).mayLoad()); |
133 | 78 | setStore(HexagonMCInstrInfo::getDesc(MCII, *id).mayStore()); |
134 | 18.1k | } else { |
135 | | // For core insns. |
136 | 18.1k | Valid = false; |
137 | 18.1k | setUnits(0); |
138 | 18.1k | setLanes(0); |
139 | 18.1k | setLoad(false); |
140 | 18.1k | setStore(false); |
141 | 18.1k | } |
142 | 18.2k | } |
143 | | |
144 | | HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII, |
145 | | MCSubtargetInfo const &STI) |
146 | 15.1k | : MCII(MCII), STI(STI) { |
147 | 15.1k | reset(); |
148 | 15.1k | HexagonCVIResource::SetupTUL(&TUL, STI.getCPU()); |
149 | 15.1k | } |
150 | | |
151 | 15.1k | void HexagonShuffler::reset() { |
152 | 15.1k | Packet.clear(); |
153 | 15.1k | BundleFlags = 0; |
154 | 15.1k | Error = SHUFFLE_SUCCESS; |
155 | 15.1k | } |
156 | | |
157 | | void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender, |
158 | 18.2k | unsigned S, bool X) { |
159 | 18.2k | HexagonInstr PI(&TUL, MCII, ID, Extender, S, X); |
160 | | |
161 | 18.2k | Packet.push_back(PI); |
162 | 18.2k | } |
163 | | |
164 | | /// Check that the packet is legal and enforce relative insn order. |
165 | 6.54k | bool HexagonShuffler::check() { |
166 | | // Descriptive slot masks. |
167 | 6.54k | const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2, |
168 | 6.54k | slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4, |
169 | 6.54k | slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1; |
170 | | // Highest slots for branches and stores used to keep their original order. |
171 | 6.54k | unsigned slotJump = slotFirstJump; |
172 | 6.54k | unsigned slotLoadStore = slotFirstLoadStore; |
173 | | // Number of branches, solo branches, indirect branches. |
174 | 6.54k | unsigned jumps = 0, jump1 = 0, jumpr = 0; |
175 | | // Number of memory operations, loads, solo loads, stores, solo stores, single |
176 | | // stores. |
177 | 6.54k | unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0; |
178 | | // Number of HVX loads, HVX stores. |
179 | 6.54k | unsigned CVIloads = 0, CVIstores = 0; |
180 | | // Number of duplex insns, solo insns. |
181 | 6.54k | unsigned duplex = 0, solo = 0; |
182 | | // Number of insns restricting other insns in the packet to A and X types, |
183 | | // which is neither A or X types. |
184 | 6.54k | unsigned onlyAX = 0, neitherAnorX = 0; |
185 | | // Number of insns restricting other insns in slot #1 to A type. |
186 | 6.54k | unsigned onlyAin1 = 0; |
187 | | // Number of insns restricting any insn in slot #1, except A2_nop. |
188 | 6.54k | unsigned onlyNo1 = 0; |
189 | 6.54k | unsigned xtypeFloat = 0; |
190 | 6.54k | unsigned pSlot3Cnt = 0; |
191 | 6.54k | iterator slot3ISJ = end(); |
192 | | |
193 | | // Collect information from the insns in the packet. |
194 | 16.2k | for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { |
195 | 9.65k | MCInst const *ID = ISJ->getDesc(); |
196 | | |
197 | 9.65k | if (HexagonMCInstrInfo::isSolo(MCII, *ID)) |
198 | 0 | solo += !ISJ->isSoloException(); |
199 | 9.65k | else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID)) |
200 | 0 | onlyAX += !ISJ->isSoloException(); |
201 | 9.65k | else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID)) |
202 | 0 | onlyAin1 += !ISJ->isSoloException(); |
203 | 9.65k | if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 && |
204 | 5.43k | HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE) |
205 | 4.62k | ++neitherAnorX; |
206 | 9.65k | if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) { |
207 | 0 | ++pSlot3Cnt; |
208 | 0 | slot3ISJ = ISJ; |
209 | 0 | } |
210 | | |
211 | 9.65k | switch (HexagonMCInstrInfo::getType(MCII, *ID)) { |
212 | 808 | case HexagonII::TypeXTYPE: |
213 | 808 | if (HexagonMCInstrInfo::isFloat(MCII, *ID)) |
214 | 0 | ++xtypeFloat; |
215 | 808 | break; |
216 | 0 | case HexagonII::TypeJR: |
217 | 0 | ++jumpr; |
218 | | // Fall-through. |
219 | 3.78k | case HexagonII::TypeJ: |
220 | 3.78k | ++jumps; |
221 | 3.78k | break; |
222 | 0 | case HexagonII::TypeCVI_VM_VP_LDU: |
223 | 0 | ++onlyNo1; |
224 | 0 | case HexagonII::TypeCVI_VM_LD: |
225 | 0 | case HexagonII::TypeCVI_VM_TMP_LD: |
226 | 0 | case HexagonII::TypeCVI_VM_CUR_LD: |
227 | 0 | ++CVIloads; |
228 | 0 | case HexagonII::TypeLD: |
229 | 0 | ++loads; |
230 | 0 | ++memory; |
231 | 0 | if (ISJ->Core.getUnits() == slotSingleLoad) |
232 | 0 | ++load0; |
233 | 0 | if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn()) |
234 | 0 | ++jumps, ++jump1; // DEALLOC_RETURN is of type LD. |
235 | 0 | break; |
236 | 0 | case HexagonII::TypeCVI_VM_STU: |
237 | 0 | ++onlyNo1; |
238 | 0 | case HexagonII::TypeCVI_VM_ST: |
239 | 0 | case HexagonII::TypeCVI_VM_NEW_ST: |
240 | 0 | ++CVIstores; |
241 | 0 | case HexagonII::TypeST: |
242 | 0 | ++stores; |
243 | 0 | ++memory; |
244 | 0 | if (ISJ->Core.getUnits() == slotSingleStore) |
245 | 0 | ++store0; |
246 | 0 | break; |
247 | 0 | case HexagonII::TypeMEMOP: |
248 | 0 | ++loads; |
249 | 0 | ++stores; |
250 | 0 | ++store1; |
251 | 0 | ++memory; |
252 | 0 | break; |
253 | 0 | case HexagonII::TypeNV: |
254 | 0 | ++memory; // NV insns are memory-like. |
255 | 0 | if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch()) |
256 | 0 | ++jumps, ++jump1; |
257 | 0 | break; |
258 | 742 | case HexagonII::TypeCR: |
259 | | // Legacy conditional branch predicated on a register. |
260 | 742 | case HexagonII::TypeSYSTEM: |
261 | 742 | if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) |
262 | 0 | ++loads; |
263 | 742 | break; |
264 | 9.65k | } |
265 | 9.65k | } |
266 | | |
267 | | // Check if the packet is legal. |
268 | 6.54k | if ((load0 > 1 || store0 > 1 || CVIloads > 1 || CVIstores > 1) || |
269 | 6.54k | (duplex > 1 || (duplex && memory)) || (solo && size() > 1) || |
270 | 6.54k | (onlyAX && neitherAnorX > 1) || (onlyAX && xtypeFloat)) { |
271 | 0 | Error = SHUFFLE_ERROR_INVALID; |
272 | 0 | return false; |
273 | 0 | } |
274 | | |
275 | 6.54k | if (jump1 && jumps > 1) { |
276 | | // Error if single branch with another branch. |
277 | 0 | Error = SHUFFLE_ERROR_BRANCHES; |
278 | 0 | return false; |
279 | 0 | } |
280 | | |
281 | | // Modify packet accordingly. |
282 | | // TODO: need to reserve slots #0 and #1 for duplex insns. |
283 | 6.54k | bool bOnlySlot3 = false; |
284 | 16.1k | for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { |
285 | 9.57k | MCInst const *ID = ISJ->getDesc(); |
286 | | |
287 | 9.57k | if (!ISJ->Core.getUnits()) { |
288 | | // Error if insn may not be executed in any slot. |
289 | 0 | Error = SHUFFLE_ERROR_UNKNOWN; |
290 | 0 | return false; |
291 | 0 | } |
292 | | |
293 | | // Exclude from slot #1 any insn but A2_nop. |
294 | 9.57k | if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop) |
295 | 8.66k | if (onlyNo1) |
296 | 0 | ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne); |
297 | | |
298 | | // Exclude from slot #1 any insn but A-type. |
299 | 9.57k | if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32) |
300 | 5.36k | if (onlyAin1) |
301 | 0 | ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne); |
302 | | |
303 | | // Branches must keep the original order. |
304 | 9.57k | if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() || |
305 | 6.27k | HexagonMCInstrInfo::getDesc(MCII, *ID).isCall()) |
306 | 3.74k | if (jumps > 1) { |
307 | 46 | if (jumpr || slotJump < slotLastJump) { |
308 | | // Error if indirect branch with another branch or |
309 | | // no more slots available for branches. |
310 | 10 | Error = SHUFFLE_ERROR_BRANCHES; |
311 | 10 | return false; |
312 | 10 | } |
313 | | // Pin the branch to the highest slot available to it. |
314 | 36 | ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump); |
315 | | // Update next highest slot available to branches. |
316 | 36 | slotJump >>= 1; |
317 | 36 | } |
318 | | |
319 | | // A single load must use slot #0. |
320 | 9.56k | if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) { |
321 | 0 | if (loads == 1 && loads == memory) |
322 | | // Pin the load to slot #0. |
323 | 0 | ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad); |
324 | 0 | } |
325 | | |
326 | | // A single store must use slot #0. |
327 | 9.56k | if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) { |
328 | 0 | if (!store0) { |
329 | 0 | if (stores == 1) |
330 | 0 | ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore); |
331 | 0 | else if (stores > 1) { |
332 | 0 | if (slotLoadStore < slotLastLoadStore) { |
333 | | // Error if no more slots available for stores. |
334 | 0 | Error = SHUFFLE_ERROR_STORES; |
335 | 0 | return false; |
336 | 0 | } |
337 | | // Pin the store to the highest slot available to it. |
338 | 0 | ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore); |
339 | | // Update the next highest slot available to stores. |
340 | 0 | slotLoadStore >>= 1; |
341 | 0 | } |
342 | 0 | } |
343 | 0 | if (store1 && stores > 1) { |
344 | | // Error if a single store with another store. |
345 | 0 | Error = SHUFFLE_ERROR_STORES; |
346 | 0 | return false; |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | // flag if an instruction can only be executed in slot 3 |
351 | 9.56k | if (ISJ->Core.getUnits() == slotThree) |
352 | 714 | bOnlySlot3 = true; |
353 | | |
354 | 9.56k | if (!ISJ->Core.getUnits()) { |
355 | | // Error if insn may not be executed in any slot. |
356 | 0 | Error = SHUFFLE_ERROR_NOSLOTS; |
357 | 0 | return false; |
358 | 0 | } |
359 | 9.56k | } |
360 | | |
361 | 6.53k | bool validateSlots = true; |
362 | 6.53k | if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) { |
363 | | // save off slot mask of instruction marked with A_PREFER_SLOT3 |
364 | | // and then pin it to slot #3 |
365 | 0 | unsigned saveUnits = slot3ISJ->Core.getUnits(); |
366 | 0 | slot3ISJ->Core.setUnits(saveUnits & slotThree); |
367 | |
|
368 | 0 | HexagonUnitAuction AuctionCore; |
369 | 0 | std::sort(begin(), end(), HexagonInstr::lessCore); |
370 | | |
371 | | // see if things ok with that instruction being pinned to slot #3 |
372 | 0 | bool bFail = false; |
373 | 0 | for (iterator I = begin(); I != end() && bFail != true; ++I) |
374 | 0 | if (!AuctionCore.bid(I->Core.getUnits())) |
375 | 0 | bFail = true; |
376 | | |
377 | | // if yes, great, if not then restore original slot mask |
378 | 0 | if (!bFail) |
379 | 0 | validateSlots = false; // all good, no need to re-do auction |
380 | 0 | else |
381 | 0 | for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { |
382 | 0 | MCInst const *ID = ISJ->getDesc(); |
383 | 0 | if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) |
384 | 0 | ISJ->Core.setUnits(saveUnits); |
385 | 0 | } |
386 | 0 | } |
387 | | |
388 | | // Check if any slot, core, is over-subscribed. |
389 | | // Verify the core slot subscriptions. |
390 | 6.53k | if (validateSlots) { |
391 | 6.53k | HexagonUnitAuction AuctionCore; |
392 | | |
393 | 6.53k | std::sort(begin(), end(), HexagonInstr::lessCore); |
394 | | |
395 | 13.2k | for (iterator I = begin(); I != end(); ++I) |
396 | 6.78k | if (!AuctionCore.bid(I->Core.getUnits())) { |
397 | 66 | Error = SHUFFLE_ERROR_SLOTS; |
398 | 66 | return false; |
399 | 66 | } |
400 | 6.53k | } |
401 | | // Verify the CVI slot subscriptions. |
402 | 6.46k | { |
403 | 6.46k | HexagonUnitAuction AuctionCVI; |
404 | | |
405 | 6.46k | std::sort(begin(), end(), HexagonInstr::lessCVI); |
406 | | |
407 | 12.9k | for (iterator I = begin(); I != end(); ++I) |
408 | 6.54k | for (unsigned i = 0; i < I->CVI.getLanes(); ++i) // TODO: I->CVI.isValid? |
409 | 53 | if (!AuctionCVI.bid(I->CVI.getUnits() << i)) { |
410 | 0 | Error = SHUFFLE_ERROR_SLOTS; |
411 | 0 | return false; |
412 | 0 | } |
413 | 6.46k | } |
414 | | |
415 | 6.46k | Error = SHUFFLE_SUCCESS; |
416 | 6.46k | return true; |
417 | 6.46k | } |
418 | | |
419 | 8.57k | bool HexagonShuffler::shuffle() { |
420 | 8.57k | if (size() > HEXAGON_PACKET_SIZE) { |
421 | | // Ignore a packet with with more than what a packet can hold |
422 | | // or with compound or duplex insns for now. |
423 | 0 | Error = SHUFFLE_ERROR_INVALID; |
424 | 0 | return false; |
425 | 0 | } |
426 | | |
427 | | // Check and prepare packet. |
428 | 8.57k | if (size() > 1 && check()) |
429 | | // Reorder the handles for each slot. |
430 | 105 | for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE; |
431 | 84 | ++nSlot) { |
432 | 84 | iterator ISJ, ISK; |
433 | 84 | unsigned slotSkip, slotWeight; |
434 | | |
435 | | // Prioritize the handles considering their restrictions. |
436 | 84 | for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0; |
437 | 348 | ISK != Packet.end(); ++ISK, ++slotSkip) |
438 | 264 | if (slotSkip < nSlot - emptySlots) |
439 | | // Note which handle to begin at. |
440 | 115 | ++ISJ; |
441 | 149 | else |
442 | | // Calculate the weight of the slot. |
443 | 149 | slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1); |
444 | | |
445 | 84 | if (slotWeight) |
446 | | // Sort the packet, favoring source order, |
447 | | // beginning after the previous slot. |
448 | 66 | std::sort(ISJ, Packet.end()); |
449 | 18 | else |
450 | | // Skip unused slot. |
451 | 18 | ++emptySlots; |
452 | 84 | } |
453 | | |
454 | 17.1k | for (iterator ISJ = begin(); ISJ != end(); ++ISJ) |
455 | 8.61k | DEBUG(dbgs().write_hex(ISJ->Core.getUnits()); |
456 | 8.61k | dbgs() << ':' |
457 | 8.61k | << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc()) |
458 | 8.61k | .getOpcode(); |
459 | 8.61k | dbgs() << '\n'); |
460 | 8.57k | DEBUG(dbgs() << '\n'); |
461 | | |
462 | 8.57k | return (!getError()); |
463 | 8.57k | } |