llvm-project/llvm/lib/Target/RISCV/RISCVSubtarget.h

320 lines
12 KiB
C++

//===-- 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 "VentusProgramInfo.h"
#include "llvm/ADT/DenseSet.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"
// FIXME: invalid yet
#if defined(__opencl_c_subgroups)
#define SubGroupFlag true
#else
#define SubGroupFlag false
#endif
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 HasStdExtZihintntl = false;
bool HasStdExtZba = false;
bool HasStdExtZbb = false;
bool HasStdExtZbc = false;
bool HasStdExtZbs = false;
bool HasStdExtZca = false;
bool HasStdExtZcd = false;
bool HasStdExtZcf = 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 HasStdExtSvnapot = false;
bool HasStdExtSvinval = false;
bool HasStdExtZmmul = false;
bool HasStdExtZawrs = false;
bool HasStdExtZtso = false;
bool HasVendorXVentanaCondOps = false;
bool HasRV32 = false;
bool HasRV64 = false;
bool IsRV32E = false;
bool EnableLinkerRelax = false;
bool EnableRVCHintInstrs = true;
bool EnableDefaultUnroll = true;
bool EnableSaveRestore = false;
bool EnableUnalignedScalarMem = false;
bool HasShortForwardBranchOpt = false;
bool HasLUIADDIFusion = false;
bool HasForcedAtomics = false;
bool HasOptimizedZeroStrideLoad = true;
unsigned XLen = 32;
unsigned ZvlLen = 0;
MVT XLenVT = MVT::i32;
uint8_t MaxInterleaveFactor = 2;
RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;
RISCVFrameLowering FrameLowering;
RISCVInstrInfo InstrInfo;
RISCVRegisterInfo RegInfo;
RISCVTargetLowering TLInfo;
SelectionDAGTargetInfo TSInfo;
VentusProgramInfo CurrentProgramInfo = VentusProgramInfo();
/// 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 VentusProgramInfo *getVentusProgramInfo() const {
return &CurrentProgramInfo;
}
const DenseSet<unsigned> *getCurrentRegisterAddedSet() const {
return &CurrentProgramInfo.RegisterAddedSetVec[CurrentProgramInfo.RegisterAddedSetVec.size() - 1];
}
const SubVentusProgramInfo *getCurrentSubProgramInfo() const {
return &CurrentProgramInfo.SubProgramInfoVec[CurrentProgramInfo.SubProgramInfoVec.size() - 1];
}
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 hasStdExtCOrZca() const { return HasStdExtC || HasStdExtZca; }
bool hasStdExtV() const { return HasStdExtV; }
bool hasStdExtZihintpause() const { return HasStdExtZihintpause; }
bool hasStdExtZihintntl() const { return HasStdExtZihintntl; }
bool hasStdExtZba() const { return HasStdExtZba; }
bool hasStdExtZbb() const { return HasStdExtZbb; }
bool hasStdExtZbc() const { return HasStdExtZbc; }
bool hasStdExtZbs() const { return HasStdExtZbs; }
bool hasStdExtZca() const { return HasStdExtZca; }
bool hasStdExtZcd() const { return HasStdExtZcd; }
bool hasStdExtZcf() const { return HasStdExtZcf; }
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 hasStdExtSvnapot() const { return HasStdExtSvnapot; }
bool hasStdExtSvinval() const { return HasStdExtSvinval; }
bool hasStdExtZawrs() const { return HasStdExtZawrs; }
bool hasStdExtZmmul() const { return HasStdExtZmmul; }
bool hasStdExtZtso() const { return HasStdExtZtso; }
bool hasVendorXVentanaCondOps() const { return HasVendorXVentanaCondOps; }
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 hasShortForwardBranchOpt() const { return HasShortForwardBranchOpt; }
bool hasSubgroupFlag() const { return SubGroupFlag; };
bool enableUnalignedScalarMem() const { return EnableUnalignedScalarMem; }
bool hasLUIADDIFusion() const { return HasLUIADDIFusion; }
bool hasForcedAtomics() const { return HasForcedAtomics; }
bool hasOptimizedZeroStrideLoad() const { return HasOptimizedZeroStrideLoad; }
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; }
bool hasVInstructionsF32() const {
return HasStdExtZve32f && (HasStdExtF || HasStdExtZfinx);
}
bool hasVInstructionsF64() const {
return HasStdExtZve64d && (HasStdExtD || HasStdExtZdinx);
}
// 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;
};
// VentusProgramInfo RISCVSubtarget::CurrentProgramInfo = VentusProgramInfo();
} // namespace llvm
#endif