Go to the documentation of this file.
35 #define DEBUG_TYPE "hexagon-shuffle"
46 enum { MAX = 360360 };
50 HexagonBid() =
default;
54 bool isSold()
const {
return (Bid >= MAX); }
63 class HexagonUnitAuction {
69 HexagonUnitAuction(
unsigned cs = 0) : isSold(cs) {}
72 bool bid(
unsigned B) {
74 unsigned b =
B & ~isSold;
79 Scores[
i] += HexagonBid(
b);
80 isSold |= Scores[
i].isSold() <<
i;
92 const unsigned SlotWeight = 8;
93 const unsigned MaskWeight = SlotWeight - 1;
95 unsigned Key = ((1u <<
s) & Units) != 0;
100 if (
Key == 0 || Units == 0 || (SlotWeight *
s >= 32))
105 Weight = (1u << (SlotWeight *
s)) * ((MaskWeight - Ctpop) << Cttz);
119 if (Units == 0 && Lanes == 0) {
144 for (
unsigned i = 1;
i < Lanes; ++
i)
145 startBit = (startBit << 1) | startBit;
150 unsigned usedUnits) {
151 if (startIdx < hvxInsts.size()) {
152 if (!hvxInsts[startIdx].Units)
154 for (
unsigned b = 0x1;
b <= 0x8;
b <<= 1) {
155 if ((hvxInsts[startIdx].Units &
b) == 0)
157 unsigned allBits =
makeAllBits(
b, hvxInsts[startIdx].Lanes);
158 if ((allBits & usedUnits) == 0) {
159 if (
checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits))
172 ReportErrors(ReportErrors), CheckFailure() {
186 Packet.push_back(PI);
197 if (Summary.Slot1AOKLoc)
199 MCInst const &Inst = ISJ.getDesc();
204 const unsigned Units = ISJ.Core.getUnits();
209 "Instruction was restricted from being in slot 1"));
211 *Summary.Slot1AOKLoc,
"Instruction can only be combined "
212 "with an ALU instruction in slot 1"));
220 HexagonPacketSummary
const &Summary) {
225 if (!Summary.NoSlot1StoreLoc)
228 bool AppliedRestriction =
false;
231 MCInst const &Inst = ISJ.getDesc();
233 unsigned Units = ISJ.Core.getUnits();
235 AppliedRestriction =
true;
237 Inst.
getLoc(),
"Instruction was restricted from being in slot 1"));
243 if (AppliedRestriction)
245 std::make_pair(*Summary.NoSlot1StoreLoc,
246 "Instruction does not allow a store in slot 1"));
250 const bool DoShuffle) {
273 const bool HasMultipleBranches = Summary.branchInsts.size() > 1;
274 if (!HasMultipleBranches)
277 if (Summary.branchInsts.size() > 2) {
282 const static std::pair<unsigned, unsigned> jumpSlots[] = {
283 {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
285 for (std::pair<unsigned, unsigned> jumpSlot : jumpSlots) {
287 if (!(jumpSlot.first & Summary.branchInsts[0]->Core.getUnits()))
291 if (!(jumpSlot.second & Summary.branchInsts[1]->Core.getUnits()))
296 Summary.branchInsts[0]->Core.setUnits(jumpSlot.first);
297 Summary.branchInsts[1]->Core.setUnits(jumpSlot.second);
299 const bool HasShuffledPacket =
tryAuction(Summary).has_value();
300 if (HasShuffledPacket)
315 ISJ.Core.setAllUnits();
320 std::optional<HexagonPacket> ShuffledPacket =
tryAuction(Summary);
322 if (!ShuffledPacket) {
332 for (
const auto &
I : *ShuffledPacket) {
334 inst.
Units =
I.CVI.getUnits();
335 inst.
Lanes =
I.CVI.getLanes();
338 hvxInsts.push_back(inst);
342 if (hvxInsts.size() > 0) {
343 unsigned startIdx, usedUnits;
344 startIdx = usedUnits = 0x0;
352 Packet = *ShuffledPacket;
358 HexagonPacketSummary
const &Summary) {
361 static const unsigned slotFirstLoadStore =
Slot1Mask;
362 static const unsigned slotLastLoadStore =
Slot0Mask;
363 unsigned slotLoadStore = slotFirstLoadStore;
368 if (!ISJ->Core.getUnits())
374 if (Summary.loads == 1 && Summary.loads == Summary.memory &&
377 switch (
ID.getOpcode()) {
378 case Hexagon::V6_vgathermw:
379 case Hexagon::V6_vgathermh:
380 case Hexagon::V6_vgathermhw:
381 case Hexagon::V6_vgathermwq:
382 case Hexagon::V6_vgathermhq:
383 case Hexagon::V6_vgathermhwq:
393 if (slotLoadStore < slotLastLoadStore) {
395 reportError(
"invalid instruction packet: too many loads");
399 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
407 if (!Summary.store0) {
408 const bool PacketHasNoOnlySlot0 =
411 I.ID->getOpcode() !=
ID.getOpcode();
413 const bool SafeToMoveToSlot0 =
414 (Summary.loads == 0) ||
417 if (Summary.stores == 1 && SafeToMoveToSlot0)
420 else if (Summary.stores >= 1) {
421 if (slotLoadStore < slotLastLoadStore) {
423 reportError(
"invalid instruction packet: too many stores");
427 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
432 if (Summary.store1 && Summary.stores > 1) {
434 reportError(
"invalid instruction packet: too many stores");
446 if ((SlotMask & (1 << SlotNum)) != 0)
447 Slots.push_back(utostr(SlotNum));
449 return llvm::join(Slots,
StringRef(
", "));
453 HexagonPacketSummary Summary = HexagonPacketSummary();
460 Summary.Slot1AOKLoc =
ID.getLoc();
462 Summary.NoSlot1StoreLoc =
ID.getLoc();
466 Summary.PrefSlot3Inst = ISJ;
468 const unsigned ReservedSlots =
470 Summary.ReservedSlotMask |= ReservedSlots;
471 if (ReservedSlots != 0)
473 (
Twine(
"Instruction has reserved slots: ") +
483 Summary.branchInsts.push_back(ISJ);
491 ++Summary.NonZCVIloads;
494 ++Summary.AllCVIloads;
503 Summary.branchInsts.push_back(ISJ);
531 Summary.branchInsts.push_back(ISJ);
551 Summary.branchInsts.push_back(ISJ);
558 Summary.branchInsts.push_back(ISJ);
560 Summary.branchInsts.push_back(ISJ);
562 Summary.branchInsts.push_back(ISJ);
564 Summary.branchInsts.push_back(ISJ);
573 HexagonPacketSummary
const &Summary)
const {
575 const unsigned ZCVIloads = Summary.AllCVIloads - Summary.NonZCVIloads;
576 const bool ValidHVXMem =
577 Summary.NonZCVIloads <= 1 && ZCVIloads <= 1 && Summary.CVIstores <= 1;
578 const bool InvalidPacket =
579 ((Summary.load0 > 1 || Summary.store0 > 1 || !ValidHVXMem) ||
580 (Summary.duplex > 1 || (Summary.duplex && Summary.memory)));
582 return !InvalidPacket;
586 const bool DoShuffle) {
591 const bool NeedsPrefSlot3Shuffle = Summary.branchInsts.size() <= 1 &&
592 !HasOnlySlot3 && Summary.pSlot3Cnt == 1 &&
593 Summary.PrefSlot3Inst && DoShuffle;
595 if (!NeedsPrefSlot3Shuffle)
601 const unsigned saveUnits = PrefSlot3Inst->Core.
getUnits();
603 const bool HasShuffledPacket =
tryAuction(Summary).has_value();
604 if (HasShuffledPacket)
607 PrefSlot3Inst->Core.
setUnits(saveUnits);
627 std::optional<HexagonShuffler::HexagonPacket>
630 HexagonUnitAuction AuctionCore(Summary.ReservedSlotMask);
633 const bool ValidSlots =
635 return AuctionCore.bid(
I.Core.getUnits());
639 dbgs() <<
"Shuffle attempt: " << (ValidSlots ?
"passed" :
"failed")
646 std::optional<HexagonPacket> Res;
663 if (
size() > 1 && Ok)
668 unsigned slotSkip, slotWeight;
671 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
672 ISK != Packet.end(); ++ISK, ++slotSkip)
673 if (slotSkip < nSlot - emptySlots)
692 if (ISJ.CVI.isValid()) {
695 dbgs() << ISJ.CVI.getLanes();
717 const unsigned Units =
I.Core.getUnits();
722 Twine(
"Instruction can utilize slots: ") +
727 "Instruction does not require a slot");
static const unsigned slotSingleStore
unsigned getOpcode() const
Return the opcode number for this descriptor.
HexagonPacketSummary GetPacketSummary()
This is an optimization pass for GlobalISel generic memory operations.
const MCInstrDesc & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
void reportError(Twine const &Msg)
unsigned HexagonConvertUnits(unsigned ItinUnits, unsigned *Lanes)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
HexagonCVIResource(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, unsigned s, MCInst const *id)
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 restrictStoreLoadOrder(HexagonPacketSummary const &Summary)
bool IsABranchingInst(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &I)
Context object for machine code objects.
void setUnits(unsigned s)
bool isMemReorderDisabled() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
unsigned getCVIResources(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCI)
Return the resources used by this instruction.
HexagonPacket::iterator iterator
void reportResourceUsage(HexagonPacketSummary const &Summary)
static const unsigned Slot0Mask
void restrictNoSlot1Store(HexagonPacketSummary const &Summary)
The instances of the Type class are immutable: once they are created, they are never changed.
bool isImmext(MCInst const &MCI)
unsigned getUnits() const
Instances of this class represent a single low-level machine instruction.
static const unsigned slotSingleLoad
bool prefersSlot3(MCInstrInfo const &MCII, 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.
static unsigned makeAllBits(unsigned startBit, unsigned Lanes)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static const unsigned Slot1Mask
static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B)
void restrictSlot1AOK(HexagonPacketSummary const &Summary)
bool requiresSlot(MCSubtargetInfo const &STI, MCInst const &MCI)
void restrictBranchOrder(HexagonPacketSummary const &Summary)
const MCInst * getInst() const
int popcount(T Value) noexcept
Count the number of set bits in a value.
std::string & operator+=(std::string &buffer, StringRef string)
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
StringRef getName(MCInstrInfo const &MCII, MCInst const &MCI)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
bool isRestrictNoSlot1Store(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned countTrailingZeros(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
void reportResourceError(HexagonPacketSummary const &Summary, StringRef Err)
bool mayLoad() const
Return true if this instruction could possibly read memory.
std::optional< HexagonPacket > tryAuction(HexagonPacketSummary const &Summary)
void PrintMessage(raw_ostream &OS, SMLoc Loc, DiagKind Kind, const Twine &Msg, ArrayRef< SMRange > Ranges={}, ArrayRef< SMFixIt > FixIts={}, bool ShowColors=true) const
Emit a message about the specified location with the specified string.
multiplies can be turned into SHL s
bool applySlotRestrictions(HexagonPacketSummary const &Summary, const bool DoShuffle)
std::vector< std::pair< SMLoc, std::string > > AppliedRestrictions
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void reportError(SMLoc L, const Twine &Msg)
static bool isBranch(unsigned Opcode)
const MCSubtargetInfo & STI
void append(MCInst const &ID, MCInst const *Extender, unsigned S)
bool ValidResourceUsage(HexagonPacketSummary const &Summary)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
@ TypeCVI_SCATTER_NEW_RST
unsigned setWeight(unsigned s)
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
const CustomOperand< const MCSubtargetInfo & > Msg[]
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
void stable_sort(R &&Range)
Interface to description of machine instruction set.
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
Return the Hexagon ISA class for the insn.
void restrictPreferSlot3(HexagonPacketSummary const &Summary, const bool DoShuffle)
static const unsigned Slot3Mask
static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx, unsigned usedUnits)
bool ValidPacketMemoryOps(HexagonPacketSummary const &Summary) const
HexagonShuffler(MCContext &Context, bool ReportErrors, MCInstrInfo const &MCII, MCSubtargetInfo const &STI)
const SourceMgr * getSourceManager() const
const MCOperand & getOperand(unsigned i) const
static std::string SlotMaskToText(unsigned SlotMask)
static bool lessCore(const HexagonInstr &A, const HexagonInstr &B)
#define HEXAGON_PACKET_SIZE
bool check(const bool RequireShuffle=true)
Check that the packet is legal and enforce relative insn order.
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Generic base class for all target subtargets.
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.