xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===//
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 #ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
150b57cec5SDimitry Andric #define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h"
195ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
220b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
230b57cec5SDimitry Andric #include "llvm/Support/SMLoc.h"
240b57cec5SDimitry Andric #include <cstdint>
255ffd83dbSDimitry Andric #include <functional>
26*bdd1243dSDimitry Andric #include <optional>
270b57cec5SDimitry Andric #include <utility>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace llvm {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class MCContext;
320b57cec5SDimitry Andric class MCInst;
330b57cec5SDimitry Andric class MCInstrInfo;
340b57cec5SDimitry Andric class MCSubtargetInfo;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric // Insn resources.
370b57cec5SDimitry Andric class HexagonResource {
380b57cec5SDimitry Andric   // Mask of the slots or units that may execute the insn and
390b57cec5SDimitry Andric   // the weight or priority that the insn requires to be assigned a slot.
400b57cec5SDimitry Andric   unsigned Slots, Weight;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric public:
430b57cec5SDimitry Andric   HexagonResource(unsigned s) { setUnits(s); }
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   void setUnits(unsigned s) {
460b57cec5SDimitry Andric     Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1);
470b57cec5SDimitry Andric     setWeight(s);
480b57cec5SDimitry Andric   }
490b57cec5SDimitry Andric 
505ffd83dbSDimitry Andric   void setAllUnits() {
515ffd83dbSDimitry Andric     setUnits(((1u << HEXAGON_PACKET_SIZE) - 1));
525ffd83dbSDimitry Andric   }
530b57cec5SDimitry Andric   unsigned setWeight(unsigned s);
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   unsigned getUnits() const { return (Slots); }
560b57cec5SDimitry Andric   unsigned getWeight() const { return (Weight); }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric   // Check if the resources are in ascending slot order.
590b57cec5SDimitry Andric   static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
60*bdd1243dSDimitry Andric     return (llvm::popcount(A.getUnits()) < llvm::popcount(B.getUnits()));
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   // Check if the resources are in ascending weight order.
640b57cec5SDimitry Andric   static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
650b57cec5SDimitry Andric     return (A.getWeight() < B.getWeight());
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric // HVX insn resources.
700b57cec5SDimitry Andric class HexagonCVIResource : public HexagonResource {
710b57cec5SDimitry Andric public:
720b57cec5SDimitry Andric   using UnitsAndLanes = std::pair<unsigned, unsigned>;
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric private:
750b57cec5SDimitry Andric   // Count of adjacent slots that the insn requires to be executed.
760b57cec5SDimitry Andric   unsigned Lanes;
770b57cec5SDimitry Andric   // Flag whether the insn is a load or a store.
780b57cec5SDimitry Andric   bool Load, Store;
790b57cec5SDimitry Andric   // Flag whether the HVX resources are valid.
800b57cec5SDimitry Andric   bool Valid;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   void setLanes(unsigned l) { Lanes = l; }
830b57cec5SDimitry Andric   void setLoad(bool f = true) { Load = f; }
840b57cec5SDimitry Andric   void setStore(bool f = true) { Store = f; }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric public:
875ffd83dbSDimitry Andric   HexagonCVIResource(MCInstrInfo const &MCII,
885ffd83dbSDimitry Andric                      MCSubtargetInfo const &STI,
890b57cec5SDimitry Andric                      unsigned s, MCInst const *id);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   bool isValid() const { return Valid; }
920b57cec5SDimitry Andric   unsigned getLanes() const { return Lanes; }
930b57cec5SDimitry Andric   bool mayLoad() const { return Load; }
940b57cec5SDimitry Andric   bool mayStore() const { return Store; }
950b57cec5SDimitry Andric };
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric // Handle to an insn used by the shuffling algorithm.
980b57cec5SDimitry Andric class HexagonInstr {
990b57cec5SDimitry Andric   friend class HexagonShuffler;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   MCInst const *ID;
1020b57cec5SDimitry Andric   MCInst const *Extender;
1030b57cec5SDimitry Andric   HexagonResource Core;
1040b57cec5SDimitry Andric   HexagonCVIResource CVI;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric public:
1075ffd83dbSDimitry Andric   HexagonInstr(MCInstrInfo const &MCII,
1085ffd83dbSDimitry Andric                MCSubtargetInfo const &STI, MCInst const *id,
1090b57cec5SDimitry Andric                MCInst const *Extender, unsigned s)
1105ffd83dbSDimitry Andric       : ID(id), Extender(Extender), Core(s), CVI(MCII, STI, s, id){};
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   MCInst const &getDesc() const { return *ID; }
1130b57cec5SDimitry Andric   MCInst const *getExtender() const { return Extender; }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // Check if the handles are in ascending order for shuffling purposes.
1160b57cec5SDimitry Andric   bool operator<(const HexagonInstr &B) const {
1170b57cec5SDimitry Andric     return (HexagonResource::lessWeight(B.Core, Core));
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // Check if the handles are in ascending order by core slots.
1210b57cec5SDimitry Andric   static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
1220b57cec5SDimitry Andric     return (HexagonResource::lessUnits(A.Core, B.Core));
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   // Check if the handles are in ascending order by HVX slots.
1260b57cec5SDimitry Andric   static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
1270b57cec5SDimitry Andric     return (HexagonResource::lessUnits(A.CVI, B.CVI));
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric };
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric // Bundle shuffler.
1320b57cec5SDimitry Andric class HexagonShuffler {
1330b57cec5SDimitry Andric   using HexagonPacket =
1340b57cec5SDimitry Andric       SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>;
1350b57cec5SDimitry Andric 
1365ffd83dbSDimitry Andric   struct HexagonPacketSummary {
1375ffd83dbSDimitry Andric     // Number of memory operations, loads, solo loads, stores, solo stores,
1385ffd83dbSDimitry Andric     // single stores.
1395ffd83dbSDimitry Andric     unsigned memory;
1405ffd83dbSDimitry Andric     unsigned loads;
1415ffd83dbSDimitry Andric     unsigned load0;
1425ffd83dbSDimitry Andric     unsigned stores;
1435ffd83dbSDimitry Andric     unsigned store0;
1445ffd83dbSDimitry Andric     unsigned store1;
1455ffd83dbSDimitry Andric     unsigned NonZCVIloads;
1465ffd83dbSDimitry Andric     unsigned AllCVIloads;
1475ffd83dbSDimitry Andric     unsigned CVIstores;
1485ffd83dbSDimitry Andric     // Number of duplex insns
1495ffd83dbSDimitry Andric     unsigned duplex;
1505ffd83dbSDimitry Andric     unsigned pSlot3Cnt;
151*bdd1243dSDimitry Andric     std::optional<HexagonInstr *> PrefSlot3Inst;
1525ffd83dbSDimitry Andric     unsigned memops;
1535ffd83dbSDimitry Andric     unsigned ReservedSlotMask;
1545ffd83dbSDimitry Andric     SmallVector<HexagonInstr *, HEXAGON_PRESHUFFLE_PACKET_SIZE> branchInsts;
155*bdd1243dSDimitry Andric     std::optional<SMLoc> Slot1AOKLoc;
156*bdd1243dSDimitry Andric     std::optional<SMLoc> NoSlot1StoreLoc;
1575ffd83dbSDimitry Andric   };
1580b57cec5SDimitry Andric   // Insn handles in a bundle.
1590b57cec5SDimitry Andric   HexagonPacket Packet;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric protected:
1620b57cec5SDimitry Andric   MCContext &Context;
1630b57cec5SDimitry Andric   int64_t BundleFlags;
1640b57cec5SDimitry Andric   MCInstrInfo const &MCII;
1650b57cec5SDimitry Andric   MCSubtargetInfo const &STI;
1660b57cec5SDimitry Andric   SMLoc Loc;
1670b57cec5SDimitry Andric   bool ReportErrors;
1685ffd83dbSDimitry Andric   bool CheckFailure;
1690b57cec5SDimitry Andric   std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions;
17004eeddc0SDimitry Andric 
17104eeddc0SDimitry Andric   bool applySlotRestrictions(HexagonPacketSummary const &Summary,
17204eeddc0SDimitry Andric                              const bool DoShuffle);
1735ffd83dbSDimitry Andric   void restrictSlot1AOK(HexagonPacketSummary const &Summary);
1745ffd83dbSDimitry Andric   void restrictNoSlot1Store(HexagonPacketSummary const &Summary);
1755ffd83dbSDimitry Andric   void restrictNoSlot1();
1765ffd83dbSDimitry Andric   bool restrictStoreLoadOrder(HexagonPacketSummary const &Summary);
1775ffd83dbSDimitry Andric   void restrictBranchOrder(HexagonPacketSummary const &Summary);
17804eeddc0SDimitry Andric   void restrictPreferSlot3(HexagonPacketSummary const &Summary,
17904eeddc0SDimitry Andric                            const bool DoShuffle);
1805ffd83dbSDimitry Andric   void permitNonSlot();
1815ffd83dbSDimitry Andric 
182*bdd1243dSDimitry Andric   std::optional<HexagonPacket> tryAuction(HexagonPacketSummary const &Summary);
1835ffd83dbSDimitry Andric 
1845ffd83dbSDimitry Andric   HexagonPacketSummary GetPacketSummary();
1855ffd83dbSDimitry Andric   bool ValidPacketMemoryOps(HexagonPacketSummary const &Summary) const;
1865ffd83dbSDimitry Andric   bool ValidResourceUsage(HexagonPacketSummary const &Summary);
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric public:
1890b57cec5SDimitry Andric   using iterator = HexagonPacket::iterator;
1905ffd83dbSDimitry Andric   using const_iterator = HexagonPacket::const_iterator;
1915ffd83dbSDimitry Andric   using packet_range = iterator_range<HexagonPacket::iterator>;
1925ffd83dbSDimitry Andric   using const_packet_range = iterator_range<HexagonPacket::const_iterator>;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   HexagonShuffler(MCContext &Context, bool ReportErrors,
1950b57cec5SDimitry Andric                   MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   // Reset to initial state.
1980b57cec5SDimitry Andric   void reset();
1990b57cec5SDimitry Andric   // Check if the bundle may be validly shuffled.
20004eeddc0SDimitry Andric   bool check(const bool RequireShuffle = true);
2010b57cec5SDimitry Andric   // Reorder the insn handles in the bundle.
2020b57cec5SDimitry Andric   bool shuffle();
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   unsigned size() const { return (Packet.size()); }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   bool isMemReorderDisabled() const {
2070b57cec5SDimitry Andric     return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0;
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   iterator begin() { return (Packet.begin()); }
2110b57cec5SDimitry Andric   iterator end() { return (Packet.end()); }
2125ffd83dbSDimitry Andric   const_iterator cbegin() const { return (Packet.begin()); }
2135ffd83dbSDimitry Andric   const_iterator cend() const { return (Packet.end()); }
2145ffd83dbSDimitry Andric   packet_range insts(HexagonPacket &P) {
2155ffd83dbSDimitry Andric     return make_range(P.begin(), P.end());
2165ffd83dbSDimitry Andric   }
2175ffd83dbSDimitry Andric   const_packet_range insts(HexagonPacket const &P) const {
2185ffd83dbSDimitry Andric     return make_range(P.begin(), P.end());
2195ffd83dbSDimitry Andric   }
2205ffd83dbSDimitry Andric   packet_range insts() { return make_range(begin(), end()); }
2215ffd83dbSDimitry Andric   const_packet_range insts() const { return make_range(cbegin(), cend()); }
2225ffd83dbSDimitry Andric 
2235ffd83dbSDimitry Andric   using InstPredicate = bool (*)(MCInstrInfo const &, MCInst const &);
2245ffd83dbSDimitry Andric 
2255ffd83dbSDimitry Andric   bool HasInstWith(InstPredicate Pred) const {
2265ffd83dbSDimitry Andric     return llvm::any_of(insts(), [&](HexagonInstr const &I) {
2275ffd83dbSDimitry Andric       MCInst const &Inst = I.getDesc();
2285ffd83dbSDimitry Andric       return (*Pred)(MCII, Inst);
2295ffd83dbSDimitry Andric     });
2305ffd83dbSDimitry Andric   }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   // Add insn handle to the bundle .
2330b57cec5SDimitry Andric   void append(MCInst const &ID, MCInst const *Extender, unsigned S);
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   // Return the error code for the last check or shuffling of the bundle.
2360b57cec5SDimitry Andric   void reportError(Twine const &Msg);
23704eeddc0SDimitry Andric   void reportResourceError(HexagonPacketSummary const &Summary, StringRef Err);
23804eeddc0SDimitry Andric   void reportResourceUsage(HexagonPacketSummary const &Summary);
2390b57cec5SDimitry Andric };
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric } // end namespace llvm
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric #endif //  LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
244