1 //===- HexagonShuffler.cpp - Instruction bundle shuffling -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This implements the shuffling of insns inside a bundle according to the
10 // packet formation rules of the Hexagon ISA.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/HexagonShuffler.h"
15 #include "MCTargetDesc/HexagonBaseInfo.h"
16 #include "MCTargetDesc/HexagonMCInstrInfo.h"
17 #include "MCTargetDesc/HexagonMCTargetDesc.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrDesc.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/SourceMgr.h"
28 #include "llvm/Support/raw_ostream.h"
34 #define DEBUG_TYPE "hexagon-shuffle"
40 // Insn shuffling priority.
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.
49 HexagonBid() = default;
50 HexagonBid(unsigned B
) { Bid
= B
? MAX
/ llvm::popcount(B
) : 0; }
52 // Check if the insn priority is overflowed.
53 bool isSold() const { return (Bid
>= MAX
); }
55 HexagonBid
&operator+=(const HexagonBid
&B
) {
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
;
68 HexagonUnitAuction(unsigned cs
= 0) : isSold(cs
) {}
71 bool bid(unsigned B
) {
72 // Exclude already auctioned slots from the bid.
73 unsigned b
= B
& ~isSold
;
75 for (unsigned i
= 0; i
< HEXAGON_PACKET_SIZE
; ++i
)
77 // Request candidate slots.
78 Scores
[i
] += HexagonBid(b
);
79 isSold
|= Scores
[i
].isSold() << i
;
83 // Error if the desired slots are already full.
88 } // end anonymous namespace
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;
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))
102 unsigned Ctpop
= llvm::popcount(Units
);
103 unsigned Cttz
= llvm::countr_zero(Units
);
104 Weight
= (1u << (SlotWeight
* s
)) * ((MaskWeight
- Ctpop
) << Cttz
);
108 HexagonCVIResource::HexagonCVIResource(MCInstrInfo
const &MCII
,
109 MCSubtargetInfo
const &STI
,
112 : HexagonResource(s
) {
114 const unsigned ItinUnits
= HexagonMCInstrInfo::getCVIResources(MCII
, STI
, *id
);
116 const unsigned Units
= HexagonConvertUnits(ItinUnits
, &Lanes
);
118 if (Units
== 0 && Lanes
== 0) {
130 setLoad(HexagonMCInstrInfo::getDesc(MCII
, *id
).mayLoad());
131 setStore(HexagonMCInstrInfo::getDesc(MCII
, *id
).mayStore());
139 using HVXInstsT
= SmallVector
<struct CVIUnits
, 8>;
141 static unsigned makeAllBits(unsigned startBit
, unsigned Lanes
)
143 for (unsigned i
= 1; i
< Lanes
; ++i
)
144 startBit
= (startBit
<< 1) | startBit
;
148 static bool checkHVXPipes(const HVXInstsT
&hvxInsts
, unsigned startIdx
,
149 unsigned usedUnits
) {
150 if (startIdx
< hvxInsts
.size()) {
151 if (!hvxInsts
[startIdx
].Units
)
152 return checkHVXPipes(hvxInsts
, startIdx
+ 1, usedUnits
);
153 for (unsigned b
= 0x1; b
<= 0x8; b
<<= 1) {
154 if ((hvxInsts
[startIdx
].Units
& b
) == 0)
156 unsigned allBits
= makeAllBits(b
, hvxInsts
[startIdx
].Lanes
);
157 if ((allBits
& usedUnits
) == 0) {
158 if (checkHVXPipes(hvxInsts
, startIdx
+ 1, usedUnits
| allBits
))
167 HexagonShuffler::HexagonShuffler(MCContext
&Context
, bool ReportErrors
,
168 MCInstrInfo
const &MCII
,
169 MCSubtargetInfo
const &STI
)
170 : Context(Context
), BundleFlags(), MCII(MCII
), STI(STI
),
171 ReportErrors(ReportErrors
), CheckFailure() {
175 void HexagonShuffler::reset() {
178 CheckFailure
= false;
181 void HexagonShuffler::append(MCInst
const &ID
, MCInst
const *Extender
,
183 HexagonInstr
PI(MCII
, STI
, &ID
, Extender
, S
);
185 Packet
.push_back(PI
);
189 static const unsigned Slot0Mask
= 1 << 0;
190 static const unsigned Slot1Mask
= 1 << 1;
191 static const unsigned Slot3Mask
= 1 << 3;
192 static const unsigned slotSingleLoad
= Slot0Mask
;
193 static const unsigned slotSingleStore
= Slot0Mask
;
195 void HexagonShuffler::restrictSlot1AOK(HexagonPacketSummary
const &Summary
) {
196 if (Summary
.Slot1AOKLoc
)
197 for (HexagonInstr
&ISJ
: insts()) {
198 MCInst
const &Inst
= ISJ
.getDesc();
199 const unsigned Type
= HexagonMCInstrInfo::getType(MCII
, Inst
);
200 if (Type
!= HexagonII::TypeALU32_2op
&&
201 Type
!= HexagonII::TypeALU32_3op
&&
202 Type
!= HexagonII::TypeALU32_ADDI
) {
203 const unsigned Units
= ISJ
.Core
.getUnits();
205 if (Units
& Slot1Mask
) {
206 AppliedRestrictions
.push_back(std::make_pair(
208 "Instruction was restricted from being in slot 1"));
209 AppliedRestrictions
.push_back(std::make_pair(
210 *Summary
.Slot1AOKLoc
, "Instruction can only be combined "
211 "with an ALU instruction in slot 1"));
212 ISJ
.Core
.setUnits(Units
& ~Slot1Mask
);
218 void HexagonShuffler::restrictNoSlot1Store(
219 HexagonPacketSummary
const &Summary
) {
220 // If this packet contains an instruction that bars slot-1 stores,
221 // we should mask off slot 1 from all of the store instructions in
224 if (!Summary
.NoSlot1StoreLoc
)
227 bool AppliedRestriction
= false;
229 for (HexagonInstr
&ISJ
: insts()) {
230 MCInst
const &Inst
= ISJ
.getDesc();
231 if (HexagonMCInstrInfo::getDesc(MCII
, Inst
).mayStore()) {
232 unsigned Units
= ISJ
.Core
.getUnits();
233 if (Units
& Slot1Mask
) {
234 AppliedRestriction
= true;
235 AppliedRestrictions
.push_back(std::make_pair(
236 Inst
.getLoc(), "Instruction was restricted from being in slot 1"));
237 ISJ
.Core
.setUnits(Units
& ~Slot1Mask
);
242 if (AppliedRestriction
)
243 AppliedRestrictions
.push_back(
244 std::make_pair(*Summary
.NoSlot1StoreLoc
,
245 "Instruction does not allow a store in slot 1"));
248 bool HexagonShuffler::applySlotRestrictions(HexagonPacketSummary
const &Summary
,
249 const bool DoShuffle
) {
250 // These restrictions can modify the slot masks in the instructions
251 // in the Packet member. They should run unconditionally and their
252 // order does not matter.
253 restrictSlot1AOK(Summary
);
254 restrictNoSlot1Store(Summary
);
258 // These restrictions can modify the slot masks in the instructions
259 // in the Packet member, but they can also detect constraint failures
262 restrictStoreLoadOrder(Summary
);
264 restrictBranchOrder(Summary
);
266 restrictPreferSlot3(Summary
, DoShuffle
);
267 return !CheckFailure
;
270 void HexagonShuffler::restrictBranchOrder(HexagonPacketSummary
const &Summary
) {
271 // preserve branch order
272 const bool HasMultipleBranches
= Summary
.branchInsts
.size() > 1;
273 if (!HasMultipleBranches
)
276 if (Summary
.branchInsts
.size() > 2) {
277 reportError(Twine("too many branches in packet"));
281 const static std::pair
<unsigned, unsigned> jumpSlots
[] = {
282 {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
283 // try all possible choices
284 for (std::pair
<unsigned, unsigned> jumpSlot
: jumpSlots
) {
285 // validate first jump with this slot rule
286 if (!(jumpSlot
.first
& Summary
.branchInsts
[0]->Core
.getUnits()))
289 // validate second jump with this slot rule
290 if (!(jumpSlot
.second
& Summary
.branchInsts
[1]->Core
.getUnits()))
293 // both valid for this configuration, set new slot rules
294 const HexagonPacket PacketSave
= Packet
;
295 Summary
.branchInsts
[0]->Core
.setUnits(jumpSlot
.first
);
296 Summary
.branchInsts
[1]->Core
.setUnits(jumpSlot
.second
);
298 const bool HasShuffledPacket
= tryAuction(Summary
).has_value();
299 if (HasShuffledPacket
)
302 // if yes, great, if not then restore original slot mask
303 // restore original values
307 reportResourceError(Summary
, "out of slots");
310 void HexagonShuffler::permitNonSlot() {
311 for (HexagonInstr
&ISJ
: insts()) {
312 const bool RequiresSlot
= HexagonMCInstrInfo::requiresSlot(STI
, *ISJ
.ID
);
314 ISJ
.Core
.setAllUnits();
318 bool HexagonShuffler::ValidResourceUsage(HexagonPacketSummary
const &Summary
) {
319 std::optional
<HexagonPacket
> ShuffledPacket
= tryAuction(Summary
);
321 if (!ShuffledPacket
) {
322 reportResourceError(Summary
, "slot error");
326 // Verify the CVI slot subscriptions.
327 llvm::stable_sort(*ShuffledPacket
, HexagonInstr::lessCVI
);
328 // create vector of hvx instructions to check
331 for (const auto &I
: *ShuffledPacket
) {
332 struct CVIUnits inst
;
333 inst
.Units
= I
.CVI
.getUnits();
334 inst
.Lanes
= I
.CVI
.getLanes();
336 continue; // not an hvx inst or an hvx inst that doesn't uses any pipes
337 hvxInsts
.push_back(inst
);
340 // if there are any hvx instructions in this packet, check pipe usage
341 if (hvxInsts
.size() > 0) {
342 unsigned startIdx
, usedUnits
;
343 startIdx
= usedUnits
= 0x0;
344 if (!checkHVXPipes(hvxInsts
, startIdx
, usedUnits
)) {
345 // too many pipes used to be valid
346 reportError(Twine("invalid instruction packet: slot error"));
351 Packet
= *ShuffledPacket
;
356 bool HexagonShuffler::restrictStoreLoadOrder(
357 HexagonPacketSummary
const &Summary
) {
358 // Modify packet accordingly.
359 // TODO: need to reserve slots #0 and #1 for duplex insns.
360 static const unsigned slotFirstLoadStore
= Slot1Mask
;
361 static const unsigned slotLastLoadStore
= Slot0Mask
;
362 unsigned slotLoadStore
= slotFirstLoadStore
;
364 for (iterator ISJ
= begin(); ISJ
!= end(); ++ISJ
) {
365 MCInst
const &ID
= ISJ
->getDesc();
367 if (!ISJ
->Core
.getUnits())
368 // Error if insn may not be executed in any slot.
371 // A single load must use slot #0.
372 if (HexagonMCInstrInfo::getDesc(MCII
, ID
).mayLoad()) {
373 if (Summary
.loads
== 1 && Summary
.loads
== Summary
.memory
&&
375 // Pin the load to slot #0.
376 switch (ID
.getOpcode()) {
377 case Hexagon::V6_vgathermw
:
378 case Hexagon::V6_vgathermh
:
379 case Hexagon::V6_vgathermhw
:
380 case Hexagon::V6_vgathermwq
:
381 case Hexagon::V6_vgathermhq
:
382 case Hexagon::V6_vgathermhwq
:
386 ISJ
->Core
.setUnits(ISJ
->Core
.getUnits() & slotSingleLoad
);
389 else if (Summary
.loads
>= 1 && isMemReorderDisabled()) { // }:mem_noshuf
390 // Loads must keep the original order ONLY if
391 // isMemReorderDisabled() == true
392 if (slotLoadStore
< slotLastLoadStore
) {
393 // Error if no more slots available for loads.
394 reportError("invalid instruction packet: too many loads");
397 // Pin the load to the highest slot available to it.
398 ISJ
->Core
.setUnits(ISJ
->Core
.getUnits() & slotLoadStore
);
399 // Update the next highest slot available to loads.
404 // A single store must use slot #0.
405 if (HexagonMCInstrInfo::getDesc(MCII
, ID
).mayStore()) {
406 if (!Summary
.store0
) {
407 const bool PacketHasNoOnlySlot0
=
408 llvm::none_of(insts(), [&](HexagonInstr
const &I
) {
409 return I
.Core
.getUnits() == Slot0Mask
&&
410 I
.ID
->getOpcode() != ID
.getOpcode();
412 const bool SafeToMoveToSlot0
=
413 (Summary
.loads
== 0) ||
414 (!isMemReorderDisabled() && PacketHasNoOnlySlot0
);
416 if (Summary
.stores
== 1 && SafeToMoveToSlot0
)
417 // Pin the store to slot #0 only if isMemReorderDisabled() == false
418 ISJ
->Core
.setUnits(ISJ
->Core
.getUnits() & slotSingleStore
);
419 else if (Summary
.stores
>= 1) {
420 if (slotLoadStore
< slotLastLoadStore
) {
421 // Error if no more slots available for stores.
422 reportError("invalid instruction packet: too many stores");
425 // Pin the store to the highest slot available to it.
426 ISJ
->Core
.setUnits(ISJ
->Core
.getUnits() & slotLoadStore
);
427 // Update the next highest slot available to stores.
431 if (Summary
.store1
&& Summary
.stores
> 1) {
432 // Error if a single store with another store.
433 reportError("invalid instruction packet: too many stores");
442 static std::string
SlotMaskToText(unsigned SlotMask
) {
443 SmallVector
<std::string
, HEXAGON_PRESHUFFLE_PACKET_SIZE
> Slots
;
444 for (unsigned SlotNum
= 0; SlotNum
< HEXAGON_PACKET_SIZE
; SlotNum
++)
445 if ((SlotMask
& (1 << SlotNum
)) != 0)
446 Slots
.push_back(utostr(SlotNum
));
448 return llvm::join(Slots
, StringRef(", "));
451 HexagonShuffler::HexagonPacketSummary
HexagonShuffler::GetPacketSummary() {
452 HexagonPacketSummary Summary
= HexagonPacketSummary();
454 // Collect information from the insns in the packet.
455 for (iterator ISJ
= begin(); ISJ
!= end(); ++ISJ
) {
456 MCInst
const &ID
= ISJ
->getDesc();
458 if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII
, ID
))
459 Summary
.Slot1AOKLoc
= ID
.getLoc();
460 if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII
, ID
))
461 Summary
.NoSlot1StoreLoc
= ID
.getLoc();
463 if (HexagonMCInstrInfo::prefersSlot3(MCII
, ID
)) {
465 Summary
.PrefSlot3Inst
= ISJ
;
467 const unsigned ReservedSlots
=
468 HexagonMCInstrInfo::getOtherReservedSlots(MCII
, STI
, ID
);
469 Summary
.ReservedSlotMask
|= ReservedSlots
;
470 if (ReservedSlots
!= 0)
471 AppliedRestrictions
.push_back(std::make_pair(ID
.getLoc(),
472 (Twine("Instruction has reserved slots: ") +
473 SlotMaskToText(ReservedSlots
)).str()));
475 switch (HexagonMCInstrInfo::getType(MCII
, ID
)) {
476 case HexagonII::TypeS_2op
:
477 case HexagonII::TypeS_3op
:
478 case HexagonII::TypeALU64
:
480 case HexagonII::TypeJ
:
481 if (HexagonMCInstrInfo::IsABranchingInst(MCII
, STI
, *ISJ
->ID
))
482 Summary
.branchInsts
.push_back(ISJ
);
484 case HexagonII::TypeCVI_VM_VP_LDU
:
485 case HexagonII::TypeCVI_VM_LD
:
486 case HexagonII::TypeCVI_VM_TMP_LD
:
487 case HexagonII::TypeCVI_GATHER
:
488 case HexagonII::TypeCVI_GATHER_DV
:
489 case HexagonII::TypeCVI_GATHER_RST
:
490 ++Summary
.NonZCVIloads
;
492 case HexagonII::TypeCVI_ZW
:
493 ++Summary
.AllCVIloads
;
495 case HexagonII::TypeLD
:
498 if (ISJ
->Core
.getUnits() == slotSingleLoad
||
499 HexagonMCInstrInfo::getType(MCII
, ID
) == HexagonII::TypeCVI_VM_VP_LDU
)
501 if (HexagonMCInstrInfo::getDesc(MCII
, ID
).isReturn())
502 Summary
.branchInsts
.push_back(ISJ
);
504 case HexagonII::TypeCVI_VM_STU
:
505 case HexagonII::TypeCVI_VM_ST
:
506 case HexagonII::TypeCVI_VM_NEW_ST
:
507 case HexagonII::TypeCVI_SCATTER
:
508 case HexagonII::TypeCVI_SCATTER_DV
:
509 case HexagonII::TypeCVI_SCATTER_RST
:
510 case HexagonII::TypeCVI_SCATTER_NEW_RST
:
511 case HexagonII::TypeCVI_SCATTER_NEW_ST
:
514 case HexagonII::TypeST
:
517 if (ISJ
->Core
.getUnits() == slotSingleStore
||
518 HexagonMCInstrInfo::getType(MCII
, ID
) == HexagonII::TypeCVI_VM_STU
)
521 case HexagonII::TypeV4LDST
:
528 case HexagonII::TypeNCJ
:
529 ++Summary
.memory
; // NV insns are memory-like.
530 Summary
.branchInsts
.push_back(ISJ
);
532 case HexagonII::TypeV2LDST
:
533 if (HexagonMCInstrInfo::getDesc(MCII
, ID
).mayLoad()) {
536 if (ISJ
->Core
.getUnits() == slotSingleLoad
||
537 HexagonMCInstrInfo::getType(MCII
, ID
) ==
538 HexagonII::TypeCVI_VM_VP_LDU
)
541 assert(HexagonMCInstrInfo::getDesc(MCII
, ID
).mayStore());
546 case HexagonII::TypeCR
:
547 // Legacy conditional branch predicated on a register.
548 case HexagonII::TypeCJ
:
549 if (HexagonMCInstrInfo::getDesc(MCII
, ID
).isBranch())
550 Summary
.branchInsts
.push_back(ISJ
);
552 case HexagonII::TypeDUPLEX
: {
554 MCInst
const &Inst0
= *ID
.getOperand(0).getInst();
555 MCInst
const &Inst1
= *ID
.getOperand(1).getInst();
556 if (HexagonMCInstrInfo::getDesc(MCII
, Inst0
).isBranch())
557 Summary
.branchInsts
.push_back(ISJ
);
558 if (HexagonMCInstrInfo::getDesc(MCII
, Inst1
).isBranch())
559 Summary
.branchInsts
.push_back(ISJ
);
560 if (HexagonMCInstrInfo::getDesc(MCII
, Inst0
).isReturn())
561 Summary
.branchInsts
.push_back(ISJ
);
562 if (HexagonMCInstrInfo::getDesc(MCII
, Inst1
).isReturn())
563 Summary
.branchInsts
.push_back(ISJ
);
571 bool HexagonShuffler::ValidPacketMemoryOps(
572 HexagonPacketSummary
const &Summary
) const {
573 // Check if the packet is legal.
574 const unsigned ZCVIloads
= Summary
.AllCVIloads
- Summary
.NonZCVIloads
;
575 const bool ValidHVXMem
=
576 Summary
.NonZCVIloads
<= 1 && ZCVIloads
<= 1 && Summary
.CVIstores
<= 1;
577 const bool InvalidPacket
=
578 ((Summary
.load0
> 1 || Summary
.store0
> 1 || !ValidHVXMem
) ||
579 (Summary
.duplex
> 1 || (Summary
.duplex
&& Summary
.memory
)));
581 return !InvalidPacket
;
584 void HexagonShuffler::restrictPreferSlot3(HexagonPacketSummary
const &Summary
,
585 const bool DoShuffle
) {
586 // flag if an instruction requires to be in slot 3
587 const bool HasOnlySlot3
= llvm::any_of(insts(), [&](HexagonInstr
const &I
) {
588 return (I
.Core
.getUnits() == Slot3Mask
);
590 const bool NeedsPrefSlot3Shuffle
= Summary
.branchInsts
.size() <= 1 &&
591 !HasOnlySlot3
&& Summary
.pSlot3Cnt
== 1 &&
592 Summary
.PrefSlot3Inst
&& DoShuffle
;
594 if (!NeedsPrefSlot3Shuffle
)
597 HexagonInstr
*PrefSlot3Inst
= *Summary
.PrefSlot3Inst
;
598 // save off slot mask of instruction marked with A_PREFER_SLOT3
599 // and then pin it to slot #3
600 const unsigned saveUnits
= PrefSlot3Inst
->Core
.getUnits();
601 PrefSlot3Inst
->Core
.setUnits(saveUnits
& Slot3Mask
);
602 const bool HasShuffledPacket
= tryAuction(Summary
).has_value();
603 if (HasShuffledPacket
)
606 PrefSlot3Inst
->Core
.setUnits(saveUnits
);
609 /// Check that the packet is legal and enforce relative insn order.
610 bool HexagonShuffler::check(const bool RequireShuffle
) {
611 const HexagonPacketSummary Summary
= GetPacketSummary();
612 if (!applySlotRestrictions(Summary
, RequireShuffle
))
615 if (!ValidPacketMemoryOps(Summary
)) {
616 reportError("invalid instruction packet");
621 ValidResourceUsage(Summary
);
623 return !CheckFailure
;
626 std::optional
<HexagonShuffler::HexagonPacket
>
627 HexagonShuffler::tryAuction(HexagonPacketSummary
const &Summary
) {
628 HexagonPacket PacketResult
= Packet
;
629 HexagonUnitAuction
AuctionCore(Summary
.ReservedSlotMask
);
630 llvm::stable_sort(PacketResult
, HexagonInstr::lessCore
);
632 const bool ValidSlots
=
633 llvm::all_of(insts(PacketResult
), [&AuctionCore
](HexagonInstr
const &I
) {
634 return AuctionCore
.bid(I
.Core
.getUnits());
638 dbgs() << "Shuffle attempt: " << (ValidSlots
? "passed" : "failed")
640 for (HexagonInstr
const &ISJ
: insts(PacketResult
))
641 dbgs() << "\t" << HexagonMCInstrInfo::getName(MCII
, *ISJ
.ID
) << ": "
642 << llvm::format_hex(ISJ
.Core
.getUnits(), 4, true) << "\n";
645 std::optional
<HexagonPacket
> Res
;
652 bool HexagonShuffler::shuffle() {
653 if (size() > HEXAGON_PACKET_SIZE
) {
654 // Ignore a packet with more than what a packet can hold
655 // or with compound or duplex insns for now.
656 reportError("invalid instruction packet");
660 // Check and prepare packet.
662 if (size() > 1 && Ok
)
663 // Reorder the handles for each slot.
664 for (unsigned nSlot
= 0, emptySlots
= 0; nSlot
< HEXAGON_PACKET_SIZE
;
667 unsigned slotSkip
, slotWeight
;
669 // Prioritize the handles considering their restrictions.
670 for (ISJ
= ISK
= Packet
.begin(), slotSkip
= slotWeight
= 0;
671 ISK
!= Packet
.end(); ++ISK
, ++slotSkip
)
672 if (slotSkip
< nSlot
- emptySlots
)
673 // Note which handle to begin at.
676 // Calculate the weight of the slot.
677 slotWeight
+= ISK
->Core
.setWeight(HEXAGON_PACKET_SIZE
- nSlot
- 1);
680 // Sort the packet, favoring source order,
681 // beginning after the previous slot.
682 std::stable_sort(ISJ
, Packet
.end());
689 for (HexagonInstr
const &ISJ
: insts()) {
690 dbgs().write_hex(ISJ
.Core
.getUnits());
691 if (ISJ
.CVI
.isValid()) {
693 dbgs().write_hex(ISJ
.CVI
.getUnits()) << '|';
694 dbgs() << ISJ
.CVI
.getLanes();
697 << HexagonMCInstrInfo::getDesc(MCII
, ISJ
.getDesc()).getOpcode()
705 void HexagonShuffler::reportResourceError(HexagonPacketSummary
const &Summary
, StringRef Err
) {
707 reportResourceUsage(Summary
);
708 reportError(Twine("invalid instruction packet: ") + Err
);
712 void HexagonShuffler::reportResourceUsage(HexagonPacketSummary
const &Summary
) {
713 auto SM
= Context
.getSourceManager();
715 for (HexagonInstr
const &I
: insts()) {
716 const unsigned Units
= I
.Core
.getUnits();
718 if (HexagonMCInstrInfo::requiresSlot(STI
, *I
.ID
)) {
719 const std::string UnitsText
= Units
? SlotMaskToText(Units
) : "<None>";
720 SM
->PrintMessage(I
.ID
->getLoc(), SourceMgr::DK_Note
,
721 Twine("Instruction can utilize slots: ") +
724 else if (!HexagonMCInstrInfo::isImmext(*I
.ID
))
725 SM
->PrintMessage(I
.ID
->getLoc(), SourceMgr::DK_Note
,
726 "Instruction does not require a slot");
731 void HexagonShuffler::reportError(Twine
const &Msg
) {
734 for (auto const &I
: AppliedRestrictions
) {
735 auto SM
= Context
.getSourceManager();
737 SM
->PrintMessage(I
.first
, SourceMgr::DK_Note
, I
.second
);
739 Context
.reportError(Loc
, Msg
);