LLVM 24.0.0git
HexagonShuffler.cpp
Go to the documentation of this file.
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
20#include "llvm/ADT/Twine.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstrDesc.h"
26#include "llvm/Support/Debug.h"
29#include <algorithm>
30#include <cassert>
31#include <optional>
32#include <utility>
33
34#define DEBUG_TYPE "hexagon-shuffle"
35
36using namespace llvm;
37
38namespace {
39
40// Insn shuffling priority.
41class 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
48public:
49 HexagonBid() = default;
50 HexagonBid(unsigned B) { Bid = B ? MAX / llvm::popcount(B) : 0; }
51
52 // Check if the insn priority is overflowed.
53 bool isSold() const { return (Bid >= MAX); }
54
55 HexagonBid &operator+=(const HexagonBid &B) {
56 Bid += B.Bid;
57 return *this;
58 }
59};
60
61// Slot shuffling allocation.
62class HexagonUnitAuction {
63 HexagonBid Scores[HEXAGON_PACKET_SIZE];
64 // Mask indicating which slot is unavailable.
65 unsigned isSold : HEXAGON_PACKET_SIZE;
66
67public:
68 HexagonUnitAuction(unsigned cs = 0) : isSold(cs) {}
69
70 // Allocate slots.
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
90unsigned 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 = llvm::popcount(Units);
103 unsigned Cttz = llvm::countr_zero(Units);
104 Weight = (1u << (SlotWeight * s)) * ((MaskWeight - Ctpop) << Cttz);
105 return Weight;
106}
107
109 MCSubtargetInfo const &STI,
110 unsigned s,
111 MCInst const *id)
112 : HexagonResource(s) {
113
114 const unsigned ItinUnits = HexagonMCInstrInfo::getCVIResources(MCII, STI, *id);
115 unsigned Lanes;
116 const unsigned Units = HexagonConvertUnits(ItinUnits, &Lanes);
117
118 if (Units == 0 && Lanes == 0) {
119 // For core insns.
120 Valid = false;
121 setUnits(0);
122 setLanes(0);
123 setLoad(false);
124 setStore(false);
125 } else {
126 // For an HVX insn.
127 Valid = true;
128 setUnits(Units);
129 setLanes(Lanes);
130 setLoad(HexagonMCInstrInfo::getDesc(MCII, *id).mayLoad());
131 setStore(HexagonMCInstrInfo::getDesc(MCII, *id).mayStore());
132 }
133}
134
135struct CVIUnits {
136 unsigned Units;
137 unsigned Lanes;
138};
140
141static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
142{
143 for (unsigned i = 1; i < Lanes; ++i)
144 startBit = (startBit << 1) | startBit;
145 return startBit;
146}
147
148static 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)
155 continue;
156 unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes);
157 if ((allBits & usedUnits) == 0) {
158 if (checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits))
159 return true;
160 }
161 }
162 return false;
163 }
164 return true;
165}
166
174
176 Packet.clear();
177 BundleFlags = 0;
178 CheckFailure = false;
179}
180
181void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender,
182 unsigned S) {
183 HexagonInstr PI(MCII, STI, &ID, Extender, S);
184
185 Packet.push_back(PI);
186}
187
188
189static const unsigned Slot0Mask = 1 << 0;
190static const unsigned Slot1Mask = 1 << 1;
191static const unsigned Slot3Mask = 1 << 3;
192static const unsigned slotSingleLoad = Slot0Mask;
193static const unsigned slotSingleStore = Slot0Mask;
194
195void 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);
203 const unsigned Units = ISJ.Core.getUnits();
204
205 if (Units & Slot1Mask) {
206 AppliedRestrictions.push_back(std::make_pair(
207 Inst.getLoc(),
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);
213 }
214 }
215 }
216}
217
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
222 // this packet.
223
224 if (!Summary.NoSlot1StoreLoc)
225 return;
226
227 bool AppliedRestriction = false;
228
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);
238 }
239 }
240 }
241
242 if (AppliedRestriction)
243 AppliedRestrictions.push_back(
244 std::make_pair(*Summary.NoSlot1StoreLoc,
245 "Instruction does not allow a store in slot 1"));
246}
247
248bool 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);
255
257
258 // These restrictions can modify the slot masks in the instructions
259 // in the Packet member, but they can also detect constraint failures
260 // which are fatal.
261 if (!CheckFailure)
262 restrictStoreLoadOrder(Summary);
263 if (!CheckFailure)
264 restrictBranchOrder(Summary);
265 if (!CheckFailure)
266 restrictPreferSlot3(Summary, DoShuffle);
267 return !CheckFailure;
268}
269
270void HexagonShuffler::restrictBranchOrder(HexagonPacketSummary const &Summary) {
271 // preserve branch order
272 const bool HasMultipleBranches = Summary.branchInsts.size() > 1;
273 if (!HasMultipleBranches)
274 return;
275
276 if (Summary.branchInsts.size() > 2) {
277 reportError(Twine("too many branches in packet"));
278 return;
279 }
280
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()))
287 continue;
288
289 // validate second jump with this slot rule
290 if (!(jumpSlot.second & Summary.branchInsts[1]->Core.getUnits()))
291 continue;
292
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);
297
298 const bool HasShuffledPacket = tryAuction(Summary).has_value();
299 if (HasShuffledPacket)
300 return;
301
302 // if yes, great, if not then restore original slot mask
303 // restore original values
304 Packet = PacketSave;
305 }
306
307 reportResourceError(Summary, "out of slots");
308}
309
311 for (HexagonInstr &ISJ : insts()) {
312 const bool RequiresSlot = HexagonMCInstrInfo::requiresSlot(STI, *ISJ.ID);
313 if (!RequiresSlot)
314 ISJ.Core.setAllUnits();
315 }
316}
317
318bool HexagonShuffler::ValidResourceUsage(HexagonPacketSummary const &Summary) {
319 std::optional<HexagonPacket> ShuffledPacket = tryAuction(Summary);
320
321 if (!ShuffledPacket) {
322 reportResourceError(Summary, "slot error");
323 return false;
324 }
325
326 // Verify the CVI slot subscriptions.
328 // create vector of hvx instructions to check
329 HVXInstsT hvxInsts;
330 hvxInsts.clear();
331 for (const auto &I : *ShuffledPacket) {
332 struct CVIUnits inst;
333 inst.Units = I.CVI.getUnits();
334 inst.Lanes = I.CVI.getLanes();
335 if (inst.Units == 0)
336 continue; // not an hvx inst or an hvx inst that doesn't uses any pipes
337 hvxInsts.push_back(inst);
338 }
339
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"));
347 return false;
348 }
349 }
350
351 Packet = *ShuffledPacket;
352
353 return true;
354}
355
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;
363
364 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
365 MCInst const &ID = ISJ->getDesc();
366
367 if (!ISJ->Core.getUnits())
368 // Error if insn may not be executed in any slot.
369 return false;
370
371 unsigned SlotCount = llvm::popcount(ISJ->Core.getUnits());
372 // A single load must use slot #0, unless it can only execute in one slot
373 // (e.g. HLX loads, which must take slot #1).
374 if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad() && SlotCount > 1) {
375 if (Summary.loads == 1 && Summary.loads == Summary.memory &&
376 Summary.memops == 0)
377 // Pin the load to slot #0.
378 switch (ID.getOpcode()) {
379 case Hexagon::V6_vgathermw:
380 case Hexagon::V6_vgathermh:
381 case Hexagon::V6_vgathermhw:
382 case Hexagon::V6_vgathermwq:
383 case Hexagon::V6_vgathermhq:
384 case Hexagon::V6_vgathermhwq:
385 // Slot1 only loads
386 break;
387 default:
388 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
389 break;
390 }
391 else if (Summary.loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf
392 // Loads must keep the original order ONLY if
393 // isMemReorderDisabled() == true
394 if (slotLoadStore < slotLastLoadStore) {
395 // Error if no more slots available for loads.
396 reportError("invalid instruction packet: too many loads");
397 return false;
398 }
399 // Pin the load to the highest slot available to it.
400 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
401 // Update the next highest slot available to loads.
402 slotLoadStore >>= 1;
403 }
404 }
405
406 // A single store must use slot #0.
407 if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) {
408 if (!Summary.store0) {
409 const bool PacketHasNoOnlySlot0 =
410 llvm::none_of(insts(), [&](HexagonInstr const &I) {
411 return I.Core.getUnits() == Slot0Mask &&
412 I.ID->getOpcode() != ID.getOpcode();
413 });
414 const bool SafeToMoveToSlot0 =
415 (Summary.loads == 0) ||
416 (!isMemReorderDisabled() && PacketHasNoOnlySlot0);
417
418 if (Summary.stores == 1 && SafeToMoveToSlot0)
419 // Pin the store to slot #0 only if isMemReorderDisabled() == false
420 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
421 else if (Summary.stores >= 1) {
422 if (slotLoadStore < slotLastLoadStore) {
423 // Error if no more slots available for stores.
424 reportError("invalid instruction packet: too many stores");
425 return false;
426 }
427 // Pin the store to the highest slot available to it.
428 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
429 // Update the next highest slot available to stores.
430 slotLoadStore >>= 1;
431 }
432 }
433 if (Summary.store1 && Summary.stores > 1) {
434 // Error if a single store with another store.
435 reportError("invalid instruction packet: too many stores");
436 return false;
437 }
438 }
439 }
440
441 return true;
442}
443
444static std::string SlotMaskToText(unsigned SlotMask) {
446 for (unsigned SlotNum = 0; SlotNum < HEXAGON_PACKET_SIZE; SlotNum++)
447 if ((SlotMask & (1 << SlotNum)) != 0)
448 Slots.push_back(utostr(SlotNum));
449
450 return llvm::join(Slots, StringRef(", "));
451}
452
453HexagonShuffler::HexagonPacketSummary HexagonShuffler::GetPacketSummary() {
454 HexagonPacketSummary Summary = HexagonPacketSummary();
455
456 // Collect information from the insns in the packet.
457 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
458 MCInst const &ID = ISJ->getDesc();
459
461 Summary.Slot1AOKLoc = ID.getLoc();
463 Summary.NoSlot1StoreLoc = ID.getLoc();
464
466 ++Summary.pSlot3Cnt;
467 Summary.PrefSlot3Inst = ISJ;
468 }
469 const unsigned ReservedSlots =
471 Summary.ReservedSlotMask |= ReservedSlots;
472 if (ReservedSlots != 0)
473 AppliedRestrictions.push_back(std::make_pair(ID.getLoc(),
474 (Twine("Instruction has reserved slots: ") +
475 SlotMaskToText(ReservedSlots)).str()));
476
477 switch (HexagonMCInstrInfo::getType(MCII, ID)) {
481 break;
482 case HexagonII::TypeJ:
484 Summary.branchInsts.push_back(ISJ);
485 break;
492 ++Summary.NonZCVIloads;
493 [[fallthrough]];
495 ++Summary.AllCVIloads;
496 [[fallthrough]];
498 ++Summary.loads;
499 ++Summary.memory;
500 if (ISJ->Core.getUnits() == slotSingleLoad ||
502 ++Summary.load0;
503 if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn())
504 Summary.branchInsts.push_back(ISJ);
505 break;
514 ++Summary.CVIstores;
515 [[fallthrough]];
517 ++Summary.stores;
518 ++Summary.memory;
519 if (ISJ->Core.getUnits() == slotSingleStore ||
521 ++Summary.store0;
522 break;
524 ++Summary.loads;
525 ++Summary.stores;
526 ++Summary.store1;
527 ++Summary.memops;
528 ++Summary.memory;
529 break;
531 ++Summary.memory; // NV insns are memory-like.
532 Summary.branchInsts.push_back(ISJ);
533 break;
535 if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {
536 ++Summary.loads;
537 ++Summary.memory;
538 if (ISJ->Core.getUnits() == slotSingleLoad ||
541 ++Summary.load0;
542 } else {
543 assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore());
544 ++Summary.memory;
545 ++Summary.stores;
546 }
547 break;
549 // Legacy conditional branch predicated on a register.
552 Summary.branchInsts.push_back(ISJ);
553 break;
555 ++Summary.duplex;
556 MCInst const &Inst0 = *ID.getOperand(0).getInst();
557 MCInst const &Inst1 = *ID.getOperand(1).getInst();
559 Summary.branchInsts.push_back(ISJ);
561 Summary.branchInsts.push_back(ISJ);
562 if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn())
563 Summary.branchInsts.push_back(ISJ);
564 if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn())
565 Summary.branchInsts.push_back(ISJ);
566 break;
567 }
568 }
569 }
570 return Summary;
571}
572
574 HexagonPacketSummary const &Summary) const {
575 // Check if the packet is legal.
576 const unsigned ZCVIloads = Summary.AllCVIloads - Summary.NonZCVIloads;
577 const bool ValidHVXMem =
578 Summary.NonZCVIloads <= 1 && ZCVIloads <= 1 && Summary.CVIstores <= 1;
579 const bool InvalidPacket =
580 ((Summary.load0 > 1 || Summary.store0 > 1 || !ValidHVXMem) ||
581 (Summary.duplex > 1 || (Summary.duplex && Summary.memory)));
582
583 return !InvalidPacket;
584}
585
586void HexagonShuffler::restrictPreferSlot3(HexagonPacketSummary const &Summary,
587 const bool DoShuffle) {
588 // flag if an instruction requires to be in slot 3
589 const bool HasOnlySlot3 = llvm::any_of(insts(), [&](HexagonInstr const &I) {
590 return (I.Core.getUnits() == Slot3Mask);
591 });
592 const bool NeedsPrefSlot3Shuffle = Summary.branchInsts.size() <= 1 &&
593 !HasOnlySlot3 && Summary.pSlot3Cnt == 1 &&
594 Summary.PrefSlot3Inst && DoShuffle;
595
596 if (!NeedsPrefSlot3Shuffle)
597 return;
598
599 HexagonInstr *PrefSlot3Inst = *Summary.PrefSlot3Inst;
600 // save off slot mask of instruction marked with A_PREFER_SLOT3
601 // and then pin it to slot #3
602 const unsigned saveUnits = PrefSlot3Inst->Core.getUnits();
603 PrefSlot3Inst->Core.setUnits(saveUnits & Slot3Mask);
604 const bool HasShuffledPacket = tryAuction(Summary).has_value();
605 if (HasShuffledPacket)
606 return;
607
608 PrefSlot3Inst->Core.setUnits(saveUnits);
609}
610
611/// Check that the packet is legal and enforce relative insn order.
612bool HexagonShuffler::check(const bool RequireShuffle) {
613 const HexagonPacketSummary Summary = GetPacketSummary();
614 if (!applySlotRestrictions(Summary, RequireShuffle))
615 return false;
616
617 if (!ValidPacketMemoryOps(Summary)) {
618 reportError("invalid instruction packet");
619 return false;
620 }
621
622 if (RequireShuffle)
623 ValidResourceUsage(Summary);
624
625 return !CheckFailure;
626}
627
628std::optional<HexagonShuffler::HexagonPacket>
629HexagonShuffler::tryAuction(HexagonPacketSummary const &Summary) {
630 HexagonPacket PacketResult = Packet;
631 HexagonUnitAuction AuctionCore(Summary.ReservedSlotMask);
633
634 const bool ValidSlots =
635 llvm::all_of(insts(PacketResult), [&AuctionCore](HexagonInstr const &I) {
636 return AuctionCore.bid(I.Core.getUnits());
637 });
638
640 dbgs() << "Shuffle attempt: " << (ValidSlots ? "passed" : "failed")
641 << "\n";
642 for (HexagonInstr const &ISJ : insts(PacketResult))
643 dbgs() << "\t" << HexagonMCInstrInfo::getName(MCII, *ISJ.ID) << ": "
644 << llvm::format_hex(ISJ.Core.getUnits(), 4, true) << "\n";
645 );
646
647 std::optional<HexagonPacket> Res;
648 if (ValidSlots)
649 Res = PacketResult;
650
651 return Res;
652}
653
655 if (size() > HEXAGON_PACKET_SIZE) {
656 // Ignore a packet with more than what a packet can hold
657 // or with compound or duplex insns for now.
658 reportError("invalid instruction packet");
659 return false;
660 }
661
662 // Check and prepare packet.
663 bool Ok = check();
664 if (size() > 1 && Ok)
665 // Reorder the handles for each slot.
666 for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
667 ++nSlot) {
668 iterator ISJ, ISK;
669 unsigned slotSkip, slotWeight;
670
671 // Prioritize the handles considering their restrictions.
672 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
673 ISK != Packet.end(); ++ISK, ++slotSkip)
674 if (slotSkip < nSlot - emptySlots)
675 // Note which handle to begin at.
676 ++ISJ;
677 else
678 // Calculate the weight of the slot.
679 slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);
680
681 if (slotWeight)
682 // Sort the packet, favoring source order,
683 // beginning after the previous slot.
684 std::stable_sort(ISJ, Packet.end());
685 else
686 // Skip unused slot.
687 ++emptySlots;
688 }
689
691 for (HexagonInstr const &ISJ : insts()) {
692 dbgs().write_hex(ISJ.Core.getUnits());
693 if (ISJ.CVI.isValid()) {
694 dbgs() << '/';
695 dbgs().write_hex(ISJ.CVI.getUnits()) << '|';
696 dbgs() << ISJ.CVI.getLanes();
697 }
698 dbgs() << ':'
699 << HexagonMCInstrInfo::getDesc(MCII, ISJ.getDesc()).getOpcode()
700 << '\n';
701 } dbgs() << '\n';
702 );
703
704 return Ok;
705}
706
707void HexagonShuffler::reportResourceError(HexagonPacketSummary const &Summary, StringRef Err) {
708 if (ReportErrors)
709 reportResourceUsage(Summary);
710 reportError(Twine("invalid instruction packet: ") + Err);
711}
712
713
714void HexagonShuffler::reportResourceUsage(HexagonPacketSummary const &Summary) {
715 auto SM = Context.getSourceManager();
716 if (SM) {
717 for (HexagonInstr const &I : insts()) {
718 const unsigned Units = I.Core.getUnits();
719
721 const std::string UnitsText = Units ? SlotMaskToText(Units) : "<None>";
722 SM->PrintMessage(I.ID->getLoc(), SourceMgr::DK_Note,
723 Twine("Instruction can utilize slots: ") +
724 UnitsText);
725 }
726 else if (!HexagonMCInstrInfo::isImmext(*I.ID))
727 SM->PrintMessage(I.ID->getLoc(), SourceMgr::DK_Note,
728 "Instruction does not require a slot");
729 }
730 }
731}
732
734 CheckFailure = true;
735 if (ReportErrors) {
736 for (auto const &I : AppliedRestrictions) {
737 auto SM = Context.getSourceManager();
738 if (SM)
739 SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second);
740 }
741 Context.reportError(Loc, Msg);
742 }
743}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define HEXAGON_PACKET_SIZE
static const unsigned Slot1Mask
static const unsigned Slot0Mask
static std::string SlotMaskToText(unsigned SlotMask)
static const unsigned slotSingleLoad
static const unsigned slotSingleStore
static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx, unsigned usedUnits)
static const unsigned Slot3Mask
SmallVector< struct CVIUnits, 8 > HVXInstsT
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
#define I(x, y, z)
Definition MD5.cpp:57
static bool isBranch(unsigned Opcode)
const char * Msg
This file defines the SmallVector class.
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
HexagonCVIResource(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, unsigned s, MCInst const *id)
static bool lessCore(const HexagonInstr &A, const HexagonInstr &B)
static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B)
unsigned setWeight(unsigned s)
unsigned getUnits() const
void setUnits(unsigned s)
unsigned size() const
HexagonShuffler(MCContext &Context, bool ReportErrors, MCInstrInfo const &MCII, MCSubtargetInfo const &STI)
bool isMemReorderDisabled() const
void restrictNoSlot1Store(HexagonPacketSummary const &Summary)
bool check(const bool RequireShuffle=true)
Check that the packet is legal and enforce relative insn order.
void restrictSlot1AOK(HexagonPacketSummary const &Summary)
bool restrictStoreLoadOrder(HexagonPacketSummary const &Summary)
void reportError(Twine const &Msg)
HexagonPacket::iterator iterator
void reportResourceError(HexagonPacketSummary const &Summary, StringRef Err)
HexagonPacketSummary GetPacketSummary()
bool ValidResourceUsage(HexagonPacketSummary const &Summary)
MCSubtargetInfo const & STI
void restrictBranchOrder(HexagonPacketSummary const &Summary)
void append(MCInst const &ID, MCInst const *Extender, unsigned S)
bool applySlotRestrictions(HexagonPacketSummary const &Summary, const bool DoShuffle)
MCInstrInfo const & MCII
void reportResourceUsage(HexagonPacketSummary const &Summary)
bool ValidPacketMemoryOps(HexagonPacketSummary const &Summary) const
void restrictPreferSlot3(HexagonPacketSummary const &Summary, const bool DoShuffle)
std::vector< std::pair< SMLoc, std::string > > AppliedRestrictions
std::optional< HexagonPacket > tryAuction(HexagonPacketSummary const &Summary)
Context object for machine code objects.
Definition MCContext.h:83
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
SMLoc getLoc() const
Definition MCInst.h:208
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
unsigned getOpcode() const
Return the opcode number for this descriptor.
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
const MCInst * getInst() const
Definition MCInst.h:128
Generic base class for all target subtargets.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
bool isRestrictSlot1AOK(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn can be packaged only with an A-type insn in slot #1.
bool IsABranchingInst(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &I)
unsigned getCVIResources(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCI)
Return the resources used by this instruction.
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
Return the Hexagon ISA class for the insn.
bool isImmext(MCInst const &MCI)
unsigned getOtherReservedSlots(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCI)
Return the slots this instruction consumes in addition to the slot(s) it can execute out of.
bool requiresSlot(MCSubtargetInfo const &STI, MCInst const &MCI)
StringRef getName(MCInstrInfo const &MCII, MCInst const &MCI)
bool isRestrictNoSlot1Store(MCInstrInfo const &MCII, MCInst const &MCI)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
Definition STLExtras.h:2132
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
unsigned HexagonConvertUnits(unsigned ItinUnits, unsigned *Lanes)
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt & operator+=(DynamicAPInt &A, int64_t B)
std::string utostr(uint64_t X, bool isNeg=false)
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
Definition bit.h:156
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition Format.h:164
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.