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