250 lines
7.7 KiB
C++
250 lines
7.7 KiB
C++
//===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This implements the shuffling of insns inside a bundle according to the
|
|
// packet formation rules of the Hexagon ISA.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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;
|
|
|
|
// Insn resources.
|
|
class HexagonResource {
|
|
// Mask of the slots or units that may execute the insn and
|
|
// the weight or priority that the insn requires to be assigned a slot.
|
|
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); }
|
|
|
|
// Check if the resources are in ascending slot order.
|
|
static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
|
|
return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
|
|
}
|
|
|
|
// Check if the resources are in ascending weight order.
|
|
static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
|
|
return (A.getWeight() < B.getWeight());
|
|
}
|
|
};
|
|
|
|
// HVX insn resources.
|
|
class HexagonCVIResource : public HexagonResource {
|
|
public:
|
|
using UnitsAndLanes = std::pair<unsigned, unsigned>;
|
|
|
|
private:
|
|
// Available HVX slots.
|
|
enum {
|
|
CVI_NONE = 0,
|
|
CVI_XLANE = 1 << 0,
|
|
CVI_SHIFT = 1 << 1,
|
|
CVI_MPY0 = 1 << 2,
|
|
CVI_MPY1 = 1 << 3,
|
|
CVI_ZW = 1 << 4
|
|
};
|
|
|
|
// Count of adjacent slots that the insn requires to be executed.
|
|
unsigned Lanes;
|
|
// Flag whether the insn is a load or a store.
|
|
bool Load, Store;
|
|
// Flag whether the HVX resources are valid.
|
|
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; }
|
|
};
|
|
|
|
// Handle to an insn used by the shuffling algorithm.
|
|
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; }
|
|
|
|
// Check if the handles are in ascending order for shuffling purposes.
|
|
bool operator<(const HexagonInstr &B) const {
|
|
return (HexagonResource::lessWeight(B.Core, Core));
|
|
}
|
|
|
|
// Check if the handles are in ascending order by core slots.
|
|
static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
|
|
return (HexagonResource::lessUnits(A.Core, B.Core));
|
|
}
|
|
|
|
// Check if the handles are in ascending order by HVX slots.
|
|
static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
|
|
return (HexagonResource::lessUnits(A.CVI, B.CVI));
|
|
}
|
|
};
|
|
|
|
// Bundle shuffler.
|
|
class HexagonShuffler {
|
|
using HexagonPacket =
|
|
SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>;
|
|
|
|
struct HexagonPacketSummary {
|
|
// Number of memory operations, loads, solo loads, stores, solo stores,
|
|
// single stores.
|
|
unsigned memory;
|
|
unsigned loads;
|
|
unsigned load0;
|
|
unsigned stores;
|
|
unsigned store0;
|
|
unsigned store1;
|
|
unsigned NonZCVIloads;
|
|
unsigned AllCVIloads;
|
|
unsigned CVIstores;
|
|
// Number of duplex insns
|
|
unsigned duplex;
|
|
unsigned pSlot3Cnt;
|
|
Optional<HexagonInstr *> PrefSlot3Inst;
|
|
unsigned memops;
|
|
unsigned ReservedSlotMask;
|
|
SmallVector<HexagonInstr *, HEXAGON_PRESHUFFLE_PACKET_SIZE> branchInsts;
|
|
Optional<SMLoc> Slot1AOKLoc;
|
|
Optional<SMLoc> NoSlot1StoreLoc;
|
|
};
|
|
// Insn handles in a bundle.
|
|
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);
|
|
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);
|
|
void permitNonSlot();
|
|
|
|
Optional<HexagonPacket> tryAuction(HexagonPacketSummary const &Summary) const;
|
|
|
|
HexagonPacketSummary GetPacketSummary();
|
|
bool ValidPacketMemoryOps(HexagonPacketSummary const &Summary) const;
|
|
bool ValidResourceUsage(HexagonPacketSummary const &Summary);
|
|
bool validPacketInsts() const;
|
|
|
|
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);
|
|
|
|
// Reset to initial state.
|
|
void reset();
|
|
// Check if the bundle may be validly shuffled.
|
|
bool check();
|
|
// Reorder the insn handles in the bundle.
|
|
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);
|
|
});
|
|
}
|
|
|
|
// Add insn handle to the bundle .
|
|
void append(MCInst const &ID, MCInst const *Extender, unsigned S);
|
|
|
|
// Return the error code for the last check or shuffling of the bundle.
|
|
void reportError(Twine const &Msg);
|
|
};
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
|