#ifndef LLVM_MC_MCSUBTARGETINFO_H
#define LLVM_MC_MCSUBTARGETINFO_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/SubtargetFeature.h"
#include <cassert>
#include <cstdint>
#include <string>
namespace llvm {
class MCInst;
struct SubtargetFeatureKV {
const char *Key; const char *Desc; unsigned Value; FeatureBitArray Implies;
bool operator<(StringRef S) const {
return StringRef(Key) < S;
}
bool operator<(const SubtargetFeatureKV &Other) const {
return StringRef(Key) < StringRef(Other.Key);
}
};
struct SubtargetSubTypeKV {
const char *Key; FeatureBitArray Implies; FeatureBitArray TuneImplies; const MCSchedModel *SchedModel;
bool operator<(StringRef S) const {
return StringRef(Key) < S;
}
bool operator<(const SubtargetSubTypeKV &Other) const {
return StringRef(Key) < StringRef(Other.Key);
}
};
class MCSubtargetInfo {
Triple TargetTriple;
std::string CPU; std::string TuneCPU; ArrayRef<SubtargetFeatureKV> ProcFeatures; ArrayRef<SubtargetSubTypeKV> ProcDesc;
const MCWriteProcResEntry *WriteProcResTable;
const MCWriteLatencyEntry *WriteLatencyTable;
const MCReadAdvanceEntry *ReadAdvanceTable;
const MCSchedModel *CPUSchedModel;
const InstrStage *Stages; const unsigned *OperandCycles; const unsigned *ForwardingPaths;
FeatureBitset FeatureBits; std::string FeatureString;
public:
MCSubtargetInfo(const MCSubtargetInfo &) = default;
MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU,
StringRef FS, ArrayRef<SubtargetFeatureKV> PF,
ArrayRef<SubtargetSubTypeKV> PD,
const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL,
const MCReadAdvanceEntry *RA, const InstrStage *IS,
const unsigned *OC, const unsigned *FP);
MCSubtargetInfo() = delete;
MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete;
MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete;
virtual ~MCSubtargetInfo() = default;
const Triple &getTargetTriple() const { return TargetTriple; }
StringRef getCPU() const { return CPU; }
StringRef getTuneCPU() const { return TuneCPU; }
const FeatureBitset& getFeatureBits() const { return FeatureBits; }
void setFeatureBits(const FeatureBitset &FeatureBits_) {
FeatureBits = FeatureBits_;
}
StringRef getFeatureString() const { return FeatureString; }
bool hasFeature(unsigned Feature) const {
return FeatureBits[Feature];
}
protected:
void InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, StringRef FS);
public:
void setDefaultFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
FeatureBitset ToggleFeature(uint64_t FB);
FeatureBitset ToggleFeature(const FeatureBitset& FB);
FeatureBitset ToggleFeature(StringRef FS);
FeatureBitset ApplyFeatureFlag(StringRef FS);
FeatureBitset SetFeatureBitsTransitively(const FeatureBitset& FB);
FeatureBitset ClearFeatureBitsTransitively(const FeatureBitset &FB);
bool checkFeatures(StringRef FS) const;
const MCSchedModel &getSchedModelForCPU(StringRef CPU) const;
const MCSchedModel &getSchedModel() const { return *CPUSchedModel; }
const MCWriteProcResEntry *getWriteProcResBegin(
const MCSchedClassDesc *SC) const {
return &WriteProcResTable[SC->WriteProcResIdx];
}
const MCWriteProcResEntry *getWriteProcResEnd(
const MCSchedClassDesc *SC) const {
return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries;
}
const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC,
unsigned DefIdx) const {
assert(DefIdx < SC->NumWriteLatencyEntries &&
"MachineModel does not specify a WriteResource for DefIdx");
return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx];
}
int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx,
unsigned WriteResID) const {
for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx],
*E = I + SC->NumReadAdvanceEntries; I != E; ++I) {
if (I->UseIdx < UseIdx)
continue;
if (I->UseIdx > UseIdx)
break;
if (!I->WriteResourceID || I->WriteResourceID == WriteResID) {
return I->Cycles;
}
}
return 0;
}
ArrayRef<MCReadAdvanceEntry>
getReadAdvanceEntries(const MCSchedClassDesc &SC) const {
if (!SC.NumReadAdvanceEntries)
return ArrayRef<MCReadAdvanceEntry>();
return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx],
SC.NumReadAdvanceEntries);
}
InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;
void initInstrItins(InstrItineraryData &InstrItins) const;
virtual unsigned resolveVariantSchedClass(unsigned SchedClass,
const MCInst *MI,
const MCInstrInfo *MCII,
unsigned CPUID) const {
return 0;
}
bool isCPUStringValid(StringRef CPU) const {
auto Found = llvm::lower_bound(ProcDesc, CPU);
return Found != ProcDesc.end() && StringRef(Found->Key) == CPU;
}
virtual unsigned getHwMode() const { return 0; }
virtual Optional<unsigned> getCacheSize(unsigned Level) const;
virtual Optional<unsigned> getCacheAssociativity(unsigned Level) const;
virtual Optional<unsigned> getCacheLineSize(unsigned Level) const;
virtual unsigned getCacheLineSize() const {
Optional<unsigned> Size = getCacheLineSize(0);
if (Size)
return *Size;
return 0;
}
virtual unsigned getPrefetchDistance() const;
virtual unsigned getMaxPrefetchIterationsAhead() const;
virtual bool enableWritePrefetching() const;
virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses,
unsigned NumStridedMemAccesses,
unsigned NumPrefetches,
bool HasCall) const;
};
}
#endif