//===-- RISCVSubtarget.h - Define Subtarget for the RISCV -------*- 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 file declares the RISCV specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
#define LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
#include "MCTargetDesc/RISCVBaseInfo.h"
#include "RISCVFrameLowering.h"
#include "RISCVISelLowering.h"
#include "RISCVInstrInfo.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#define GET_SUBTARGETINFO_HEADER
#include "RISCVGenSubtargetInfo.inc"
namespace llvm {
class StringRef;
class RISCVSubtarget : public RISCVGenSubtargetInfo {
public:
enum RISCVProcFamilyEnum : uint8_t {
Others,
SiFive7,
};
private:
virtual void anchor();
RISCVProcFamilyEnum RISCVProcFamily = Others;
bool HasStdExtM = false;
bool HasStdExtA = false;
bool HasStdExtF = false;
bool HasStdExtD = false;
bool HasStdExtC = false;
bool HasStdExtZihintpause = false;
bool HasStdExtZba = false;
bool HasStdExtZbb = false;
bool HasStdExtZbc = false;
bool HasStdExtZbe = false;
bool HasStdExtZbf = false;
bool HasStdExtZbm = false;
bool HasStdExtZbp = false;
bool HasStdExtZbr = false;
bool HasStdExtZbs = false;
bool HasStdExtZbt = false;
bool HasStdExtV = false;
bool HasStdExtZve32x = false;
bool HasStdExtZve32f = false;
bool HasStdExtZve64x = false;
bool HasStdExtZve64f = false;
bool HasStdExtZve64d = false;
bool HasStdExtZvfh = false;
bool HasStdExtZfhmin = false;
bool HasStdExtZfh = false;
bool HasStdExtZfinx = false;
bool HasStdExtZdinx = false;
bool HasStdExtZhinxmin = false;
bool HasStdExtZhinx = false;
bool HasStdExtZbkb = false;
bool HasStdExtZbkc = false;
bool HasStdExtZbkx = false;
bool HasStdExtZknd = false;
bool HasStdExtZkne = false;
bool HasStdExtZknh = false;
bool HasStdExtZksed = false;
bool HasStdExtZksh = false;
bool HasStdExtZkr = false;
bool HasStdExtZkn = false;
bool HasStdExtZks = false;
bool HasStdExtZkt = false;
bool HasStdExtZk = false;
bool HasStdExtZicbom = false;
bool HasStdExtZicboz = false;
bool HasStdExtZicbop = false;
bool HasStdExtZmmul = false;
bool HasRV64 = false;
bool IsRV32E = false;
bool EnableLinkerRelax = false;
bool EnableRVCHintInstrs = true;
bool EnableDefaultUnroll = true;
bool EnableSaveRestore = false;
bool EnableUnalignedScalarMem = false;
bool HasLUIADDIFusion = false;
unsigned XLen = 32;
unsigned ZvlLen = 0;
MVT XLenVT = MVT::i32;
uint8_t MaxInterleaveFactor = 2;
RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
BitVector UserReservedRegister;
RISCVFrameLowering FrameLowering;
RISCVInstrInfo InstrInfo;
RISCVRegisterInfo RegInfo;
RISCVTargetLowering TLInfo;
SelectionDAGTargetInfo TSInfo;
/// Initializes using the passed in CPU and feature strings so that we can
/// use initializer lists for subtarget initialization.
RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
StringRef CPU,
StringRef TuneCPU,
StringRef FS,
StringRef ABIName);
public:
// Initializes the data members to match that of the specified triple.
RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
StringRef FS, StringRef ABIName, const TargetMachine &TM);
// Parses features string setting specified subtarget options. The
// definition of this function is auto-generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
const RISCVFrameLowering *getFrameLowering() const override {
return &FrameLowering;
}
const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const RISCVRegisterInfo *getRegisterInfo() const override {
return &RegInfo;
}
const RISCVTargetLowering *getTargetLowering() const override {
return &TLInfo;
}
const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
return &TSInfo;
}
bool enableMachineScheduler() const override { return true; }
/// Returns RISCV processor family.
/// Avoid this function! CPU specifics should be kept local to this class
/// and preferably modeled with SubtargetFeatures or properties in
/// initializeProperties().
RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
bool hasStdExtM() const { return HasStdExtM; }
bool hasStdExtA() const { return HasStdExtA; }
bool hasStdExtF() const { return HasStdExtF; }
bool hasStdExtD() const { return HasStdExtD; }
bool hasStdExtC() const { return HasStdExtC; }
bool hasStdExtV() const { return HasStdExtV; }
bool hasStdExtZihintpause() const { return HasStdExtZihintpause; }
bool hasStdExtZba() const { return HasStdExtZba; }
bool hasStdExtZbb() const { return HasStdExtZbb; }
bool hasStdExtZbc() const { return HasStdExtZbc; }
bool hasStdExtZbe() const { return HasStdExtZbe; }
bool hasStdExtZbf() const { return HasStdExtZbf; }
bool hasStdExtZbm() const { return HasStdExtZbm; }
bool hasStdExtZbp() const { return HasStdExtZbp; }
bool hasStdExtZbr() const { return HasStdExtZbr; }
bool hasStdExtZbs() const { return HasStdExtZbs; }
bool hasStdExtZbt() const { return HasStdExtZbt; }
bool hasStdExtZvl() const { return ZvlLen != 0; }
bool hasStdExtZvfh() const { return HasStdExtZvfh; }
bool hasStdExtZfhmin() const { return HasStdExtZfhmin; }
bool hasStdExtZfh() const { return HasStdExtZfh; }
bool hasStdExtZfinx() const { return HasStdExtZfinx; }
bool hasStdExtZdinx() const { return HasStdExtZdinx; }
bool hasStdExtZhinxmin() const { return HasStdExtZhinxmin; }
bool hasStdExtZhinx() const { return HasStdExtZhinx; }
bool hasStdExtZbkb() const { return HasStdExtZbkb; }
bool hasStdExtZbkc() const { return HasStdExtZbkc; }
bool hasStdExtZbkx() const { return HasStdExtZbkx; }
bool hasStdExtZknd() const { return HasStdExtZknd; }
bool hasStdExtZkne() const { return HasStdExtZkne; }
bool hasStdExtZknh() const { return HasStdExtZknh; }
bool hasStdExtZksed() const { return HasStdExtZksed; }
bool hasStdExtZksh() const { return HasStdExtZksh; }
bool hasStdExtZkr() const { return HasStdExtZkr; }
bool hasStdExtZicbom() const { return HasStdExtZicbom; }
bool hasStdExtZicboz() const { return HasStdExtZicboz; }
bool hasStdExtZicbop() const { return HasStdExtZicbop; }
bool hasStdExtZmmul() const { return HasStdExtZmmul; }
bool is64Bit() const { return HasRV64; }
bool isRV32E() const { return IsRV32E; }
bool enableLinkerRelax() const { return EnableLinkerRelax; }
bool enableRVCHintInstrs() const { return EnableRVCHintInstrs; }
bool enableDefaultUnroll() const { return EnableDefaultUnroll; }
bool enableSaveRestore() const { return EnableSaveRestore; }
bool enableUnalignedScalarMem() const { return EnableUnalignedScalarMem; }
bool hasLUIADDIFusion() const { return HasLUIADDIFusion; }
MVT getXLenVT() const { return XLenVT; }
unsigned getXLen() const { return XLen; }
unsigned getFLen() const {
if (HasStdExtD)
return 64;
if (HasStdExtF)
return 32;
return 0;
}
unsigned getELEN() const {
assert(hasVInstructions() && "Expected V extension");
return hasVInstructionsI64() ? 64 : 32;
}
unsigned getRealMinVLen() const {
unsigned VLen = getMinRVVVectorSizeInBits();
return VLen == 0 ? getArchMinVLen() : VLen;
}
unsigned getRealMaxVLen() const {
unsigned VLen = getMaxRVVVectorSizeInBits();
return VLen == 0 ? getArchMaxVLen() : VLen;
}
RISCVABI::ABI getTargetABI() const { return TargetABI; }
bool isRegisterReservedByUser(Register i) const {
assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");
return UserReservedRegister[i];
}
bool hasMacroFusion() const { return hasLUIADDIFusion(); }
// Vector codegen related methods.
bool hasVInstructions() const { return HasStdExtZve32x; }
bool hasVInstructionsI64() const { return HasStdExtZve64x; }
bool hasVInstructionsF16() const { return HasStdExtZvfh && HasStdExtZfh; }
// FIXME: Consider Zfinx in the future
bool hasVInstructionsF32() const { return HasStdExtZve32f && HasStdExtF; }
// FIXME: Consider Zdinx in the future
bool hasVInstructionsF64() const { return HasStdExtZve64d && HasStdExtD; }
// F16 and F64 both require F32.
bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
unsigned getMaxInterleaveFactor() const {
return hasVInstructions() ? MaxInterleaveFactor : 1;
}
protected:
// GlobalISel related APIs.
std::unique_ptr<CallLowering> CallLoweringInfo;
std::unique_ptr<InstructionSelector> InstSelector;
std::unique_ptr<LegalizerInfo> Legalizer;
std::unique_ptr<RegisterBankInfo> RegBankInfo;
// Return the known range for the bit length of RVV data registers as set
// at the command line. A value of 0 means nothing is known about that particular
// limit beyond what's implied by the architecture.
// NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
unsigned getMaxRVVVectorSizeInBits() const;
unsigned getMinRVVVectorSizeInBits() const;
// Return the known range for the bit length of RVV data registers as indicated
// by -march and -mattr.
unsigned getArchMinVLen() const { return ZvlLen; }
unsigned getArchMaxVLen() const { return 65536; }
public:
const CallLowering *getCallLowering() const override;
InstructionSelector *getInstructionSelector() const override;
const LegalizerInfo *getLegalizerInfo() const override;
const RegisterBankInfo *getRegBankInfo() const override;
bool useConstantPoolForLargeInts() const;
// Maximum cost used for building integers, integers will be put into constant
// pool if exceeded.
unsigned getMaxBuildIntsCost() const;
unsigned getMaxLMULForFixedLengthVectors() const;
bool useRVVForFixedLengthVectors() const;
bool enableSubRegLiveness() const override;
void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
&Mutations) const override;
};
} // End llvm namespace
#endif