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 "MCTargetDesc/HexagonShuffler.h"
18 #include "Hexagon.h"
19 #include "MCTargetDesc/HexagonBaseInfo.h"
20 #include "MCTargetDesc/HexagonMCInstrInfo.h"
21 #include "MCTargetDesc/HexagonMCTargetDesc.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/Twine.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/Support/Compiler.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/MathExtras.h"
30 #include "llvm/Support/SourceMgr.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include <algorithm>
33 #include <cassert>
34 #include <utility>
35 #include <vector>
36
37 using namespace llvm;
38
39 namespace {
40
41 // Insn shuffling priority.
42 class HexagonBid {
43 // The priority is directly proportional to how restricted the insn is based
44 // on its flexibility to run on the available slots. So, the fewer slots it
45 // may run on, the higher its priority.
46 enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15.
47 unsigned Bid = 0;
48
49 public:
50 HexagonBid() = default;
HexagonBid(unsigned B)51 HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }
52
53 // Check if the insn priority is overflowed.
isSold() const54 bool isSold() const { return (Bid >= MAX); }
55
operator +=(const HexagonBid & B)56 HexagonBid &operator+=(const HexagonBid &B) {
57 Bid += B.Bid;
58 return *this;
59 }
60 };
61
62 // Slot shuffling allocation.
63 class HexagonUnitAuction {
64 HexagonBid Scores[HEXAGON_PACKET_SIZE];
65 // Mask indicating which slot is unavailable.
66 unsigned isSold : HEXAGON_PACKET_SIZE;
67
68 public:
HexagonUnitAuction(unsigned cs=0)69 HexagonUnitAuction(unsigned cs = 0) : isSold(cs) {}
70
71 // Allocate slots.
bid(unsigned B)72 bool bid(unsigned B) {
73 // Exclude already auctioned slots from the bid.
74 unsigned b = B & ~isSold;
75 if (b) {
76 for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i)
77 if (b & (1 << i)) {
78 // Request candidate slots.
79 Scores[i] += HexagonBid(b);
80 isSold |= Scores[i].isSold() << i;
81 }
82 return true;
83 } else
84 // Error if the desired slots are already full.
85 return false;
86 }
87 };
88
89 } // end anonymous namespace
90
setWeight(unsigned s)91 unsigned HexagonResource::setWeight(unsigned s) {
92 const unsigned SlotWeight = 8;
93 const unsigned MaskWeight = SlotWeight - 1;
94 unsigned Units = getUnits();
95 unsigned Key = ((1u << s) & Units) != 0;
96
97 // Calculate relative weight of the insn for the given slot, weighing it the
98 // heavier the more restrictive the insn is and the lowest the slots that the
99 // insn may be executed in.
100 if (Key == 0 || Units == 0 || (SlotWeight * s >= 32))
101 return Weight = 0;
102
103 unsigned Ctpop = countPopulation(Units);
104 unsigned Cttz = countTrailingZeros(Units);
105 Weight = (1u << (SlotWeight * s)) * ((MaskWeight - Ctpop) << Cttz);
106 return Weight;
107 }
108
SetupTUL(TypeUnitsAndLanes * TUL,StringRef CPU)109 void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) {
110 (*TUL)[HexagonII::TypeCVI_VA] =
111 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
112 (*TUL)[HexagonII::TypeCVI_VA_DV] = UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2);
113 (*TUL)[HexagonII::TypeCVI_VX] = UnitsAndLanes(CVI_MPY0 | CVI_MPY1, 1);
114 (*TUL)[HexagonII::TypeCVI_VX_LATE] = UnitsAndLanes(CVI_MPY0 | CVI_MPY1, 1);
115 (*TUL)[HexagonII::TypeCVI_VX_DV] = UnitsAndLanes(CVI_MPY0, 2);
116 (*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1);
117 (*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2);
118 (*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1);
119 (*TUL)[HexagonII::TypeCVI_VS_VX] = UnitsAndLanes(CVI_XLANE | CVI_SHIFT, 1);
120 (*TUL)[HexagonII::TypeCVI_VINLANESAT] =
121 (CPU == "hexagonv60")
122 ? UnitsAndLanes(CVI_SHIFT, 1)
123 : UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
124 (*TUL)[HexagonII::TypeCVI_VM_LD] =
125 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
126 (*TUL)[HexagonII::TypeCVI_VM_TMP_LD] = UnitsAndLanes(CVI_NONE, 0);
127 (*TUL)[HexagonII::TypeCVI_VM_VP_LDU] = UnitsAndLanes(CVI_XLANE, 1);
128 (*TUL)[HexagonII::TypeCVI_VM_ST] =
129 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
130 (*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0);
131 (*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1);
132 (*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4);
133 (*TUL)[HexagonII::TypeCVI_GATHER] =
134 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
135 (*TUL)[HexagonII::TypeCVI_SCATTER] =
136 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
137 (*TUL)[HexagonII::TypeCVI_SCATTER_DV] =
138 UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2);
139 (*TUL)[HexagonII::TypeCVI_SCATTER_NEW_ST] =
140 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
141 }
142
HexagonCVIResource(TypeUnitsAndLanes * TUL,MCInstrInfo const & MCII,unsigned s,MCInst const * id)143 HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL,
144 MCInstrInfo const &MCII, unsigned s,
145 MCInst const *id)
146 : HexagonResource(s) {
147 unsigned T = HexagonMCInstrInfo::getType(MCII, *id);
148
149 if (TUL->count(T)) {
150 // For an HVX insn.
151 Valid = true;
152 setUnits((*TUL)[T].first);
153 setLanes((*TUL)[T].second);
154 setLoad(HexagonMCInstrInfo::getDesc(MCII, *id).mayLoad());
155 setStore(HexagonMCInstrInfo::getDesc(MCII, *id).mayStore());
156 } else {
157 // For core insns.
158 Valid = false;
159 setUnits(0);
160 setLanes(0);
161 setLoad(false);
162 setStore(false);
163 }
164 }
165
166 struct CVIUnits {
167 unsigned Units;
168 unsigned Lanes;
169 };
170 using HVXInstsT = SmallVector<struct CVIUnits, 8>;
171
makeAllBits(unsigned startBit,unsigned Lanes)172 static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
173 {
174 for (unsigned i = 1; i < Lanes; ++i)
175 startBit = (startBit << 1) | startBit;
176 return startBit;
177 }
178
checkHVXPipes(const HVXInstsT & hvxInsts,unsigned startIdx,unsigned usedUnits)179 static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx,
180 unsigned usedUnits) {
181 if (startIdx < hvxInsts.size()) {
182 if (!hvxInsts[startIdx].Units)
183 return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits);
184 for (unsigned b = 0x1; b <= 0x8; b <<= 1) {
185 if ((hvxInsts[startIdx].Units & b) == 0)
186 continue;
187 unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes);
188 if ((allBits & usedUnits) == 0) {
189 if (checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits))
190 return true;
191 }
192 }
193 return false;
194 }
195 return true;
196 }
197
HexagonShuffler(MCContext & Context,bool ReportErrors,MCInstrInfo const & MCII,MCSubtargetInfo const & STI)198 HexagonShuffler::HexagonShuffler(MCContext &Context, bool ReportErrors,
199 MCInstrInfo const &MCII,
200 MCSubtargetInfo const &STI)
201 : Context(Context), MCII(MCII), STI(STI), ReportErrors(ReportErrors) {
202 reset();
203 HexagonCVIResource::SetupTUL(&TUL, STI.getCPU());
204 }
205
reset()206 void HexagonShuffler::reset() {
207 Packet.clear();
208 BundleFlags = 0;
209 }
210
append(MCInst const & ID,MCInst const * Extender,unsigned S)211 void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender,
212 unsigned S) {
213 HexagonInstr PI(&TUL, MCII, &ID, Extender, S);
214
215 Packet.push_back(PI);
216 }
217
218 static struct {
219 unsigned first;
220 unsigned second;
221 } jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
222 #define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0]))
223
restrictSlot1AOK()224 void HexagonShuffler::restrictSlot1AOK() {
225 bool HasRestrictSlot1AOK = false;
226 SMLoc RestrictLoc;
227 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
228 MCInst const &Inst = ISJ->getDesc();
229 if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII, Inst)) {
230 HasRestrictSlot1AOK = true;
231 RestrictLoc = Inst.getLoc();
232 }
233 }
234 if (HasRestrictSlot1AOK)
235 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
236 MCInst const &Inst = ISJ->getDesc();
237 unsigned Type = HexagonMCInstrInfo::getType(MCII, Inst);
238 if (Type != HexagonII::TypeALU32_2op &&
239 Type != HexagonII::TypeALU32_3op &&
240 Type != HexagonII::TypeALU32_ADDI) {
241 unsigned Units = ISJ->Core.getUnits();
242 if (Units & 2U) {
243 AppliedRestrictions.push_back(std::make_pair(
244 Inst.getLoc(),
245 "Instruction was restricted from being in slot 1"));
246 AppliedRestrictions.push_back(
247 std::make_pair(RestrictLoc, "Instruction can only be combine "
248 "with an ALU instruction in slot 1"));
249 ISJ->Core.setUnits(Units & ~2U);
250 }
251 }
252 }
253 }
254
restrictNoSlot1Store()255 void HexagonShuffler::restrictNoSlot1Store() {
256 bool HasRestrictNoSlot1Store = false;
257 SMLoc RestrictLoc;
258 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
259 MCInst const &Inst = ISJ->getDesc();
260 if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII, Inst)) {
261 HasRestrictNoSlot1Store = true;
262 RestrictLoc = Inst.getLoc();
263 }
264 }
265 if (HasRestrictNoSlot1Store) {
266 bool AppliedRestriction = false;
267 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
268 MCInst const &Inst = ISJ->getDesc();
269 if (HexagonMCInstrInfo::getDesc(MCII, Inst).mayStore()) {
270 unsigned Units = ISJ->Core.getUnits();
271 if (Units & 2U) {
272 AppliedRestriction = true;
273 AppliedRestrictions.push_back(std::make_pair(
274 Inst.getLoc(),
275 "Instruction was restricted from being in slot 1"));
276 ISJ->Core.setUnits(Units & ~2U);
277 }
278 }
279 }
280 if (AppliedRestriction)
281 AppliedRestrictions.push_back(std::make_pair(
282 RestrictLoc, "Instruction does not allow a store in slot 1"));
283 }
284 }
285
applySlotRestrictions()286 void HexagonShuffler::applySlotRestrictions() {
287 restrictSlot1AOK();
288 restrictNoSlot1Store();
289 }
290
291 /// Check that the packet is legal and enforce relative insn order.
check()292 bool HexagonShuffler::check() {
293 // Descriptive slot masks.
294 const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1,
295 slotThree = 0x8, // slotFirstJump = 0x8,
296 slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
297 // Highest slots for branches and stores used to keep their original order.
298 // unsigned slotJump = slotFirstJump;
299 unsigned slotLoadStore = slotFirstLoadStore;
300 // Number of memory operations, loads, solo loads, stores, solo stores, single
301 // stores.
302 unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
303 // Number of duplex insns
304 unsigned duplex = 0;
305 unsigned pSlot3Cnt = 0;
306 unsigned memops = 0;
307 iterator slot3ISJ = end();
308 std::vector<iterator> foundBranches;
309 unsigned reservedSlots = 0;
310
311 // Collect information from the insns in the packet.
312 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
313 MCInst const &ID = ISJ->getDesc();
314
315 if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {
316 ++pSlot3Cnt;
317 slot3ISJ = ISJ;
318 }
319 reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID);
320
321 switch (HexagonMCInstrInfo::getType(MCII, ID)) {
322 case HexagonII::TypeS_2op:
323 case HexagonII::TypeS_3op:
324 case HexagonII::TypeALU64:
325 break;
326 case HexagonII::TypeJ:
327 foundBranches.push_back(ISJ);
328 break;
329 case HexagonII::TypeCVI_VM_VP_LDU:
330 case HexagonII::TypeCVI_VM_LD:
331 case HexagonII::TypeCVI_VM_TMP_LD:
332 case HexagonII::TypeCVI_GATHER:
333 case HexagonII::TypeCVI_GATHER_RST:
334 case HexagonII::TypeLD:
335 ++loads;
336 ++memory;
337 if (ISJ->Core.getUnits() == slotSingleLoad ||
338 HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_VP_LDU)
339 ++load0;
340 if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn())
341 foundBranches.push_back(ISJ);
342 break;
343 case HexagonII::TypeCVI_VM_STU:
344 case HexagonII::TypeCVI_VM_ST:
345 case HexagonII::TypeCVI_VM_NEW_ST:
346 case HexagonII::TypeCVI_SCATTER:
347 case HexagonII::TypeCVI_SCATTER_DV:
348 case HexagonII::TypeCVI_SCATTER_RST:
349 case HexagonII::TypeCVI_SCATTER_NEW_RST:
350 case HexagonII::TypeCVI_SCATTER_NEW_ST:
351 case HexagonII::TypeST:
352 ++stores;
353 ++memory;
354 if (ISJ->Core.getUnits() == slotSingleStore ||
355 HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_STU)
356 ++store0;
357 break;
358 case HexagonII::TypeV4LDST:
359 ++loads;
360 ++stores;
361 ++store1;
362 ++memops;
363 ++memory;
364 break;
365 case HexagonII::TypeNCJ:
366 ++memory; // NV insns are memory-like.
367 foundBranches.push_back(ISJ);
368 break;
369 case HexagonII::TypeV2LDST:
370 if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
371 ++loads;
372 ++memory;
373 if (ISJ->Core.getUnits() == slotSingleLoad ||
374 HexagonMCInstrInfo::getType(MCII, ID) ==
375 HexagonII::TypeCVI_VM_VP_LDU)
376 ++load0;
377 } else {
378 assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore());
379 ++memory;
380 ++stores;
381 }
382 break;
383 case HexagonII::TypeCR:
384 // Legacy conditional branch predicated on a register.
385 case HexagonII::TypeCJ:
386 if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch())
387 foundBranches.push_back(ISJ);
388 break;
389 case HexagonII::TypeDUPLEX: {
390 ++duplex;
391 MCInst const &Inst0 = *ID.getOperand(0).getInst();
392 MCInst const &Inst1 = *ID.getOperand(1).getInst();
393 if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch())
394 foundBranches.push_back(ISJ);
395 if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch())
396 foundBranches.push_back(ISJ);
397 if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn())
398 foundBranches.push_back(ISJ);
399 if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn())
400 foundBranches.push_back(ISJ);
401 break;
402 }
403 }
404 }
405 applySlotRestrictions();
406
407 // Check if the packet is legal.
408 if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory))) {
409 reportError(llvm::Twine("invalid instruction packet"));
410 return false;
411 }
412
413 // Modify packet accordingly.
414 // TODO: need to reserve slots #0 and #1 for duplex insns.
415 bool bOnlySlot3 = false;
416 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
417 MCInst const &ID = ISJ->getDesc();
418
419 if (!ISJ->Core.getUnits()) {
420 // Error if insn may not be executed in any slot.
421 return false;
422 }
423
424 // A single load must use slot #0.
425 if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
426 if (loads == 1 && loads == memory && memops == 0)
427 // Pin the load to slot #0.
428 switch (ID.getOpcode()) {
429 case Hexagon::V6_vgathermw:
430 case Hexagon::V6_vgathermh:
431 case Hexagon::V6_vgathermhw:
432 case Hexagon::V6_vgathermwq:
433 case Hexagon::V6_vgathermhq:
434 case Hexagon::V6_vgathermhwq:
435 // Slot1 only loads
436 break;
437 default:
438 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
439 break;
440 }
441 else if (loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf
442 // Loads must keep the original order ONLY if
443 // isMemReorderDisabled() == true
444 if (slotLoadStore < slotLastLoadStore) {
445 // Error if no more slots available for loads.
446 reportError(
447 llvm::Twine("invalid instruction packet: too many loads"));
448 return false;
449 }
450 // Pin the load to the highest slot available to it.
451 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
452 // Update the next highest slot available to loads.
453 slotLoadStore >>= 1;
454 }
455 }
456
457 // A single store must use slot #0.
458 if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) {
459 if (!store0) {
460 if (stores == 1 && (loads == 0 || !isMemReorderDisabled()))
461 // Pin the store to slot #0 only if isMemReorderDisabled() == false
462 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
463 else if (stores >= 1) {
464 if (slotLoadStore < slotLastLoadStore) {
465 // Error if no more slots available for stores.
466 reportError(Twine("invalid instruction packet: too many stores"));
467 return false;
468 }
469 // Pin the store to the highest slot available to it.
470 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
471 // Update the next highest slot available to stores.
472 slotLoadStore >>= 1;
473 }
474 }
475 if (store1 && stores > 1) {
476 // Error if a single store with another store.
477 reportError(Twine("invalid instruction packet: too many stores"));
478 return false;
479 }
480 }
481
482 // flag if an instruction requires to be in slot 3
483 if (ISJ->Core.getUnits() == slotThree)
484 bOnlySlot3 = true;
485
486 if (!ISJ->Core.getUnits()) {
487 // Error if insn may not be executed in any slot.
488 reportError(Twine("invalid instruction packet: out of slots"));
489 return false;
490 }
491 }
492
493 // preserve branch order
494 bool validateSlots = true;
495 if (foundBranches.size() > 1) {
496 if (foundBranches.size() > 2) {
497 reportError(Twine("too many branches in packet"));
498 return false;
499 }
500
501 // try all possible choices
502 for (unsigned int i = 0; i < MAX_JUMP_SLOTS; ++i) {
503 // validate first jump with this slot rule
504 if (!(jumpSlots[i].first & foundBranches[0]->Core.getUnits()))
505 continue;
506
507 // validate second jump with this slot rule
508 if (!(jumpSlots[i].second & foundBranches[1]->Core.getUnits()))
509 continue;
510
511 // both valid for this configuration, set new slot rules
512 PacketSave = Packet;
513 foundBranches[0]->Core.setUnits(jumpSlots[i].first);
514 foundBranches[1]->Core.setUnits(jumpSlots[i].second);
515
516 HexagonUnitAuction AuctionCore(reservedSlots);
517 std::stable_sort(begin(), end(), HexagonInstr::lessCore);
518
519 // see if things ok with that instruction being pinned to slot "slotJump"
520 bool bFail = false;
521 for (iterator I = begin(); I != end() && !bFail; ++I)
522 if (!AuctionCore.bid(I->Core.getUnits()))
523 bFail = true;
524
525 // if yes, great, if not then restore original slot mask
526 if (!bFail) {
527 validateSlots = false; // all good, no need to re-do auction
528 break;
529 } else
530 // restore original values
531 Packet = PacketSave;
532 }
533 if (validateSlots) {
534 reportError(Twine("invalid instruction packet: out of slots"));
535 return false;
536 }
537 }
538
539 if (foundBranches.size() <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 &&
540 slot3ISJ != end()) {
541 validateSlots = true;
542 // save off slot mask of instruction marked with A_PREFER_SLOT3
543 // and then pin it to slot #3
544 unsigned saveUnits = slot3ISJ->Core.getUnits();
545 slot3ISJ->Core.setUnits(saveUnits & slotThree);
546
547 HexagonUnitAuction AuctionCore(reservedSlots);
548 std::stable_sort(begin(), end(), HexagonInstr::lessCore);
549
550 // see if things ok with that instruction being pinned to slot #3
551 bool bFail = false;
552 for (iterator I = begin(); I != end() && !bFail; ++I)
553 if (!AuctionCore.bid(I->Core.getUnits()))
554 bFail = true;
555
556 // if yes, great, if not then restore original slot mask
557 if (!bFail)
558 validateSlots = false; // all good, no need to re-do auction
559 else
560 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
561 MCInst const &ID = ISJ->getDesc();
562 if (HexagonMCInstrInfo::prefersSlot3(MCII, ID))
563 ISJ->Core.setUnits(saveUnits);
564 }
565 }
566
567 // Check if any slot, core or CVI, is over-subscribed.
568 // Verify the core slot subscriptions.
569 if (validateSlots) {
570 HexagonUnitAuction AuctionCore(reservedSlots);
571
572 std::stable_sort(begin(), end(), HexagonInstr::lessCore);
573
574 for (iterator I = begin(); I != end(); ++I)
575 if (!AuctionCore.bid(I->Core.getUnits())) {
576 reportError(Twine("invalid instruction packet: slot error"));
577 return false;
578 }
579 }
580 // Verify the CVI slot subscriptions.
581 std::stable_sort(begin(), end(), HexagonInstr::lessCVI);
582 // create vector of hvx instructions to check
583 HVXInstsT hvxInsts;
584 hvxInsts.clear();
585 for (iterator I = begin(); I != end(); ++I) {
586 struct CVIUnits inst;
587 inst.Units = I->CVI.getUnits();
588 inst.Lanes = I->CVI.getLanes();
589 if (inst.Units == 0)
590 continue; // not an hvx inst or an hvx inst that doesn't uses any pipes
591 hvxInsts.push_back(inst);
592 }
593 // if there are any hvx instructions in this packet, check pipe usage
594 if (hvxInsts.size() > 0) {
595 unsigned startIdx, usedUnits;
596 startIdx = usedUnits = 0x0;
597 if (!checkHVXPipes(hvxInsts, startIdx, usedUnits)) {
598 // too many pipes used to be valid
599 reportError(Twine("invalid instruction packet: slot error"));
600 return false;
601 }
602 }
603
604 return true;
605 }
606
shuffle()607 bool HexagonShuffler::shuffle() {
608 if (size() > HEXAGON_PACKET_SIZE) {
609 // Ignore a packet with with more than what a packet can hold
610 // or with compound or duplex insns for now.
611 reportError(Twine("invalid instruction packet"));
612 return false;
613 }
614
615 // Check and prepare packet.
616 bool Ok = true;
617 if (size() > 1 && (Ok = check()))
618 // Reorder the handles for each slot.
619 for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
620 ++nSlot) {
621 iterator ISJ, ISK;
622 unsigned slotSkip, slotWeight;
623
624 // Prioritize the handles considering their restrictions.
625 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
626 ISK != Packet.end(); ++ISK, ++slotSkip)
627 if (slotSkip < nSlot - emptySlots)
628 // Note which handle to begin at.
629 ++ISJ;
630 else
631 // Calculate the weight of the slot.
632 slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);
633
634 if (slotWeight)
635 // Sort the packet, favoring source order,
636 // beginning after the previous slot.
637 std::stable_sort(ISJ, Packet.end());
638 else
639 // Skip unused slot.
640 ++emptySlots;
641 }
642
643 for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
644 LLVM_DEBUG(dbgs().write_hex(ISJ->Core.getUnits()); if (ISJ->CVI.isValid()) {
645 dbgs() << '/';
646 dbgs().write_hex(ISJ->CVI.getUnits()) << '|';
647 dbgs() << ISJ->CVI.getLanes();
648 } dbgs() << ':'
649 << HexagonMCInstrInfo::getDesc(MCII, ISJ->getDesc()).getOpcode();
650 dbgs() << '\n');
651 LLVM_DEBUG(dbgs() << '\n');
652
653 return Ok;
654 }
655
reportError(Twine const & Msg)656 void HexagonShuffler::reportError(Twine const &Msg) {
657 if (ReportErrors) {
658 for (auto const &I : AppliedRestrictions) {
659 auto SM = Context.getSourceManager();
660 if (SM)
661 SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second);
662 }
663 Context.reportError(Loc, Msg);
664 }
665 }
666