• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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