brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.1 KiB · 2edcc0d Raw
742 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This implements the shuffling of insns inside a bundle according to the10// packet formation rules of the Hexagon ISA.11//12//===----------------------------------------------------------------------===//13 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"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 based43  // on its flexibility to run on the available slots.  So, the fewer slots it44  // 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    } else83      // Error if the desired slots are already full.84      return false;85  }86};87 88} // end anonymous namespace89 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 the97  // heavier the more restrictive the insn is and the lowest the slots that the98  // 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 108HexagonCVIResource::HexagonCVIResource(MCInstrInfo const &MCII,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};139using HVXInstsT = SmallVector<struct CVIUnits, 8>;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 167HexagonShuffler::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() {172  reset();173}174 175void HexagonShuffler::reset() {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);200      if (Type != HexagonII::TypeALU32_2op &&201          Type != HexagonII::TypeALU32_3op &&202          Type != HexagonII::TypeALU32_ADDI) {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 218void 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 in222  // 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 instructions251  // in the Packet member.  They should run unconditionally and their252  // order does not matter.253  restrictSlot1AOK(Summary);254  restrictNoSlot1Store(Summary);255 256  permitNonSlot();257 258  // These restrictions can modify the slot masks in the instructions259  // in the Packet member, but they can also detect constraint failures260  // 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 order272  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 choices284  for (std::pair<unsigned, unsigned> jumpSlot : jumpSlots) {285    // validate first jump with this slot rule286    if (!(jumpSlot.first & Summary.branchInsts[0]->Core.getUnits()))287      continue;288 289    // validate second jump with this slot rule290    if (!(jumpSlot.second & Summary.branchInsts[1]->Core.getUnits()))291      continue;292 293    // both valid for this configuration, set new slot rules294    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 mask303    // restore original values304    Packet = PacketSave;305  }306 307  reportResourceError(Summary, "out of slots");308}309 310void HexagonShuffler::permitNonSlot() {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.327  llvm::stable_sort(*ShuffledPacket, HexagonInstr::lessCVI);328  // create vector of hvx instructions to check329  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 pipes337    hvxInsts.push_back(inst);338  }339 340  // if there are any hvx instructions in this packet, check pipe usage341  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 valid346      reportError(Twine("invalid instruction packet: slot error"));347      return false;348    }349  }350 351  Packet = *ShuffledPacket;352 353  return true;354}355 356bool 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;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    // A single load must use slot #0.372    if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {373      if (Summary.loads == 1 && Summary.loads == Summary.memory &&374          Summary.memops == 0)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:383          // Slot1 only loads384          break;385        default:386          ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);387          break;388        }389      else if (Summary.loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf390        // Loads must keep the original order ONLY if391        // isMemReorderDisabled() == true392        if (slotLoadStore < slotLastLoadStore) {393          // Error if no more slots available for loads.394          reportError("invalid instruction packet: too many loads");395          return false;396        }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.400        slotLoadStore >>= 1;401      }402    }403 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();411            });412        const bool SafeToMoveToSlot0 =413            (Summary.loads == 0) ||414            (!isMemReorderDisabled() && PacketHasNoOnlySlot0);415 416        if (Summary.stores == 1 && SafeToMoveToSlot0)417          // Pin the store to slot #0 only if isMemReorderDisabled() == false418          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");423            return false;424          }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.428          slotLoadStore >>= 1;429        }430      }431      if (Summary.store1 && Summary.stores > 1) {432        // Error if a single store with another store.433        reportError("invalid instruction packet: too many stores");434        return false;435      }436    }437  }438 439  return true;440}441 442static 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));447 448    return llvm::join(Slots, StringRef(", "));449}450 451HexagonShuffler::HexagonPacketSummary HexagonShuffler::GetPacketSummary() {452  HexagonPacketSummary Summary = HexagonPacketSummary();453 454  // Collect information from the insns in the packet.455  for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {456    MCInst const &ID = ISJ->getDesc();457 458    if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII, ID))459      Summary.Slot1AOKLoc = ID.getLoc();460    if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII, ID))461      Summary.NoSlot1StoreLoc = ID.getLoc();462 463    if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) {464      ++Summary.pSlot3Cnt;465      Summary.PrefSlot3Inst = ISJ;466    }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()));474 475    switch (HexagonMCInstrInfo::getType(MCII, ID)) {476    case HexagonII::TypeS_2op:477    case HexagonII::TypeS_3op:478    case HexagonII::TypeALU64:479      break;480    case HexagonII::TypeJ:481      if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, *ISJ->ID))482        Summary.branchInsts.push_back(ISJ);483      break;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;491      [[fallthrough]];492    case HexagonII::TypeCVI_ZW:493      ++Summary.AllCVIloads;494      [[fallthrough]];495    case HexagonII::TypeLD:496      ++Summary.loads;497      ++Summary.memory;498      if (ISJ->Core.getUnits() == slotSingleLoad ||499          HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_VP_LDU)500        ++Summary.load0;501      if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn())502        Summary.branchInsts.push_back(ISJ);503      break;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:512      ++Summary.CVIstores;513      [[fallthrough]];514    case HexagonII::TypeST:515      ++Summary.stores;516      ++Summary.memory;517      if (ISJ->Core.getUnits() == slotSingleStore ||518          HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_STU)519        ++Summary.store0;520      break;521    case HexagonII::TypeV4LDST:522      ++Summary.loads;523      ++Summary.stores;524      ++Summary.store1;525      ++Summary.memops;526      ++Summary.memory;527      break;528    case HexagonII::TypeNCJ:529      ++Summary.memory; // NV insns are memory-like.530      Summary.branchInsts.push_back(ISJ);531      break;532    case HexagonII::TypeV2LDST:533      if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) {534        ++Summary.loads;535        ++Summary.memory;536        if (ISJ->Core.getUnits() == slotSingleLoad ||537            HexagonMCInstrInfo::getType(MCII, ID) ==538                HexagonII::TypeCVI_VM_VP_LDU)539          ++Summary.load0;540      } else {541        assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore());542        ++Summary.memory;543        ++Summary.stores;544      }545      break;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);551      break;552    case HexagonII::TypeDUPLEX: {553      ++Summary.duplex;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);564      break;565    }566    }567  }568  return Summary;569}570 571bool 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)));580 581  return !InvalidPacket;582}583 584void HexagonShuffler::restrictPreferSlot3(HexagonPacketSummary const &Summary,585                                          const bool DoShuffle) {586  // flag if an instruction requires to be in slot 3587  const bool HasOnlySlot3 = llvm::any_of(insts(), [&](HexagonInstr const &I) {588    return (I.Core.getUnits() == Slot3Mask);589  });590  const bool NeedsPrefSlot3Shuffle = Summary.branchInsts.size() <= 1 &&591                                     !HasOnlySlot3 && Summary.pSlot3Cnt == 1 &&592                                     Summary.PrefSlot3Inst && DoShuffle;593 594  if (!NeedsPrefSlot3Shuffle)595    return;596 597  HexagonInstr *PrefSlot3Inst = *Summary.PrefSlot3Inst;598  // save off slot mask of instruction marked with A_PREFER_SLOT3599  // and then pin it to slot #3600  const unsigned saveUnits = PrefSlot3Inst->Core.getUnits();601  PrefSlot3Inst->Core.setUnits(saveUnits & Slot3Mask);602  const bool HasShuffledPacket = tryAuction(Summary).has_value();603  if (HasShuffledPacket)604    return;605 606  PrefSlot3Inst->Core.setUnits(saveUnits);607}608 609/// Check that the packet is legal and enforce relative insn order.610bool HexagonShuffler::check(const bool RequireShuffle) {611  const HexagonPacketSummary Summary = GetPacketSummary();612  if (!applySlotRestrictions(Summary, RequireShuffle))613    return false;614 615  if (!ValidPacketMemoryOps(Summary)) {616    reportError("invalid instruction packet");617    return false;618  }619 620  if (RequireShuffle)621    ValidResourceUsage(Summary);622 623  return !CheckFailure;624}625 626std::optional<HexagonShuffler::HexagonPacket>627HexagonShuffler::tryAuction(HexagonPacketSummary const &Summary) {628  HexagonPacket PacketResult = Packet;629  HexagonUnitAuction AuctionCore(Summary.ReservedSlotMask);630  llvm::stable_sort(PacketResult, HexagonInstr::lessCore);631 632  const bool ValidSlots =633      llvm::all_of(insts(PacketResult), [&AuctionCore](HexagonInstr const &I) {634        return AuctionCore.bid(I.Core.getUnits());635      });636 637  LLVM_DEBUG(638    dbgs() << "Shuffle attempt: " << (ValidSlots ? "passed" : "failed")639           << "\n";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";643  );644 645  std::optional<HexagonPacket> Res;646  if (ValidSlots)647    Res = PacketResult;648 649  return Res;650}651 652bool HexagonShuffler::shuffle() {653  if (size() > HEXAGON_PACKET_SIZE) {654    // Ignore a packet with more than what a packet can hold655    // or with compound or duplex insns for now.656    reportError("invalid instruction packet");657    return false;658  }659 660  // Check and prepare packet.661  bool Ok = check();662  if (size() > 1 && Ok)663    // Reorder the handles for each slot.664    for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;665         ++nSlot) {666      iterator ISJ, ISK;667      unsigned slotSkip, slotWeight;668 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.674          ++ISJ;675        else676          // Calculate the weight of the slot.677          slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);678 679      if (slotWeight)680        // Sort the packet, favoring source order,681        // beginning after the previous slot.682        std::stable_sort(ISJ, Packet.end());683      else684        // Skip unused slot.685        ++emptySlots;686    }687 688  LLVM_DEBUG(689    for (HexagonInstr const &ISJ : insts()) {690      dbgs().write_hex(ISJ.Core.getUnits());691      if (ISJ.CVI.isValid()) {692        dbgs() << '/';693        dbgs().write_hex(ISJ.CVI.getUnits()) << '|';694        dbgs() << ISJ.CVI.getLanes();695      }696      dbgs() << ':'697             << HexagonMCInstrInfo::getDesc(MCII, ISJ.getDesc()).getOpcode()698             << '\n';699    } dbgs() << '\n';700  );701 702  return Ok;703}704 705void HexagonShuffler::reportResourceError(HexagonPacketSummary const &Summary, StringRef Err) {706  if (ReportErrors)707    reportResourceUsage(Summary);708  reportError(Twine("invalid instruction packet: ") + Err);709}710 711 712void HexagonShuffler::reportResourceUsage(HexagonPacketSummary const &Summary) {713  auto SM = Context.getSourceManager();714  if (SM) {715    for (HexagonInstr const &I : insts()) {716      const unsigned Units = I.Core.getUnits();717 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: ") +722                UnitsText);723      }724      else if (!HexagonMCInstrInfo::isImmext(*I.ID))725        SM->PrintMessage(I.ID->getLoc(), SourceMgr::DK_Note,726                       "Instruction does not require a slot");727    }728  }729}730 731void HexagonShuffler::reportError(Twine const &Msg) {732  CheckFailure = true;733  if (ReportErrors) {734    for (auto const &I : AppliedRestrictions) {735      auto SM = Context.getSourceManager();736      if (SM)737        SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second);738    }739    Context.reportError(Loc, Msg);740  }741}742