10b57cec5SDimitry Andric //===- HexagonShuffler.cpp - Instruction bundle shuffling -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This implements the shuffling of insns inside a bundle according to the 100b57cec5SDimitry Andric // packet formation rules of the Hexagon ISA. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "MCTargetDesc/HexagonShuffler.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/HexagonBaseInfo.h" 160b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h" 170b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 1906c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 200b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 210b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 250b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 260b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 270b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 280b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric #include <algorithm> 310b57cec5SDimitry Andric #include <cassert> 32bdd1243dSDimitry Andric #include <optional> 330b57cec5SDimitry Andric #include <utility> 340b57cec5SDimitry Andric 35fe6060f1SDimitry Andric #define DEBUG_TYPE "hexagon-shuffle" 36fe6060f1SDimitry Andric 370b57cec5SDimitry Andric using namespace llvm; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric namespace { 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric // Insn shuffling priority. 420b57cec5SDimitry Andric class HexagonBid { 430b57cec5SDimitry Andric // The priority is directly proportional to how restricted the insn is based 440b57cec5SDimitry Andric // on its flexibility to run on the available slots. So, the fewer slots it 450b57cec5SDimitry Andric // may run on, the higher its priority. 460b57cec5SDimitry Andric enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15. 470b57cec5SDimitry Andric unsigned Bid = 0; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric public: 500b57cec5SDimitry Andric HexagonBid() = default; 51bdd1243dSDimitry Andric HexagonBid(unsigned B) { Bid = B ? MAX / llvm::popcount(B) : 0; } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric // Check if the insn priority is overflowed. 540b57cec5SDimitry Andric bool isSold() const { return (Bid >= MAX); } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric HexagonBid &operator+=(const HexagonBid &B) { 570b57cec5SDimitry Andric Bid += B.Bid; 580b57cec5SDimitry Andric return *this; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric }; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // Slot shuffling allocation. 630b57cec5SDimitry Andric class HexagonUnitAuction { 640b57cec5SDimitry Andric HexagonBid Scores[HEXAGON_PACKET_SIZE]; 650b57cec5SDimitry Andric // Mask indicating which slot is unavailable. 660b57cec5SDimitry Andric unsigned isSold : HEXAGON_PACKET_SIZE; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric public: 690b57cec5SDimitry Andric HexagonUnitAuction(unsigned cs = 0) : isSold(cs) {} 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // Allocate slots. 720b57cec5SDimitry Andric bool bid(unsigned B) { 730b57cec5SDimitry Andric // Exclude already auctioned slots from the bid. 740b57cec5SDimitry Andric unsigned b = B & ~isSold; 750b57cec5SDimitry Andric if (b) { 760b57cec5SDimitry Andric for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i) 770b57cec5SDimitry Andric if (b & (1 << i)) { 780b57cec5SDimitry Andric // Request candidate slots. 790b57cec5SDimitry Andric Scores[i] += HexagonBid(b); 800b57cec5SDimitry Andric isSold |= Scores[i].isSold() << i; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric return true; 830b57cec5SDimitry Andric } else 840b57cec5SDimitry Andric // Error if the desired slots are already full. 850b57cec5SDimitry Andric return false; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric }; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric } // end anonymous namespace 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric unsigned HexagonResource::setWeight(unsigned s) { 920b57cec5SDimitry Andric const unsigned SlotWeight = 8; 930b57cec5SDimitry Andric const unsigned MaskWeight = SlotWeight - 1; 940b57cec5SDimitry Andric unsigned Units = getUnits(); 950b57cec5SDimitry Andric unsigned Key = ((1u << s) & Units) != 0; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric // Calculate relative weight of the insn for the given slot, weighing it the 980b57cec5SDimitry Andric // heavier the more restrictive the insn is and the lowest the slots that the 990b57cec5SDimitry Andric // insn may be executed in. 1000b57cec5SDimitry Andric if (Key == 0 || Units == 0 || (SlotWeight * s >= 32)) 1010b57cec5SDimitry Andric return Weight = 0; 1020b57cec5SDimitry Andric 103bdd1243dSDimitry Andric unsigned Ctpop = llvm::popcount(Units); 10406c3fb27SDimitry Andric unsigned Cttz = llvm::countr_zero(Units); 1050b57cec5SDimitry Andric Weight = (1u << (SlotWeight * s)) * ((MaskWeight - Ctpop) << Cttz); 1060b57cec5SDimitry Andric return Weight; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric 1095ffd83dbSDimitry Andric HexagonCVIResource::HexagonCVIResource(MCInstrInfo const &MCII, 1105ffd83dbSDimitry Andric MCSubtargetInfo const &STI, 1115ffd83dbSDimitry Andric unsigned s, 1120b57cec5SDimitry Andric MCInst const *id) 1130b57cec5SDimitry Andric : HexagonResource(s) { 1140b57cec5SDimitry Andric 1155ffd83dbSDimitry Andric const unsigned ItinUnits = HexagonMCInstrInfo::getCVIResources(MCII, STI, *id); 1165ffd83dbSDimitry Andric unsigned Lanes; 1175ffd83dbSDimitry Andric const unsigned Units = HexagonConvertUnits(ItinUnits, &Lanes); 1185ffd83dbSDimitry Andric 1195ffd83dbSDimitry Andric if (Units == 0 && Lanes == 0) { 1200b57cec5SDimitry Andric // For core insns. 1210b57cec5SDimitry Andric Valid = false; 1220b57cec5SDimitry Andric setUnits(0); 1230b57cec5SDimitry Andric setLanes(0); 1240b57cec5SDimitry Andric setLoad(false); 1250b57cec5SDimitry Andric setStore(false); 1265ffd83dbSDimitry Andric } else { 1275ffd83dbSDimitry Andric // For an HVX insn. 1285ffd83dbSDimitry Andric Valid = true; 1295ffd83dbSDimitry Andric setUnits(Units); 1305ffd83dbSDimitry Andric setLanes(Lanes); 1315ffd83dbSDimitry Andric setLoad(HexagonMCInstrInfo::getDesc(MCII, *id).mayLoad()); 1325ffd83dbSDimitry Andric setStore(HexagonMCInstrInfo::getDesc(MCII, *id).mayStore()); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric struct CVIUnits { 1370b57cec5SDimitry Andric unsigned Units; 1380b57cec5SDimitry Andric unsigned Lanes; 1390b57cec5SDimitry Andric }; 1400b57cec5SDimitry Andric using HVXInstsT = SmallVector<struct CVIUnits, 8>; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric static unsigned makeAllBits(unsigned startBit, unsigned Lanes) 1430b57cec5SDimitry Andric { 1440b57cec5SDimitry Andric for (unsigned i = 1; i < Lanes; ++i) 1450b57cec5SDimitry Andric startBit = (startBit << 1) | startBit; 1460b57cec5SDimitry Andric return startBit; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx, 1500b57cec5SDimitry Andric unsigned usedUnits) { 1510b57cec5SDimitry Andric if (startIdx < hvxInsts.size()) { 1520b57cec5SDimitry Andric if (!hvxInsts[startIdx].Units) 1530b57cec5SDimitry Andric return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits); 1540b57cec5SDimitry Andric for (unsigned b = 0x1; b <= 0x8; b <<= 1) { 1550b57cec5SDimitry Andric if ((hvxInsts[startIdx].Units & b) == 0) 1560b57cec5SDimitry Andric continue; 1570b57cec5SDimitry Andric unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes); 1580b57cec5SDimitry Andric if ((allBits & usedUnits) == 0) { 1590b57cec5SDimitry Andric if (checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits)) 1600b57cec5SDimitry Andric return true; 1610b57cec5SDimitry Andric } 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric return false; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric return true; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric HexagonShuffler::HexagonShuffler(MCContext &Context, bool ReportErrors, 1690b57cec5SDimitry Andric MCInstrInfo const &MCII, 1700b57cec5SDimitry Andric MCSubtargetInfo const &STI) 17104eeddc0SDimitry Andric : Context(Context), BundleFlags(), MCII(MCII), STI(STI), 17204eeddc0SDimitry Andric ReportErrors(ReportErrors), CheckFailure() { 1730b57cec5SDimitry Andric reset(); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void HexagonShuffler::reset() { 1770b57cec5SDimitry Andric Packet.clear(); 1780b57cec5SDimitry Andric BundleFlags = 0; 1795ffd83dbSDimitry Andric CheckFailure = false; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender, 1830b57cec5SDimitry Andric unsigned S) { 1845ffd83dbSDimitry Andric HexagonInstr PI(MCII, STI, &ID, Extender, S); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric Packet.push_back(PI); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric 1905ffd83dbSDimitry Andric static const unsigned Slot0Mask = 1 << 0; 1915ffd83dbSDimitry Andric static const unsigned Slot1Mask = 1 << 1; 1925ffd83dbSDimitry Andric static const unsigned Slot3Mask = 1 << 3; 1935ffd83dbSDimitry Andric static const unsigned slotSingleLoad = Slot0Mask; 1945ffd83dbSDimitry Andric static const unsigned slotSingleStore = Slot0Mask; 1955ffd83dbSDimitry Andric 1965ffd83dbSDimitry Andric void HexagonShuffler::restrictSlot1AOK(HexagonPacketSummary const &Summary) { 1975ffd83dbSDimitry Andric if (Summary.Slot1AOKLoc) 1985ffd83dbSDimitry Andric for (HexagonInstr &ISJ : insts()) { 1995ffd83dbSDimitry Andric MCInst const &Inst = ISJ.getDesc(); 2005ffd83dbSDimitry Andric const unsigned Type = HexagonMCInstrInfo::getType(MCII, Inst); 2010b57cec5SDimitry Andric if (Type != HexagonII::TypeALU32_2op && 2020b57cec5SDimitry Andric Type != HexagonII::TypeALU32_3op && 2030b57cec5SDimitry Andric Type != HexagonII::TypeALU32_ADDI) { 2045ffd83dbSDimitry Andric const unsigned Units = ISJ.Core.getUnits(); 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric if (Units & Slot1Mask) { 2070b57cec5SDimitry Andric AppliedRestrictions.push_back(std::make_pair( 2080b57cec5SDimitry Andric Inst.getLoc(), 2090b57cec5SDimitry Andric "Instruction was restricted from being in slot 1")); 2105ffd83dbSDimitry Andric AppliedRestrictions.push_back(std::make_pair( 2115ffd83dbSDimitry Andric *Summary.Slot1AOKLoc, "Instruction can only be combined " 2120b57cec5SDimitry Andric "with an ALU instruction in slot 1")); 2135ffd83dbSDimitry Andric ISJ.Core.setUnits(Units & ~Slot1Mask); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2195ffd83dbSDimitry Andric void HexagonShuffler::restrictNoSlot1Store( 2205ffd83dbSDimitry Andric HexagonPacketSummary const &Summary) { 2215ffd83dbSDimitry Andric // If this packet contains an instruction that bars slot-1 stores, 2225ffd83dbSDimitry Andric // we should mask off slot 1 from all of the store instructions in 2235ffd83dbSDimitry Andric // this packet. 2245ffd83dbSDimitry Andric 2255ffd83dbSDimitry Andric if (!Summary.NoSlot1StoreLoc) 2265ffd83dbSDimitry Andric return; 2275ffd83dbSDimitry Andric 2280b57cec5SDimitry Andric bool AppliedRestriction = false; 2295ffd83dbSDimitry Andric 2305ffd83dbSDimitry Andric for (HexagonInstr &ISJ : insts()) { 2315ffd83dbSDimitry Andric MCInst const &Inst = ISJ.getDesc(); 2320b57cec5SDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, Inst).mayStore()) { 2335ffd83dbSDimitry Andric unsigned Units = ISJ.Core.getUnits(); 2345ffd83dbSDimitry Andric if (Units & Slot1Mask) { 2350b57cec5SDimitry Andric AppliedRestriction = true; 2360b57cec5SDimitry Andric AppliedRestrictions.push_back(std::make_pair( 2375ffd83dbSDimitry Andric Inst.getLoc(), "Instruction was restricted from being in slot 1")); 2385ffd83dbSDimitry Andric ISJ.Core.setUnits(Units & ~Slot1Mask); 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric } 2425ffd83dbSDimitry Andric 2430b57cec5SDimitry Andric if (AppliedRestriction) 2445ffd83dbSDimitry Andric AppliedRestrictions.push_back( 2455ffd83dbSDimitry Andric std::make_pair(*Summary.NoSlot1StoreLoc, 2465ffd83dbSDimitry Andric "Instruction does not allow a store in slot 1")); 2475ffd83dbSDimitry Andric } 2485ffd83dbSDimitry Andric 24904eeddc0SDimitry Andric bool HexagonShuffler::applySlotRestrictions(HexagonPacketSummary const &Summary, 25004eeddc0SDimitry Andric const bool DoShuffle) { 2515ffd83dbSDimitry Andric // These restrictions can modify the slot masks in the instructions 2525ffd83dbSDimitry Andric // in the Packet member. They should run unconditionally and their 2535ffd83dbSDimitry Andric // order does not matter. 2545ffd83dbSDimitry Andric restrictSlot1AOK(Summary); 2555ffd83dbSDimitry Andric restrictNoSlot1Store(Summary); 2565ffd83dbSDimitry Andric 2575ffd83dbSDimitry Andric permitNonSlot(); 2585ffd83dbSDimitry Andric 2595ffd83dbSDimitry Andric // These restrictions can modify the slot masks in the instructions 2605ffd83dbSDimitry Andric // in the Packet member, but they can also detect constraint failures 2615ffd83dbSDimitry Andric // which are fatal. 2625ffd83dbSDimitry Andric if (!CheckFailure) 2635ffd83dbSDimitry Andric restrictStoreLoadOrder(Summary); 2645ffd83dbSDimitry Andric if (!CheckFailure) 2655ffd83dbSDimitry Andric restrictBranchOrder(Summary); 2665ffd83dbSDimitry Andric if (!CheckFailure) 26704eeddc0SDimitry Andric restrictPreferSlot3(Summary, DoShuffle); 2685ffd83dbSDimitry Andric return !CheckFailure; 2695ffd83dbSDimitry Andric } 2705ffd83dbSDimitry Andric 2715ffd83dbSDimitry Andric void HexagonShuffler::restrictBranchOrder(HexagonPacketSummary const &Summary) { 2725ffd83dbSDimitry Andric // preserve branch order 2735ffd83dbSDimitry Andric const bool HasMultipleBranches = Summary.branchInsts.size() > 1; 2745ffd83dbSDimitry Andric if (!HasMultipleBranches) 2755ffd83dbSDimitry Andric return; 2765ffd83dbSDimitry Andric 2775ffd83dbSDimitry Andric if (Summary.branchInsts.size() > 2) { 2785ffd83dbSDimitry Andric reportError(Twine("too many branches in packet")); 2795ffd83dbSDimitry Andric return; 2805ffd83dbSDimitry Andric } 2815ffd83dbSDimitry Andric 2825ffd83dbSDimitry Andric const static std::pair<unsigned, unsigned> jumpSlots[] = { 2835ffd83dbSDimitry Andric {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}}; 2845ffd83dbSDimitry Andric // try all possible choices 2855ffd83dbSDimitry Andric for (std::pair<unsigned, unsigned> jumpSlot : jumpSlots) { 2865ffd83dbSDimitry Andric // validate first jump with this slot rule 2875ffd83dbSDimitry Andric if (!(jumpSlot.first & Summary.branchInsts[0]->Core.getUnits())) 2885ffd83dbSDimitry Andric continue; 2895ffd83dbSDimitry Andric 2905ffd83dbSDimitry Andric // validate second jump with this slot rule 2915ffd83dbSDimitry Andric if (!(jumpSlot.second & Summary.branchInsts[1]->Core.getUnits())) 2925ffd83dbSDimitry Andric continue; 2935ffd83dbSDimitry Andric 2945ffd83dbSDimitry Andric // both valid for this configuration, set new slot rules 2955ffd83dbSDimitry Andric const HexagonPacket PacketSave = Packet; 2965ffd83dbSDimitry Andric Summary.branchInsts[0]->Core.setUnits(jumpSlot.first); 2975ffd83dbSDimitry Andric Summary.branchInsts[1]->Core.setUnits(jumpSlot.second); 2985ffd83dbSDimitry Andric 29981ad6265SDimitry Andric const bool HasShuffledPacket = tryAuction(Summary).has_value(); 3005ffd83dbSDimitry Andric if (HasShuffledPacket) 3015ffd83dbSDimitry Andric return; 3025ffd83dbSDimitry Andric 3035ffd83dbSDimitry Andric // if yes, great, if not then restore original slot mask 3045ffd83dbSDimitry Andric // restore original values 3055ffd83dbSDimitry Andric Packet = PacketSave; 3065ffd83dbSDimitry Andric } 3075ffd83dbSDimitry Andric 30804eeddc0SDimitry Andric reportResourceError(Summary, "out of slots"); 3095ffd83dbSDimitry Andric } 3105ffd83dbSDimitry Andric 3115ffd83dbSDimitry Andric void HexagonShuffler::permitNonSlot() { 3125ffd83dbSDimitry Andric for (HexagonInstr &ISJ : insts()) { 3135ffd83dbSDimitry Andric const bool RequiresSlot = HexagonMCInstrInfo::requiresSlot(STI, *ISJ.ID); 3145ffd83dbSDimitry Andric if (!RequiresSlot) 3155ffd83dbSDimitry Andric ISJ.Core.setAllUnits(); 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3195ffd83dbSDimitry Andric bool HexagonShuffler::ValidResourceUsage(HexagonPacketSummary const &Summary) { 320bdd1243dSDimitry Andric std::optional<HexagonPacket> ShuffledPacket = tryAuction(Summary); 3210b57cec5SDimitry Andric 3225ffd83dbSDimitry Andric if (!ShuffledPacket) { 32304eeddc0SDimitry Andric reportResourceError(Summary, "slot error"); 3245ffd83dbSDimitry Andric return false; 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3275ffd83dbSDimitry Andric // Verify the CVI slot subscriptions. 32804eeddc0SDimitry Andric llvm::stable_sort(*ShuffledPacket, HexagonInstr::lessCVI); 3295ffd83dbSDimitry Andric // create vector of hvx instructions to check 3305ffd83dbSDimitry Andric HVXInstsT hvxInsts; 3315ffd83dbSDimitry Andric hvxInsts.clear(); 33204eeddc0SDimitry Andric for (const auto &I : *ShuffledPacket) { 3335ffd83dbSDimitry Andric struct CVIUnits inst; 33404eeddc0SDimitry Andric inst.Units = I.CVI.getUnits(); 33504eeddc0SDimitry Andric inst.Lanes = I.CVI.getLanes(); 3365ffd83dbSDimitry Andric if (inst.Units == 0) 3375ffd83dbSDimitry Andric continue; // not an hvx inst or an hvx inst that doesn't uses any pipes 3385ffd83dbSDimitry Andric hvxInsts.push_back(inst); 3395ffd83dbSDimitry Andric } 3405ffd83dbSDimitry Andric 3415ffd83dbSDimitry Andric // if there are any hvx instructions in this packet, check pipe usage 3425ffd83dbSDimitry Andric if (hvxInsts.size() > 0) { 3435ffd83dbSDimitry Andric unsigned startIdx, usedUnits; 3445ffd83dbSDimitry Andric startIdx = usedUnits = 0x0; 3455ffd83dbSDimitry Andric if (!checkHVXPipes(hvxInsts, startIdx, usedUnits)) { 3465ffd83dbSDimitry Andric // too many pipes used to be valid 3475ffd83dbSDimitry Andric reportError(Twine("invalid instruction packet: slot error")); 3480b57cec5SDimitry Andric return false; 3490b57cec5SDimitry Andric } 3505ffd83dbSDimitry Andric } 35104eeddc0SDimitry Andric 35204eeddc0SDimitry Andric Packet = *ShuffledPacket; 35304eeddc0SDimitry Andric 3545ffd83dbSDimitry Andric return true; 3555ffd83dbSDimitry Andric } 3560b57cec5SDimitry Andric 3575ffd83dbSDimitry Andric bool HexagonShuffler::restrictStoreLoadOrder( 3585ffd83dbSDimitry Andric HexagonPacketSummary const &Summary) { 3590b57cec5SDimitry Andric // Modify packet accordingly. 3600b57cec5SDimitry Andric // TODO: need to reserve slots #0 and #1 for duplex insns. 3615ffd83dbSDimitry Andric static const unsigned slotFirstLoadStore = Slot1Mask; 3625ffd83dbSDimitry Andric static const unsigned slotLastLoadStore = Slot0Mask; 3635ffd83dbSDimitry Andric unsigned slotLoadStore = slotFirstLoadStore; 3645ffd83dbSDimitry Andric 3650b57cec5SDimitry Andric for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { 3660b57cec5SDimitry Andric MCInst const &ID = ISJ->getDesc(); 3670b57cec5SDimitry Andric 3685ffd83dbSDimitry Andric if (!ISJ->Core.getUnits()) 3690b57cec5SDimitry Andric // Error if insn may not be executed in any slot. 3700b57cec5SDimitry Andric return false; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // A single load must use slot #0. 3730b57cec5SDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) { 3745ffd83dbSDimitry Andric if (Summary.loads == 1 && Summary.loads == Summary.memory && 3755ffd83dbSDimitry Andric Summary.memops == 0) 3760b57cec5SDimitry Andric // Pin the load to slot #0. 3770b57cec5SDimitry Andric switch (ID.getOpcode()) { 3780b57cec5SDimitry Andric case Hexagon::V6_vgathermw: 3790b57cec5SDimitry Andric case Hexagon::V6_vgathermh: 3800b57cec5SDimitry Andric case Hexagon::V6_vgathermhw: 3810b57cec5SDimitry Andric case Hexagon::V6_vgathermwq: 3820b57cec5SDimitry Andric case Hexagon::V6_vgathermhq: 3830b57cec5SDimitry Andric case Hexagon::V6_vgathermhwq: 3840b57cec5SDimitry Andric // Slot1 only loads 3850b57cec5SDimitry Andric break; 3860b57cec5SDimitry Andric default: 3870b57cec5SDimitry Andric ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad); 3880b57cec5SDimitry Andric break; 3890b57cec5SDimitry Andric } 3905ffd83dbSDimitry Andric else if (Summary.loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf 3910b57cec5SDimitry Andric // Loads must keep the original order ONLY if 3920b57cec5SDimitry Andric // isMemReorderDisabled() == true 3930b57cec5SDimitry Andric if (slotLoadStore < slotLastLoadStore) { 3940b57cec5SDimitry Andric // Error if no more slots available for loads. 3955ffd83dbSDimitry Andric reportError("invalid instruction packet: too many loads"); 3960b57cec5SDimitry Andric return false; 3970b57cec5SDimitry Andric } 3980b57cec5SDimitry Andric // Pin the load to the highest slot available to it. 3990b57cec5SDimitry Andric ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore); 4000b57cec5SDimitry Andric // Update the next highest slot available to loads. 4010b57cec5SDimitry Andric slotLoadStore >>= 1; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric // A single store must use slot #0. 4060b57cec5SDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) { 4075ffd83dbSDimitry Andric if (!Summary.store0) { 4085ffd83dbSDimitry Andric const bool PacketHasNoOnlySlot0 = 4095ffd83dbSDimitry Andric llvm::none_of(insts(), [&](HexagonInstr const &I) { 4105ffd83dbSDimitry Andric return I.Core.getUnits() == Slot0Mask && 4115ffd83dbSDimitry Andric I.ID->getOpcode() != ID.getOpcode(); 4125ffd83dbSDimitry Andric }); 4135ffd83dbSDimitry Andric const bool SafeToMoveToSlot0 = 4145ffd83dbSDimitry Andric (Summary.loads == 0) || 4155ffd83dbSDimitry Andric (!isMemReorderDisabled() && PacketHasNoOnlySlot0); 4165ffd83dbSDimitry Andric 4175ffd83dbSDimitry Andric if (Summary.stores == 1 && SafeToMoveToSlot0) 4180b57cec5SDimitry Andric // Pin the store to slot #0 only if isMemReorderDisabled() == false 4190b57cec5SDimitry Andric ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore); 4205ffd83dbSDimitry Andric else if (Summary.stores >= 1) { 4210b57cec5SDimitry Andric if (slotLoadStore < slotLastLoadStore) { 4220b57cec5SDimitry Andric // Error if no more slots available for stores. 4235ffd83dbSDimitry Andric reportError("invalid instruction packet: too many stores"); 4240b57cec5SDimitry Andric return false; 4250b57cec5SDimitry Andric } 4260b57cec5SDimitry Andric // Pin the store to the highest slot available to it. 4270b57cec5SDimitry Andric ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore); 4280b57cec5SDimitry Andric // Update the next highest slot available to stores. 4290b57cec5SDimitry Andric slotLoadStore >>= 1; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric } 4325ffd83dbSDimitry Andric if (Summary.store1 && Summary.stores > 1) { 4330b57cec5SDimitry Andric // Error if a single store with another store. 4345ffd83dbSDimitry Andric reportError("invalid instruction packet: too many stores"); 4350b57cec5SDimitry Andric return false; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric return true; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 44304eeddc0SDimitry Andric static std::string SlotMaskToText(unsigned SlotMask) { 44404eeddc0SDimitry Andric SmallVector<std::string, HEXAGON_PRESHUFFLE_PACKET_SIZE> Slots; 44504eeddc0SDimitry Andric for (unsigned SlotNum = 0; SlotNum < HEXAGON_PACKET_SIZE; SlotNum++) 44604eeddc0SDimitry Andric if ((SlotMask & (1 << SlotNum)) != 0) 44704eeddc0SDimitry Andric Slots.push_back(utostr(SlotNum)); 44804eeddc0SDimitry Andric 44904eeddc0SDimitry Andric return llvm::join(Slots, StringRef(", ")); 45004eeddc0SDimitry Andric } 45104eeddc0SDimitry Andric 4525ffd83dbSDimitry Andric HexagonShuffler::HexagonPacketSummary HexagonShuffler::GetPacketSummary() { 4535ffd83dbSDimitry Andric HexagonPacketSummary Summary = HexagonPacketSummary(); 4545ffd83dbSDimitry Andric 4555ffd83dbSDimitry Andric // Collect information from the insns in the packet. 4565ffd83dbSDimitry Andric for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { 4575ffd83dbSDimitry Andric MCInst const &ID = ISJ->getDesc(); 4585ffd83dbSDimitry Andric 4595ffd83dbSDimitry Andric if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII, ID)) 4605ffd83dbSDimitry Andric Summary.Slot1AOKLoc = ID.getLoc(); 4615ffd83dbSDimitry Andric if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII, ID)) 4625ffd83dbSDimitry Andric Summary.NoSlot1StoreLoc = ID.getLoc(); 4635ffd83dbSDimitry Andric 4645ffd83dbSDimitry Andric if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) { 4655ffd83dbSDimitry Andric ++Summary.pSlot3Cnt; 4665ffd83dbSDimitry Andric Summary.PrefSlot3Inst = ISJ; 4675ffd83dbSDimitry Andric } 46804eeddc0SDimitry Andric const unsigned ReservedSlots = 4695ffd83dbSDimitry Andric HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID); 47004eeddc0SDimitry Andric Summary.ReservedSlotMask |= ReservedSlots; 47104eeddc0SDimitry Andric if (ReservedSlots != 0) 47204eeddc0SDimitry Andric AppliedRestrictions.push_back(std::make_pair(ID.getLoc(), 47304eeddc0SDimitry Andric (Twine("Instruction has reserved slots: ") + 47404eeddc0SDimitry Andric SlotMaskToText(ReservedSlots)).str())); 4755ffd83dbSDimitry Andric 4765ffd83dbSDimitry Andric switch (HexagonMCInstrInfo::getType(MCII, ID)) { 4775ffd83dbSDimitry Andric case HexagonII::TypeS_2op: 4785ffd83dbSDimitry Andric case HexagonII::TypeS_3op: 4795ffd83dbSDimitry Andric case HexagonII::TypeALU64: 4805ffd83dbSDimitry Andric break; 4815ffd83dbSDimitry Andric case HexagonII::TypeJ: 48204eeddc0SDimitry Andric if (HexagonMCInstrInfo::IsABranchingInst(MCII, STI, *ISJ->ID)) 4835ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 4845ffd83dbSDimitry Andric break; 4855ffd83dbSDimitry Andric case HexagonII::TypeCVI_VM_VP_LDU: 4865ffd83dbSDimitry Andric case HexagonII::TypeCVI_VM_LD: 4875ffd83dbSDimitry Andric case HexagonII::TypeCVI_VM_TMP_LD: 4885ffd83dbSDimitry Andric case HexagonII::TypeCVI_GATHER: 4895ffd83dbSDimitry Andric case HexagonII::TypeCVI_GATHER_DV: 4905ffd83dbSDimitry Andric case HexagonII::TypeCVI_GATHER_RST: 4915ffd83dbSDimitry Andric ++Summary.NonZCVIloads; 492bdd1243dSDimitry Andric [[fallthrough]]; 4935ffd83dbSDimitry Andric case HexagonII::TypeCVI_ZW: 4945ffd83dbSDimitry Andric ++Summary.AllCVIloads; 495bdd1243dSDimitry Andric [[fallthrough]]; 4965ffd83dbSDimitry Andric case HexagonII::TypeLD: 4975ffd83dbSDimitry Andric ++Summary.loads; 4985ffd83dbSDimitry Andric ++Summary.memory; 4995ffd83dbSDimitry Andric if (ISJ->Core.getUnits() == slotSingleLoad || 5005ffd83dbSDimitry Andric HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_VP_LDU) 5015ffd83dbSDimitry Andric ++Summary.load0; 5025ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) 5035ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5045ffd83dbSDimitry Andric break; 5055ffd83dbSDimitry Andric case HexagonII::TypeCVI_VM_STU: 5065ffd83dbSDimitry Andric case HexagonII::TypeCVI_VM_ST: 5075ffd83dbSDimitry Andric case HexagonII::TypeCVI_VM_NEW_ST: 5085ffd83dbSDimitry Andric case HexagonII::TypeCVI_SCATTER: 5095ffd83dbSDimitry Andric case HexagonII::TypeCVI_SCATTER_DV: 5105ffd83dbSDimitry Andric case HexagonII::TypeCVI_SCATTER_RST: 5115ffd83dbSDimitry Andric case HexagonII::TypeCVI_SCATTER_NEW_RST: 5125ffd83dbSDimitry Andric case HexagonII::TypeCVI_SCATTER_NEW_ST: 5135ffd83dbSDimitry Andric ++Summary.CVIstores; 514bdd1243dSDimitry Andric [[fallthrough]]; 5155ffd83dbSDimitry Andric case HexagonII::TypeST: 5165ffd83dbSDimitry Andric ++Summary.stores; 5175ffd83dbSDimitry Andric ++Summary.memory; 5185ffd83dbSDimitry Andric if (ISJ->Core.getUnits() == slotSingleStore || 5195ffd83dbSDimitry Andric HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_STU) 5205ffd83dbSDimitry Andric ++Summary.store0; 5215ffd83dbSDimitry Andric break; 5225ffd83dbSDimitry Andric case HexagonII::TypeV4LDST: 5235ffd83dbSDimitry Andric ++Summary.loads; 5245ffd83dbSDimitry Andric ++Summary.stores; 5255ffd83dbSDimitry Andric ++Summary.store1; 5265ffd83dbSDimitry Andric ++Summary.memops; 5275ffd83dbSDimitry Andric ++Summary.memory; 5285ffd83dbSDimitry Andric break; 5295ffd83dbSDimitry Andric case HexagonII::TypeNCJ: 5305ffd83dbSDimitry Andric ++Summary.memory; // NV insns are memory-like. 5315ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5325ffd83dbSDimitry Andric break; 5335ffd83dbSDimitry Andric case HexagonII::TypeV2LDST: 5345ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) { 5355ffd83dbSDimitry Andric ++Summary.loads; 5365ffd83dbSDimitry Andric ++Summary.memory; 5375ffd83dbSDimitry Andric if (ISJ->Core.getUnits() == slotSingleLoad || 5385ffd83dbSDimitry Andric HexagonMCInstrInfo::getType(MCII, ID) == 5395ffd83dbSDimitry Andric HexagonII::TypeCVI_VM_VP_LDU) 5405ffd83dbSDimitry Andric ++Summary.load0; 5415ffd83dbSDimitry Andric } else { 5425ffd83dbSDimitry Andric assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()); 5435ffd83dbSDimitry Andric ++Summary.memory; 5445ffd83dbSDimitry Andric ++Summary.stores; 5455ffd83dbSDimitry Andric } 5465ffd83dbSDimitry Andric break; 5475ffd83dbSDimitry Andric case HexagonII::TypeCR: 5485ffd83dbSDimitry Andric // Legacy conditional branch predicated on a register. 5495ffd83dbSDimitry Andric case HexagonII::TypeCJ: 5505ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) 5515ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5525ffd83dbSDimitry Andric break; 5535ffd83dbSDimitry Andric case HexagonII::TypeDUPLEX: { 5545ffd83dbSDimitry Andric ++Summary.duplex; 5555ffd83dbSDimitry Andric MCInst const &Inst0 = *ID.getOperand(0).getInst(); 5565ffd83dbSDimitry Andric MCInst const &Inst1 = *ID.getOperand(1).getInst(); 5575ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) 5585ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5595ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) 5605ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5615ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn()) 5625ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5635ffd83dbSDimitry Andric if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn()) 5645ffd83dbSDimitry Andric Summary.branchInsts.push_back(ISJ); 5655ffd83dbSDimitry Andric break; 5665ffd83dbSDimitry Andric } 5675ffd83dbSDimitry Andric } 5685ffd83dbSDimitry Andric } 5695ffd83dbSDimitry Andric return Summary; 5705ffd83dbSDimitry Andric } 5715ffd83dbSDimitry Andric 5725ffd83dbSDimitry Andric bool HexagonShuffler::ValidPacketMemoryOps( 5735ffd83dbSDimitry Andric HexagonPacketSummary const &Summary) const { 5745ffd83dbSDimitry Andric // Check if the packet is legal. 5755ffd83dbSDimitry Andric const unsigned ZCVIloads = Summary.AllCVIloads - Summary.NonZCVIloads; 5765ffd83dbSDimitry Andric const bool ValidHVXMem = 5775ffd83dbSDimitry Andric Summary.NonZCVIloads <= 1 && ZCVIloads <= 1 && Summary.CVIstores <= 1; 5785ffd83dbSDimitry Andric const bool InvalidPacket = 5795ffd83dbSDimitry Andric ((Summary.load0 > 1 || Summary.store0 > 1 || !ValidHVXMem) || 5805ffd83dbSDimitry Andric (Summary.duplex > 1 || (Summary.duplex && Summary.memory))); 5815ffd83dbSDimitry Andric 5825ffd83dbSDimitry Andric return !InvalidPacket; 5835ffd83dbSDimitry Andric } 5845ffd83dbSDimitry Andric 58504eeddc0SDimitry Andric void HexagonShuffler::restrictPreferSlot3(HexagonPacketSummary const &Summary, 58604eeddc0SDimitry Andric const bool DoShuffle) { 5875ffd83dbSDimitry Andric // flag if an instruction requires to be in slot 3 5885ffd83dbSDimitry Andric const bool HasOnlySlot3 = llvm::any_of(insts(), [&](HexagonInstr const &I) { 5895ffd83dbSDimitry Andric return (I.Core.getUnits() == Slot3Mask); 5905ffd83dbSDimitry Andric }); 59104eeddc0SDimitry Andric const bool NeedsPrefSlot3Shuffle = Summary.branchInsts.size() <= 1 && 59204eeddc0SDimitry Andric !HasOnlySlot3 && Summary.pSlot3Cnt == 1 && 59304eeddc0SDimitry Andric Summary.PrefSlot3Inst && DoShuffle; 5945ffd83dbSDimitry Andric 5955ffd83dbSDimitry Andric if (!NeedsPrefSlot3Shuffle) 5965ffd83dbSDimitry Andric return; 5975ffd83dbSDimitry Andric 5985ffd83dbSDimitry Andric HexagonInstr *PrefSlot3Inst = *Summary.PrefSlot3Inst; 5995ffd83dbSDimitry Andric // save off slot mask of instruction marked with A_PREFER_SLOT3 6005ffd83dbSDimitry Andric // and then pin it to slot #3 6015ffd83dbSDimitry Andric const unsigned saveUnits = PrefSlot3Inst->Core.getUnits(); 6025ffd83dbSDimitry Andric PrefSlot3Inst->Core.setUnits(saveUnits & Slot3Mask); 60381ad6265SDimitry Andric const bool HasShuffledPacket = tryAuction(Summary).has_value(); 6045ffd83dbSDimitry Andric if (HasShuffledPacket) 6055ffd83dbSDimitry Andric return; 6065ffd83dbSDimitry Andric 6075ffd83dbSDimitry Andric PrefSlot3Inst->Core.setUnits(saveUnits); 6085ffd83dbSDimitry Andric } 6095ffd83dbSDimitry Andric 6105ffd83dbSDimitry Andric /// Check that the packet is legal and enforce relative insn order. 61104eeddc0SDimitry Andric bool HexagonShuffler::check(const bool RequireShuffle) { 6125ffd83dbSDimitry Andric const HexagonPacketSummary Summary = GetPacketSummary(); 61304eeddc0SDimitry Andric if (!applySlotRestrictions(Summary, RequireShuffle)) 6145ffd83dbSDimitry Andric return false; 6155ffd83dbSDimitry Andric 6165ffd83dbSDimitry Andric if (!ValidPacketMemoryOps(Summary)) { 6175ffd83dbSDimitry Andric reportError("invalid instruction packet"); 6185ffd83dbSDimitry Andric return false; 6195ffd83dbSDimitry Andric } 6205ffd83dbSDimitry Andric 62104eeddc0SDimitry Andric if (RequireShuffle) 6225ffd83dbSDimitry Andric ValidResourceUsage(Summary); 6235ffd83dbSDimitry Andric 6245ffd83dbSDimitry Andric return !CheckFailure; 6255ffd83dbSDimitry Andric } 6265ffd83dbSDimitry Andric 627bdd1243dSDimitry Andric std::optional<HexagonShuffler::HexagonPacket> 62804eeddc0SDimitry Andric HexagonShuffler::tryAuction(HexagonPacketSummary const &Summary) { 6295ffd83dbSDimitry Andric HexagonPacket PacketResult = Packet; 6305ffd83dbSDimitry Andric HexagonUnitAuction AuctionCore(Summary.ReservedSlotMask); 631e8d8bef9SDimitry Andric llvm::stable_sort(PacketResult, HexagonInstr::lessCore); 6325ffd83dbSDimitry Andric 6335ffd83dbSDimitry Andric const bool ValidSlots = 6345ffd83dbSDimitry Andric llvm::all_of(insts(PacketResult), [&AuctionCore](HexagonInstr const &I) { 6355ffd83dbSDimitry Andric return AuctionCore.bid(I.Core.getUnits()); 6365ffd83dbSDimitry Andric }); 6375ffd83dbSDimitry Andric 6385ffd83dbSDimitry Andric LLVM_DEBUG( 6395ffd83dbSDimitry Andric dbgs() << "Shuffle attempt: " << (ValidSlots ? "passed" : "failed") 6405ffd83dbSDimitry Andric << "\n"; 6415ffd83dbSDimitry Andric for (HexagonInstr const &ISJ : insts(PacketResult)) 6425ffd83dbSDimitry Andric dbgs() << "\t" << HexagonMCInstrInfo::getName(MCII, *ISJ.ID) << ": " 6435ffd83dbSDimitry Andric << llvm::format_hex(ISJ.Core.getUnits(), 4, true) << "\n"; 6445ffd83dbSDimitry Andric ); 6455ffd83dbSDimitry Andric 646bdd1243dSDimitry Andric std::optional<HexagonPacket> Res; 6475ffd83dbSDimitry Andric if (ValidSlots) 6485ffd83dbSDimitry Andric Res = PacketResult; 6495ffd83dbSDimitry Andric 6505ffd83dbSDimitry Andric return Res; 6515ffd83dbSDimitry Andric } 6525ffd83dbSDimitry Andric 6530b57cec5SDimitry Andric bool HexagonShuffler::shuffle() { 6540b57cec5SDimitry Andric if (size() > HEXAGON_PACKET_SIZE) { 655*5f757f3fSDimitry Andric // Ignore a packet with more than what a packet can hold 6560b57cec5SDimitry Andric // or with compound or duplex insns for now. 65704eeddc0SDimitry Andric reportError("invalid instruction packet"); 6580b57cec5SDimitry Andric return false; 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric // Check and prepare packet. 66204eeddc0SDimitry Andric bool Ok = check(); 66304eeddc0SDimitry Andric if (size() > 1 && Ok) 6640b57cec5SDimitry Andric // Reorder the handles for each slot. 6650b57cec5SDimitry Andric for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE; 6660b57cec5SDimitry Andric ++nSlot) { 6670b57cec5SDimitry Andric iterator ISJ, ISK; 6680b57cec5SDimitry Andric unsigned slotSkip, slotWeight; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // Prioritize the handles considering their restrictions. 6710b57cec5SDimitry Andric for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0; 6720b57cec5SDimitry Andric ISK != Packet.end(); ++ISK, ++slotSkip) 6730b57cec5SDimitry Andric if (slotSkip < nSlot - emptySlots) 6740b57cec5SDimitry Andric // Note which handle to begin at. 6750b57cec5SDimitry Andric ++ISJ; 6760b57cec5SDimitry Andric else 6770b57cec5SDimitry Andric // Calculate the weight of the slot. 6780b57cec5SDimitry Andric slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1); 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric if (slotWeight) 6810b57cec5SDimitry Andric // Sort the packet, favoring source order, 6820b57cec5SDimitry Andric // beginning after the previous slot. 6830b57cec5SDimitry Andric std::stable_sort(ISJ, Packet.end()); 6840b57cec5SDimitry Andric else 6850b57cec5SDimitry Andric // Skip unused slot. 6860b57cec5SDimitry Andric ++emptySlots; 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric 6895ffd83dbSDimitry Andric LLVM_DEBUG( 6905ffd83dbSDimitry Andric for (HexagonInstr const &ISJ : insts()) { 6915ffd83dbSDimitry Andric dbgs().write_hex(ISJ.Core.getUnits()); 6925ffd83dbSDimitry Andric if (ISJ.CVI.isValid()) { 6930b57cec5SDimitry Andric dbgs() << '/'; 6945ffd83dbSDimitry Andric dbgs().write_hex(ISJ.CVI.getUnits()) << '|'; 6955ffd83dbSDimitry Andric dbgs() << ISJ.CVI.getLanes(); 6965ffd83dbSDimitry Andric } 6975ffd83dbSDimitry Andric dbgs() << ':' 6985ffd83dbSDimitry Andric << HexagonMCInstrInfo::getDesc(MCII, ISJ.getDesc()).getOpcode() 6995ffd83dbSDimitry Andric << '\n'; 7005ffd83dbSDimitry Andric } dbgs() << '\n'; 7015ffd83dbSDimitry Andric ); 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric return Ok; 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric 70604eeddc0SDimitry Andric void HexagonShuffler::reportResourceError(HexagonPacketSummary const &Summary, StringRef Err) { 70704eeddc0SDimitry Andric if (ReportErrors) 70804eeddc0SDimitry Andric reportResourceUsage(Summary); 70904eeddc0SDimitry Andric reportError(Twine("invalid instruction packet: ") + Err); 71004eeddc0SDimitry Andric } 71104eeddc0SDimitry Andric 71204eeddc0SDimitry Andric 71304eeddc0SDimitry Andric void HexagonShuffler::reportResourceUsage(HexagonPacketSummary const &Summary) { 71404eeddc0SDimitry Andric auto SM = Context.getSourceManager(); 71504eeddc0SDimitry Andric if (SM) { 71604eeddc0SDimitry Andric for (HexagonInstr const &I : insts()) { 71704eeddc0SDimitry Andric const unsigned Units = I.Core.getUnits(); 71804eeddc0SDimitry Andric 71904eeddc0SDimitry Andric if (HexagonMCInstrInfo::requiresSlot(STI, *I.ID)) { 72004eeddc0SDimitry Andric const std::string UnitsText = Units ? SlotMaskToText(Units) : "<None>"; 72104eeddc0SDimitry Andric SM->PrintMessage(I.ID->getLoc(), SourceMgr::DK_Note, 72204eeddc0SDimitry Andric Twine("Instruction can utilize slots: ") + 72304eeddc0SDimitry Andric UnitsText); 72404eeddc0SDimitry Andric } 72504eeddc0SDimitry Andric else if (!HexagonMCInstrInfo::isImmext(*I.ID)) 72604eeddc0SDimitry Andric SM->PrintMessage(I.ID->getLoc(), SourceMgr::DK_Note, 72704eeddc0SDimitry Andric "Instruction does not require a slot"); 72804eeddc0SDimitry Andric } 72904eeddc0SDimitry Andric } 73004eeddc0SDimitry Andric } 73104eeddc0SDimitry Andric 7320b57cec5SDimitry Andric void HexagonShuffler::reportError(Twine const &Msg) { 7335ffd83dbSDimitry Andric CheckFailure = true; 7340b57cec5SDimitry Andric if (ReportErrors) { 7350b57cec5SDimitry Andric for (auto const &I : AppliedRestrictions) { 7360b57cec5SDimitry Andric auto SM = Context.getSourceManager(); 7370b57cec5SDimitry Andric if (SM) 7380b57cec5SDimitry Andric SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second); 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric Context.reportError(Loc, Msg); 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric } 743