445 lines · c
1//===-- RISCVSubtarget.h - Define Subtarget for the RISC-V ------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file declares the RISC-V specific subclass of TargetSubtargetInfo.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H14#define LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H15 16#include "GISel/RISCVRegisterBankInfo.h"17#include "MCTargetDesc/RISCVBaseInfo.h"18#include "RISCVFrameLowering.h"19#include "RISCVISelLowering.h"20#include "RISCVInstrInfo.h"21#include "llvm/CodeGen/GlobalISel/CallLowering.h"22#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"23#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"24#include "llvm/CodeGen/MachineScheduler.h"25#include "llvm/CodeGen/TargetSubtargetInfo.h"26#include "llvm/IR/DataLayout.h"27#include "llvm/Support/Compiler.h"28#include "llvm/Target/TargetMachine.h"29#include <bitset>30 31#define GET_RISCV_MACRO_FUSION_PRED_DECL32#include "RISCVGenMacroFusion.inc"33 34#define GET_SUBTARGETINFO_HEADER35#include "RISCVGenSubtargetInfo.inc"36 37namespace llvm {38class StringRef;39 40namespace RISCVTuneInfoTable {41 42struct RISCVTuneInfo {43 const char *Name;44 uint8_t PrefFunctionAlignment;45 uint8_t PrefLoopAlignment;46 47 // Information needed by LoopDataPrefetch.48 uint16_t CacheLineSize;49 uint16_t PrefetchDistance;50 uint16_t MinPrefetchStride;51 unsigned MaxPrefetchIterationsAhead;52 53 unsigned MinimumJumpTableEntries;54 55 // Tail duplication threshold at -O3.56 unsigned TailDupAggressiveThreshold;57 58 unsigned MaxStoresPerMemsetOptSize;59 unsigned MaxStoresPerMemset;60 61 unsigned MaxGluedStoresPerMemcpy;62 unsigned MaxStoresPerMemcpyOptSize;63 unsigned MaxStoresPerMemcpy;64 65 unsigned MaxStoresPerMemmoveOptSize;66 unsigned MaxStoresPerMemmove;67 68 unsigned MaxLoadsPerMemcmpOptSize;69 unsigned MaxLoadsPerMemcmp;70 71 // The direction of PostRA scheduling.72 MISched::Direction PostRASchedDirection;73};74 75#define GET_RISCVTuneInfoTable_DECL76#include "RISCVGenSearchableTables.inc"77} // namespace RISCVTuneInfoTable78 79class RISCVSubtarget : public RISCVGenSubtargetInfo {80public:81 // clang-format off82 enum RISCVProcFamilyEnum : uint8_t {83 Others,84 SiFive7,85 VentanaVeyron,86 MIPSP8700,87 Andes45,88 };89 enum RISCVVRGatherCostModelEnum : uint8_t {90 Quadratic,91 NLog2N,92 };93 // clang-format on94private:95 virtual void anchor();96 97 RISCVProcFamilyEnum RISCVProcFamily = Others;98 RISCVVRGatherCostModelEnum RISCVVRGatherCostModel = Quadratic;99 100#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \101 bool ATTRIBUTE = DEFAULT;102#include "RISCVGenSubtargetInfo.inc"103 104 unsigned XSfmmTE = 0;105 unsigned ZvlLen = 0;106 unsigned RVVVectorBitsMin;107 unsigned RVVVectorBitsMax;108 uint8_t MaxInterleaveFactor = 2;109 RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;110 std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;111 const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo;112 113 RISCVFrameLowering FrameLowering;114 RISCVInstrInfo InstrInfo;115 RISCVTargetLowering TLInfo;116 117 /// Initializes using the passed in CPU and feature strings so that we can118 /// use initializer lists for subtarget initialization.119 RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,120 StringRef CPU,121 StringRef TuneCPU,122 StringRef FS,123 StringRef ABIName);124 125public:126 // Initializes the data members to match that of the specified triple.127 RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,128 StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin,129 unsigned RVVVectorLMULMax, const TargetMachine &TM);130 131 ~RISCVSubtarget() override;132 133 // Parses features string setting specified subtarget options. The134 // definition of this function is auto-generated by tblgen.135 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);136 137 const RISCVFrameLowering *getFrameLowering() const override {138 return &FrameLowering;139 }140 const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }141 const RISCVRegisterInfo *getRegisterInfo() const override {142 return &InstrInfo.getRegisterInfo();143 }144 const RISCVTargetLowering *getTargetLowering() const override {145 return &TLInfo;146 }147 148 bool enableMachineScheduler() const override { return true; }149 150 bool enablePostRAScheduler() const override { return UsePostRAScheduler; }151 152 Align getPrefFunctionAlignment() const {153 return Align(TuneInfo->PrefFunctionAlignment);154 }155 Align getPrefLoopAlignment() const {156 return Align(TuneInfo->PrefLoopAlignment);157 }158 159 /// Returns RISC-V processor family.160 /// Avoid this function! CPU specifics should be kept local to this class161 /// and preferably modeled with SubtargetFeatures or properties in162 /// initializeProperties().163 RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }164 165 RISCVVRGatherCostModelEnum getVRGatherCostModel() const { return RISCVVRGatherCostModel; }166 167#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \168 bool GETTER() const { return ATTRIBUTE; }169#include "RISCVGenSubtargetInfo.inc"170 171 LLVM_DEPRECATED("Now Equivalent to hasStdExtZca", "hasStdExtZca")172 bool hasStdExtCOrZca() const { return HasStdExtZca; }173 bool hasStdExtCOrZcd() const { return HasStdExtC || HasStdExtZcd; }174 bool hasStdExtCOrZcfOrZce() const {175 return HasStdExtC || HasStdExtZcf || HasStdExtZce;176 }177 bool hasStdExtZvl() const { return ZvlLen != 0; }178 bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }179 bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }180 bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }181 bool hasStdExtZfhminOrZhinxmin() const {182 return HasStdExtZfhmin || HasStdExtZhinxmin;183 }184 bool hasHalfFPLoadStoreMove() const {185 return HasStdExtZfhmin || HasStdExtZfbfmin;186 }187 188 bool hasCLZLike() const {189 return HasStdExtZbb || HasStdExtP || HasVendorXTHeadBb ||190 (HasVendorXCVbitmanip && !IsRV64);191 }192 bool hasCTZLike() const {193 return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);194 }195 bool hasCPOPLike() const {196 return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64);197 }198 bool hasREV8Like() const {199 return HasStdExtZbb || HasStdExtZbkb || HasStdExtP || HasVendorXTHeadBb;200 }201 202 bool hasBEXTILike() const { return HasStdExtZbs || HasVendorXTHeadBs; }203 204 bool hasCZEROLike() const {205 return HasStdExtZicond || HasVendorXVentanaCondOps;206 }207 208 bool hasConditionalMoveFusion() const {209 // Do we support fusing a branch+mv or branch+c.mv as a conditional move.210 return (hasConditionalCompressedMoveFusion() && hasStdExtZca()) ||211 hasShortForwardBranchIALU();212 }213 214 bool hasShlAdd(int64_t ShAmt) const {215 if (ShAmt <= 0)216 return false;217 if (ShAmt <= 3)218 return HasStdExtZba || HasVendorXAndesPerf || HasVendorXTHeadBa;219 return ShAmt <= 31 && HasVendorXqciac;220 }221 222 bool is64Bit() const { return IsRV64; }223 MVT getXLenVT() const {224 return is64Bit() ? MVT::i64 : MVT::i32;225 }226 unsigned getXLen() const {227 return is64Bit() ? 64 : 32;228 }229 bool useMIPSLoadStorePairs() const;230 bool useMIPSCCMovInsn() const;231 unsigned getFLen() const {232 if (HasStdExtD)233 return 64;234 235 if (HasStdExtF)236 return 32;237 238 return 0;239 }240 241 Align getZilsdAlign() const {242 return Align(enableUnalignedScalarMem() ? 1243 : allowZilsd4ByteAlign() ? 4244 : 8);245 }246 247 unsigned getELen() const {248 assert(hasVInstructions() && "Expected V extension");249 return hasVInstructionsI64() ? 64 : 32;250 }251 unsigned getRealMinVLen() const {252 unsigned VLen = getMinRVVVectorSizeInBits();253 return VLen == 0 ? ZvlLen : VLen;254 }255 unsigned getRealMaxVLen() const {256 unsigned VLen = getMaxRVVVectorSizeInBits();257 return VLen == 0 ? 65536 : VLen;258 }259 // If we know the exact VLEN, return it. Otherwise, return std::nullopt.260 std::optional<unsigned> getRealVLen() const {261 unsigned Min = getRealMinVLen();262 if (Min != getRealMaxVLen())263 return std::nullopt;264 return Min;265 }266 267 /// If the ElementCount or TypeSize \p X is scalable and VScale (VLEN) is268 /// exactly known, returns \p X converted to a fixed quantity. Otherwise269 /// returns \p X unmodified.270 template <typename Quantity> Quantity expandVScale(Quantity X) const {271 if (auto VLen = getRealVLen(); VLen && X.isScalable()) {272 const unsigned VScale = *VLen / RISCV::RVVBitsPerBlock;273 X = Quantity::getFixed(X.getKnownMinValue() * VScale);274 }275 return X;276 }277 278 RISCVABI::ABI getTargetABI() const { return TargetABI; }279 bool isSoftFPABI() const {280 return TargetABI == RISCVABI::ABI_LP64 ||281 TargetABI == RISCVABI::ABI_ILP32 ||282 TargetABI == RISCVABI::ABI_ILP32E;283 }284 bool isRegisterReservedByUser(Register i) const override {285 assert(i.id() < RISCV::NUM_TARGET_REGS && "Register out of range");286 return UserReservedRegister[i.id()];287 }288 289 // XRay support - require D and C extensions.290 bool isXRaySupported() const override { return hasStdExtD() && hasStdExtC(); }291 292 // Vector codegen related methods.293 bool hasVInstructions() const { return HasStdExtZve32x; }294 bool hasVInstructionsI64() const { return HasStdExtZve64x; }295 bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }296 bool hasVInstructionsF16() const { return HasStdExtZvfh; }297 bool hasVInstructionsBF16Minimal() const {298 return HasStdExtZvfbfmin || HasStdExtZvfbfa;299 }300 bool hasVInstructionsF32() const { return HasStdExtZve32f; }301 bool hasVInstructionsF64() const { return HasStdExtZve64d; }302 bool hasVInstructionsBF16() const { return HasStdExtZvfbfa; }303 // F16 and F64 both require F32.304 bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }305 bool hasVInstructionsFullMultiply() const { return HasStdExtV; }306 unsigned getMaxInterleaveFactor() const {307 return hasVInstructions() ? MaxInterleaveFactor : 1;308 }309 310 bool hasOptimizedSegmentLoadStore(unsigned NF) const {311 switch (NF) {312 case 2:313 return hasOptimizedNF2SegmentLoadStore();314 case 3:315 return hasOptimizedNF3SegmentLoadStore();316 case 4:317 return hasOptimizedNF4SegmentLoadStore();318 case 5:319 return hasOptimizedNF5SegmentLoadStore();320 case 6:321 return hasOptimizedNF6SegmentLoadStore();322 case 7:323 return hasOptimizedNF7SegmentLoadStore();324 case 8:325 return hasOptimizedNF8SegmentLoadStore();326 default:327 llvm_unreachable("Unexpected NF");328 }329 }330 331 bool enablePExtCodeGen() const;332 333 // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the334 // vector hardware implementation which may be less than VLEN.335 unsigned getDLenFactor() const {336 if (DLenFactor2)337 return 2;338 return 1;339 }340 341protected:342 // SelectionDAGISel related APIs.343 std::unique_ptr<const SelectionDAGTargetInfo> TSInfo;344 345 // GlobalISel related APIs.346 mutable std::unique_ptr<CallLowering> CallLoweringInfo;347 mutable std::unique_ptr<InstructionSelector> InstSelector;348 mutable std::unique_ptr<LegalizerInfo> Legalizer;349 mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo;350 351 // Return the known range for the bit length of RVV data registers as set352 // at the command line. A value of 0 means nothing is known about that particular353 // limit beyond what's implied by the architecture.354 // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!355 unsigned getMaxRVVVectorSizeInBits() const;356 unsigned getMinRVVVectorSizeInBits() const;357 358public:359 const SelectionDAGTargetInfo *getSelectionDAGInfo() const override;360 const CallLowering *getCallLowering() const override;361 InstructionSelector *getInstructionSelector() const override;362 const LegalizerInfo *getLegalizerInfo() const override;363 const RISCVRegisterBankInfo *getRegBankInfo() const override;364 365 bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }366 bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }367 368 bool useConstantPoolForLargeInts() const;369 370 // Maximum cost used for building integers, integers will be put into constant371 // pool if exceeded.372 unsigned getMaxBuildIntsCost() const;373 374 unsigned getMaxLMULForFixedLengthVectors() const;375 bool useRVVForFixedLengthVectors() const;376 377 bool enableSubRegLiveness() const override;378 379 bool enableMachinePipeliner() const override;380 381 bool useDFAforSMS() const override { return false; }382 383 bool useAA() const override;384 385 unsigned getCacheLineSize() const override {386 return TuneInfo->CacheLineSize;387 };388 unsigned getPrefetchDistance() const override {389 return TuneInfo->PrefetchDistance;390 };391 unsigned getMinPrefetchStride(unsigned NumMemAccesses,392 unsigned NumStridedMemAccesses,393 unsigned NumPrefetches,394 bool HasCall) const override {395 return TuneInfo->MinPrefetchStride;396 };397 unsigned getMaxPrefetchIterationsAhead() const override {398 return TuneInfo->MaxPrefetchIterationsAhead;399 };400 bool enableWritePrefetching() const override { return true; }401 402 unsigned getMinimumJumpTableEntries() const;403 404 unsigned getTailDupAggressiveThreshold() const {405 return TuneInfo->TailDupAggressiveThreshold;406 }407 408 unsigned getMaxStoresPerMemset(bool OptSize) const {409 return OptSize ? TuneInfo->MaxStoresPerMemsetOptSize410 : TuneInfo->MaxStoresPerMemset;411 }412 413 unsigned getMaxGluedStoresPerMemcpy() const {414 return TuneInfo->MaxGluedStoresPerMemcpy;415 }416 417 unsigned getMaxStoresPerMemcpy(bool OptSize) const {418 return OptSize ? TuneInfo->MaxStoresPerMemcpyOptSize419 : TuneInfo->MaxStoresPerMemcpy;420 }421 422 unsigned getMaxStoresPerMemmove(bool OptSize) const {423 return OptSize ? TuneInfo->MaxStoresPerMemmoveOptSize424 : TuneInfo->MaxStoresPerMemmove;425 }426 427 unsigned getMaxLoadsPerMemcmp(bool OptSize) const {428 return OptSize ? TuneInfo->MaxLoadsPerMemcmpOptSize429 : TuneInfo->MaxLoadsPerMemcmp;430 }431 432 MISched::Direction getPostRASchedDirection() const {433 return TuneInfo->PostRASchedDirection;434 }435 436 void overrideSchedPolicy(MachineSchedPolicy &Policy,437 const SchedRegion &Region) const override;438 439 void overridePostRASchedPolicy(MachineSchedPolicy &Policy,440 const SchedRegion &Region) const override;441};442} // namespace llvm443 444#endif445