#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
#include "MCTargetDesc/HexagonMCInstrInfo.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SMLoc.h"
#include <cstdint>
#include <functional>
#include <utility>
namespace llvm {
class MCContext;
class MCInst;
class MCInstrInfo;
class MCSubtargetInfo;
class HexagonResource {
unsigned Slots, Weight;
public:
HexagonResource(unsigned s) { setUnits(s); }
void setUnits(unsigned s) {
Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1);
setWeight(s);
}
void setAllUnits() {
setUnits(((1u << HEXAGON_PACKET_SIZE) - 1));
}
unsigned setWeight(unsigned s);
unsigned getUnits() const { return (Slots); }
unsigned getWeight() const { return (Weight); }
static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
}
static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
return (A.getWeight() < B.getWeight());
}
};
class HexagonCVIResource : public HexagonResource {
public:
using UnitsAndLanes = std::pair<unsigned, unsigned>;
private:
unsigned Lanes;
bool Load, Store;
bool Valid;
void setLanes(unsigned l) { Lanes = l; }
void setLoad(bool f = true) { Load = f; }
void setStore(bool f = true) { Store = f; }
public:
HexagonCVIResource(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI,
unsigned s, MCInst const *id);
bool isValid() const { return Valid; }
unsigned getLanes() const { return Lanes; }
bool mayLoad() const { return Load; }
bool mayStore() const { return Store; }
};
class HexagonInstr {
friend class HexagonShuffler;
MCInst const *ID;
MCInst const *Extender;
HexagonResource Core;
HexagonCVIResource CVI;
public:
HexagonInstr(MCInstrInfo const &MCII,
MCSubtargetInfo const &STI, MCInst const *id,
MCInst const *Extender, unsigned s)
: ID(id), Extender(Extender), Core(s), CVI(MCII, STI, s, id){};
MCInst const &getDesc() const { return *ID; }
MCInst const *getExtender() const { return Extender; }
bool operator<(const HexagonInstr &B) const {
return (HexagonResource::lessWeight(B.Core, Core));
}
static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
return (HexagonResource::lessUnits(A.Core, B.Core));
}
static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
return (HexagonResource::lessUnits(A.CVI, B.CVI));
}
};
class HexagonShuffler {
using HexagonPacket =
SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>;
struct HexagonPacketSummary {
unsigned memory;
unsigned loads;
unsigned load0;
unsigned stores;
unsigned store0;
unsigned store1;
unsigned NonZCVIloads;
unsigned AllCVIloads;
unsigned CVIstores;
unsigned duplex;
unsigned pSlot3Cnt;
Optional<HexagonInstr *> PrefSlot3Inst;
unsigned memops;
unsigned ReservedSlotMask;
SmallVector<HexagonInstr *, HEXAGON_PRESHUFFLE_PACKET_SIZE> branchInsts;
Optional<SMLoc> Slot1AOKLoc;
Optional<SMLoc> NoSlot1StoreLoc;
};
HexagonPacket Packet;
protected:
MCContext &Context;
int64_t BundleFlags;
MCInstrInfo const &MCII;
MCSubtargetInfo const &STI;
SMLoc Loc;
bool ReportErrors;
bool CheckFailure;
std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions;
bool applySlotRestrictions(HexagonPacketSummary const &Summary,
const bool DoShuffle);
void restrictSlot1AOK(HexagonPacketSummary const &Summary);
void restrictNoSlot1Store(HexagonPacketSummary const &Summary);
void restrictNoSlot1();
bool restrictStoreLoadOrder(HexagonPacketSummary const &Summary);
void restrictBranchOrder(HexagonPacketSummary const &Summary);
void restrictPreferSlot3(HexagonPacketSummary const &Summary,
const bool DoShuffle);
void permitNonSlot();
Optional<HexagonPacket> tryAuction(HexagonPacketSummary const &Summary);
HexagonPacketSummary GetPacketSummary();
bool ValidPacketMemoryOps(HexagonPacketSummary const &Summary) const;
bool ValidResourceUsage(HexagonPacketSummary const &Summary);
public:
using iterator = HexagonPacket::iterator;
using const_iterator = HexagonPacket::const_iterator;
using packet_range = iterator_range<HexagonPacket::iterator>;
using const_packet_range = iterator_range<HexagonPacket::const_iterator>;
HexagonShuffler(MCContext &Context, bool ReportErrors,
MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
void reset();
bool check(const bool RequireShuffle = true);
bool shuffle();
unsigned size() const { return (Packet.size()); }
bool isMemReorderDisabled() const {
return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0;
}
iterator begin() { return (Packet.begin()); }
iterator end() { return (Packet.end()); }
const_iterator cbegin() const { return (Packet.begin()); }
const_iterator cend() const { return (Packet.end()); }
packet_range insts(HexagonPacket &P) {
return make_range(P.begin(), P.end());
}
const_packet_range insts(HexagonPacket const &P) const {
return make_range(P.begin(), P.end());
}
packet_range insts() { return make_range(begin(), end()); }
const_packet_range insts() const { return make_range(cbegin(), cend()); }
using InstPredicate = bool (*)(MCInstrInfo const &, MCInst const &);
bool HasInstWith(InstPredicate Pred) const {
return llvm::any_of(insts(), [&](HexagonInstr const &I) {
MCInst const &Inst = I.getDesc();
return (*Pred)(MCII, Inst);
});
}
void append(MCInst const &ID, MCInst const *Extender, unsigned S);
void reportError(Twine const &Msg);
void reportResourceError(HexagonPacketSummary const &Summary, StringRef Err);
void reportResourceUsage(HexagonPacketSummary const &Summary);
};
}
#endif