Go to the documentation of this file.
34 #define DEBUG_TYPE "hexagon-shuffle"
45 enum { MAX = 360360 };
49 HexagonBid() =
default;
53 bool isSold()
const {
return (Bid >= MAX); }
62 class HexagonUnitAuction {
68 HexagonUnitAuction(
unsigned cs = 0) : isSold(cs) {}
71 bool bid(
unsigned B) {
73 unsigned b =
B & ~isSold;
78 Scores[
i] += HexagonBid(
b);
79 isSold |= Scores[
i].isSold() <<
i;
91 const unsigned SlotWeight = 8;
92 const unsigned MaskWeight = SlotWeight - 1;
94 unsigned Key = ((1u <<
s) & Units) != 0;
99 if (
Key == 0 || Units == 0 || (SlotWeight *
s >= 32))
104 Weight = (1u << (SlotWeight *
s)) * ((MaskWeight - Ctpop) << Cttz);
118 if (Units == 0 && Lanes == 0) {
143 for (
unsigned i = 1;
i < Lanes; ++
i)
144 startBit = (startBit << 1) | startBit;
149 unsigned usedUnits) {
150 if (startIdx < hvxInsts.size()) {
151 if (!hvxInsts[startIdx].Units)
153 for (
unsigned b = 0x1;
b <= 0x8;
b <<= 1) {
154 if ((hvxInsts[startIdx].Units &
b) == 0)
156 unsigned allBits =
makeAllBits(
b, hvxInsts[startIdx].Lanes);
157 if ((allBits & usedUnits) == 0) {
158 if (
checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits))
171 ReportErrors(ReportErrors), CheckFailure() {
185 Packet.push_back(PI);
196 if (Summary.Slot1AOKLoc)
198 MCInst const &Inst = ISJ.getDesc();
203 const unsigned Units = ISJ.Core.getUnits();
208 "Instruction was restricted from being in slot 1"));
210 *Summary.Slot1AOKLoc,
"Instruction can only be combined "
211 "with an ALU instruction in slot 1"));
219 HexagonPacketSummary
const &Summary) {
224 if (!Summary.NoSlot1StoreLoc)
227 bool AppliedRestriction =
false;
230 MCInst const &Inst = ISJ.getDesc();
232 unsigned Units = ISJ.Core.getUnits();
234 AppliedRestriction =
true;
236 Inst.
getLoc(),
"Instruction was restricted from being in slot 1"));
242 if (AppliedRestriction)
244 std::make_pair(*Summary.NoSlot1StoreLoc,
245 "Instruction does not allow a store in slot 1"));
249 const bool DoShuffle) {
272 const bool HasMultipleBranches = Summary.branchInsts.size() > 1;
273 if (!HasMultipleBranches)
276 if (Summary.branchInsts.size() > 2) {
281 const static std::pair<unsigned, unsigned> jumpSlots[] = {
282 {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}};
284 for (std::pair<unsigned, unsigned> jumpSlot : jumpSlots) {
286 if (!(jumpSlot.first & Summary.branchInsts[0]->Core.getUnits()))
290 if (!(jumpSlot.second & Summary.branchInsts[1]->Core.getUnits()))
295 Summary.branchInsts[0]->Core.setUnits(jumpSlot.first);
296 Summary.branchInsts[1]->Core.setUnits(jumpSlot.second);
298 const bool HasShuffledPacket =
tryAuction(Summary).hasValue();
299 if (HasShuffledPacket)
314 ISJ.Core.setAllUnits();
321 if (!ShuffledPacket) {
331 for (
const auto &
I : *ShuffledPacket) {
333 inst.
Units =
I.CVI.getUnits();
334 inst.
Lanes =
I.CVI.getLanes();
337 hvxInsts.push_back(inst);
341 if (hvxInsts.size() > 0) {
342 unsigned startIdx, usedUnits;
343 startIdx = usedUnits = 0x0;
351 Packet = *ShuffledPacket;
357 HexagonPacketSummary
const &Summary) {
360 static const unsigned slotFirstLoadStore =
Slot1Mask;
361 static const unsigned slotLastLoadStore =
Slot0Mask;
362 unsigned slotLoadStore = slotFirstLoadStore;
367 if (!ISJ->Core.getUnits())
373 if (Summary.loads == 1 && Summary.loads == Summary.memory &&
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:
392 if (slotLoadStore < slotLastLoadStore) {
394 reportError(
"invalid instruction packet: too many loads");
398 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
406 if (!Summary.store0) {
407 const bool PacketHasNoOnlySlot0 =
410 I.ID->getOpcode() !=
ID.getOpcode();
412 const bool SafeToMoveToSlot0 =
413 (Summary.loads == 0) ||
416 if (Summary.stores == 1 && SafeToMoveToSlot0)
419 else if (Summary.stores >= 1) {
420 if (slotLoadStore < slotLastLoadStore) {
422 reportError(
"invalid instruction packet: too many stores");
426 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
431 if (Summary.store1 && Summary.stores > 1) {
433 reportError(
"invalid instruction packet: too many stores");
445 if ((SlotMask & (1 << SlotNum)) != 0)
446 Slots.push_back(utostr(SlotNum));
448 return llvm::join(Slots,
StringRef(
", "));
452 HexagonPacketSummary Summary = HexagonPacketSummary();
461 Summary.NoSlot1StoreLoc =
ID.getLoc();
465 Summary.PrefSlot3Inst = ISJ;
467 const unsigned ReservedSlots =
469 Summary.ReservedSlotMask |= ReservedSlots;
470 if (ReservedSlots != 0)
472 (
Twine(
"Instruction has reserved slots: ") +
482 Summary.branchInsts.push_back(ISJ);
490 ++Summary.NonZCVIloads;
493 ++Summary.AllCVIloads;
502 Summary.branchInsts.push_back(ISJ);
530 Summary.branchInsts.push_back(ISJ);
550 Summary.branchInsts.push_back(ISJ);
557 Summary.branchInsts.push_back(ISJ);
559 Summary.branchInsts.push_back(ISJ);
561 Summary.branchInsts.push_back(ISJ);
563 Summary.branchInsts.push_back(ISJ);
572 HexagonPacketSummary
const &Summary)
const {
574 const unsigned ZCVIloads = Summary.AllCVIloads - Summary.NonZCVIloads;
575 const bool ValidHVXMem =
576 Summary.NonZCVIloads <= 1 && ZCVIloads <= 1 && Summary.CVIstores <= 1;
577 const bool InvalidPacket =
578 ((Summary.load0 > 1 || Summary.store0 > 1 || !ValidHVXMem) ||
579 (Summary.duplex > 1 || (Summary.duplex && Summary.memory)));
581 return !InvalidPacket;
585 const bool DoShuffle) {
590 const bool NeedsPrefSlot3Shuffle = Summary.branchInsts.size() <= 1 &&
591 !HasOnlySlot3 && Summary.pSlot3Cnt == 1 &&
592 Summary.PrefSlot3Inst && DoShuffle;
594 if (!NeedsPrefSlot3Shuffle)
600 const unsigned saveUnits = PrefSlot3Inst->Core.
getUnits();
602 const bool HasShuffledPacket =
tryAuction(Summary).hasValue();
603 if (HasShuffledPacket)
606 PrefSlot3Inst->Core.
setUnits(saveUnits);
629 HexagonUnitAuction AuctionCore(Summary.ReservedSlotMask);
632 const bool ValidSlots =
634 return AuctionCore.bid(
I.Core.getUnits());
638 dbgs() <<
"Shuffle attempt: " << (ValidSlots ?
"passed" :
"failed")
662 if (
size() > 1 && Ok)
667 unsigned slotSkip, slotWeight;
670 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
671 ISK != Packet.end(); ++ISK, ++slotSkip)
672 if (slotSkip < nSlot - emptySlots)
691 if (ISJ.CVI.isValid()) {
694 dbgs() << ISJ.CVI.getLanes();
716 const unsigned Units =
I.Core.getUnits();
721 Twine(
"Instruction can utilize slots: ") +
726 "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
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 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.
unsigned countPopulation(T Value)
Count the number of set bits in a value.
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)
Optional< HexagonPacket > tryAuction(HexagonPacketSummary const &Summary)
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.
unsigned countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1.
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
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
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.