xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSubtarget.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- RISCVSubtarget.h - Define Subtarget for the RISC-V ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
906c3fb27SDimitry Andric // This file declares the RISC-V specific subclass of TargetSubtargetInfo.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_RISCV_RISCVSUBTARGET_H
150b57cec5SDimitry Andric 
16*0fca6ea1SDimitry Andric #include "GISel/RISCVRegisterBankInfo.h"
17e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVBaseInfo.h"
180b57cec5SDimitry Andric #include "RISCVFrameLowering.h"
190b57cec5SDimitry Andric #include "RISCVISelLowering.h"
200b57cec5SDimitry Andric #include "RISCVInstrInfo.h"
218bcb0991SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h"
228bcb0991SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
238bcb0991SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGTargetInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
260b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
270b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
285f757f3fSDimitry Andric #include <bitset>
290b57cec5SDimitry Andric 
30b3edf446SDimitry Andric #define GET_RISCV_MACRO_FUSION_PRED_DECL
31b3edf446SDimitry Andric #include "RISCVGenMacroFusion.inc"
32b3edf446SDimitry Andric 
330b57cec5SDimitry Andric #define GET_SUBTARGETINFO_HEADER
340b57cec5SDimitry Andric #include "RISCVGenSubtargetInfo.inc"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric namespace llvm {
370b57cec5SDimitry Andric class StringRef;
380b57cec5SDimitry Andric 
395f757f3fSDimitry Andric namespace RISCVTuneInfoTable {
405f757f3fSDimitry Andric 
415f757f3fSDimitry Andric struct RISCVTuneInfo {
425f757f3fSDimitry Andric   const char *Name;
435f757f3fSDimitry Andric   uint8_t PrefFunctionAlignment;
445f757f3fSDimitry Andric   uint8_t PrefLoopAlignment;
455f757f3fSDimitry Andric 
465f757f3fSDimitry Andric   // Information needed by LoopDataPrefetch.
475f757f3fSDimitry Andric   uint16_t CacheLineSize;
485f757f3fSDimitry Andric   uint16_t PrefetchDistance;
495f757f3fSDimitry Andric   uint16_t MinPrefetchStride;
505f757f3fSDimitry Andric   unsigned MaxPrefetchIterationsAhead;
515f757f3fSDimitry Andric 
525f757f3fSDimitry Andric   unsigned MinimumJumpTableEntries;
535f757f3fSDimitry Andric };
545f757f3fSDimitry Andric 
555f757f3fSDimitry Andric #define GET_RISCVTuneInfoTable_DECL
565f757f3fSDimitry Andric #include "RISCVGenSearchableTables.inc"
575f757f3fSDimitry Andric } // namespace RISCVTuneInfoTable
585f757f3fSDimitry Andric 
590b57cec5SDimitry Andric class RISCVSubtarget : public RISCVGenSubtargetInfo {
6004eeddc0SDimitry Andric public:
615f757f3fSDimitry Andric   // clang-format off
6204eeddc0SDimitry Andric   enum RISCVProcFamilyEnum : uint8_t {
6304eeddc0SDimitry Andric     Others,
6404eeddc0SDimitry Andric     SiFive7,
655f757f3fSDimitry Andric     VentanaVeyron,
6604eeddc0SDimitry Andric   };
675f757f3fSDimitry Andric   // clang-format on
6804eeddc0SDimitry Andric private:
690b57cec5SDimitry Andric   virtual void anchor();
7004eeddc0SDimitry Andric 
7104eeddc0SDimitry Andric   RISCVProcFamilyEnum RISCVProcFamily = Others;
7204eeddc0SDimitry Andric 
73bdd1243dSDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
74bdd1243dSDimitry Andric   bool ATTRIBUTE = DEFAULT;
75bdd1243dSDimitry Andric #include "RISCVGenSubtargetInfo.inc"
76bdd1243dSDimitry Andric 
7781ad6265SDimitry Andric   unsigned ZvlLen = 0;
78bdd1243dSDimitry Andric   unsigned RVVVectorBitsMin;
79bdd1243dSDimitry Andric   unsigned RVVVectorBitsMax;
80fe6060f1SDimitry Andric   uint8_t MaxInterleaveFactor = 2;
810b57cec5SDimitry Andric   RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown;
82bdd1243dSDimitry Andric   std::bitset<RISCV::NUM_TARGET_REGS> UserReservedRegister;
835f757f3fSDimitry Andric   const RISCVTuneInfoTable::RISCVTuneInfo *TuneInfo;
8406c3fb27SDimitry Andric 
850b57cec5SDimitry Andric   RISCVFrameLowering FrameLowering;
860b57cec5SDimitry Andric   RISCVInstrInfo InstrInfo;
870b57cec5SDimitry Andric   RISCVRegisterInfo RegInfo;
880b57cec5SDimitry Andric   RISCVTargetLowering TLInfo;
890b57cec5SDimitry Andric   SelectionDAGTargetInfo TSInfo;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Initializes using the passed in CPU and feature strings so that we can
920b57cec5SDimitry Andric   /// use initializer lists for subtarget initialization.
930b57cec5SDimitry Andric   RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
94e8d8bef9SDimitry Andric                                                   StringRef CPU,
95e8d8bef9SDimitry Andric                                                   StringRef TuneCPU,
96e8d8bef9SDimitry Andric                                                   StringRef FS,
970b57cec5SDimitry Andric                                                   StringRef ABIName);
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric public:
1000b57cec5SDimitry Andric   // Initializes the data members to match that of the specified triple.
101e8d8bef9SDimitry Andric   RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
102bdd1243dSDimitry Andric                  StringRef FS, StringRef ABIName, unsigned RVVVectorBitsMin,
103bdd1243dSDimitry Andric                  unsigned RVVVectorLMULMax, const TargetMachine &TM);
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   // Parses features string setting specified subtarget options. The
1060b57cec5SDimitry Andric   // definition of this function is auto-generated by tblgen.
107e8d8bef9SDimitry Andric   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   const RISCVFrameLowering *getFrameLowering() const override {
1100b57cec5SDimitry Andric     return &FrameLowering;
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric   const RISCVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
1130b57cec5SDimitry Andric   const RISCVRegisterInfo *getRegisterInfo() const override {
1140b57cec5SDimitry Andric     return &RegInfo;
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric   const RISCVTargetLowering *getTargetLowering() const override {
1170b57cec5SDimitry Andric     return &TLInfo;
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric   const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
1200b57cec5SDimitry Andric     return &TSInfo;
1210b57cec5SDimitry Andric   }
1228bcb0991SDimitry Andric   bool enableMachineScheduler() const override { return true; }
12304eeddc0SDimitry Andric 
124*0fca6ea1SDimitry Andric   bool enablePostRAScheduler() const override { return UsePostRAScheduler; }
1255f757f3fSDimitry Andric 
1265f757f3fSDimitry Andric   Align getPrefFunctionAlignment() const {
1275f757f3fSDimitry Andric     return Align(TuneInfo->PrefFunctionAlignment);
1285f757f3fSDimitry Andric   }
1295f757f3fSDimitry Andric   Align getPrefLoopAlignment() const {
1305f757f3fSDimitry Andric     return Align(TuneInfo->PrefLoopAlignment);
1315f757f3fSDimitry Andric   }
13206c3fb27SDimitry Andric 
13306c3fb27SDimitry Andric   /// Returns RISC-V processor family.
13404eeddc0SDimitry Andric   /// Avoid this function! CPU specifics should be kept local to this class
13504eeddc0SDimitry Andric   /// and preferably modeled with SubtargetFeatures or properties in
13604eeddc0SDimitry Andric   /// initializeProperties().
13704eeddc0SDimitry Andric   RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; }
13804eeddc0SDimitry Andric 
139bdd1243dSDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
140bdd1243dSDimitry Andric   bool GETTER() const { return ATTRIBUTE; }
141bdd1243dSDimitry Andric #include "RISCVGenSubtargetInfo.inc"
142bdd1243dSDimitry Andric 
143bdd1243dSDimitry Andric   bool hasStdExtCOrZca() const { return HasStdExtC || HasStdExtZca; }
144*0fca6ea1SDimitry Andric   bool hasStdExtCOrZcd() const { return HasStdExtC || HasStdExtZcd; }
145*0fca6ea1SDimitry Andric   bool hasStdExtCOrZcfOrZce() const {
146*0fca6ea1SDimitry Andric     return HasStdExtC || HasStdExtZcf || HasStdExtZce;
147*0fca6ea1SDimitry Andric   }
14881ad6265SDimitry Andric   bool hasStdExtZvl() const { return ZvlLen != 0; }
14906c3fb27SDimitry Andric   bool hasStdExtFOrZfinx() const { return HasStdExtF || HasStdExtZfinx; }
15006c3fb27SDimitry Andric   bool hasStdExtDOrZdinx() const { return HasStdExtD || HasStdExtZdinx; }
15106c3fb27SDimitry Andric   bool hasStdExtZfhOrZhinx() const { return HasStdExtZfh || HasStdExtZhinx; }
152cb14a3feSDimitry Andric   bool hasStdExtZfhminOrZhinxmin() const {
153cb14a3feSDimitry Andric     return HasStdExtZfhmin || HasStdExtZhinxmin;
15406c3fb27SDimitry Andric   }
15506c3fb27SDimitry Andric   bool hasHalfFPLoadStoreMove() const {
156cb14a3feSDimitry Andric     return HasStdExtZfhmin || HasStdExtZfbfmin;
15706c3fb27SDimitry Andric   }
1581db9f3b2SDimitry Andric 
1591db9f3b2SDimitry Andric   bool hasConditionalMoveFusion() const {
1601db9f3b2SDimitry Andric     // Do we support fusing a branch+mv or branch+c.mv as a conditional move.
1611db9f3b2SDimitry Andric     return (hasConditionalCompressedMoveFusion() && hasStdExtCOrZca()) ||
1621db9f3b2SDimitry Andric            hasShortForwardBranchOpt();
1631db9f3b2SDimitry Andric   }
1641db9f3b2SDimitry Andric 
16506c3fb27SDimitry Andric   bool is64Bit() const { return IsRV64; }
1665f757f3fSDimitry Andric   MVT getXLenVT() const {
1675f757f3fSDimitry Andric     return is64Bit() ? MVT::i64 : MVT::i32;
1685f757f3fSDimitry Andric   }
1695f757f3fSDimitry Andric   unsigned getXLen() const {
1705f757f3fSDimitry Andric     return is64Bit() ? 64 : 32;
1715f757f3fSDimitry Andric   }
17204eeddc0SDimitry Andric   unsigned getFLen() const {
17304eeddc0SDimitry Andric     if (HasStdExtD)
17404eeddc0SDimitry Andric       return 64;
17504eeddc0SDimitry Andric 
17604eeddc0SDimitry Andric     if (HasStdExtF)
17704eeddc0SDimitry Andric       return 32;
17804eeddc0SDimitry Andric 
17904eeddc0SDimitry Andric     return 0;
18004eeddc0SDimitry Andric   }
1815f757f3fSDimitry Andric   unsigned getELen() const {
18281ad6265SDimitry Andric     assert(hasVInstructions() && "Expected V extension");
18381ad6265SDimitry Andric     return hasVInstructionsI64() ? 64 : 32;
18481ad6265SDimitry Andric   }
18581ad6265SDimitry Andric   unsigned getRealMinVLen() const {
18681ad6265SDimitry Andric     unsigned VLen = getMinRVVVectorSizeInBits();
187bdd1243dSDimitry Andric     return VLen == 0 ? ZvlLen : VLen;
18881ad6265SDimitry Andric   }
18981ad6265SDimitry Andric   unsigned getRealMaxVLen() const {
19081ad6265SDimitry Andric     unsigned VLen = getMaxRVVVectorSizeInBits();
191bdd1243dSDimitry Andric     return VLen == 0 ? 65536 : VLen;
19281ad6265SDimitry Andric   }
193*0fca6ea1SDimitry Andric   // If we know the exact VLEN, return it.  Otherwise, return std::nullopt.
194*0fca6ea1SDimitry Andric   std::optional<unsigned> getRealVLen() const {
195*0fca6ea1SDimitry Andric     unsigned Min = getRealMinVLen();
196*0fca6ea1SDimitry Andric     if (Min != getRealMaxVLen())
197*0fca6ea1SDimitry Andric       return std::nullopt;
198*0fca6ea1SDimitry Andric     return Min;
199*0fca6ea1SDimitry Andric   }
200*0fca6ea1SDimitry Andric 
201*0fca6ea1SDimitry Andric   /// If the ElementCount or TypeSize \p X is scalable and VScale (VLEN) is
202*0fca6ea1SDimitry Andric   /// exactly known, returns \p X converted to a fixed quantity. Otherwise
203*0fca6ea1SDimitry Andric   /// returns \p X unmodified.
204*0fca6ea1SDimitry Andric   template <typename Quantity> Quantity expandVScale(Quantity X) const {
205*0fca6ea1SDimitry Andric     if (auto VLen = getRealVLen(); VLen && X.isScalable()) {
206*0fca6ea1SDimitry Andric       const unsigned VScale = *VLen / RISCV::RVVBitsPerBlock;
207*0fca6ea1SDimitry Andric       X = Quantity::getFixed(X.getKnownMinValue() * VScale);
208*0fca6ea1SDimitry Andric     }
209*0fca6ea1SDimitry Andric     return X;
210*0fca6ea1SDimitry Andric   }
211*0fca6ea1SDimitry Andric 
2120b57cec5SDimitry Andric   RISCVABI::ABI getTargetABI() const { return TargetABI; }
21306c3fb27SDimitry Andric   bool isSoftFPABI() const {
21406c3fb27SDimitry Andric     return TargetABI == RISCVABI::ABI_LP64 ||
21506c3fb27SDimitry Andric            TargetABI == RISCVABI::ABI_ILP32 ||
21606c3fb27SDimitry Andric            TargetABI == RISCVABI::ABI_ILP32E;
21706c3fb27SDimitry Andric   }
218480093f4SDimitry Andric   bool isRegisterReservedByUser(Register i) const {
219480093f4SDimitry Andric     assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");
220480093f4SDimitry Andric     return UserReservedRegister[i];
221480093f4SDimitry Andric   }
222349cc55cSDimitry Andric 
223349cc55cSDimitry Andric   // Vector codegen related methods.
22481ad6265SDimitry Andric   bool hasVInstructions() const { return HasStdExtZve32x; }
22581ad6265SDimitry Andric   bool hasVInstructionsI64() const { return HasStdExtZve64x; }
226cb14a3feSDimitry Andric   bool hasVInstructionsF16Minimal() const { return HasStdExtZvfhmin; }
22706c3fb27SDimitry Andric   bool hasVInstructionsF16() const { return HasStdExtZvfh; }
2285f757f3fSDimitry Andric   bool hasVInstructionsBF16() const { return HasStdExtZvfbfmin; }
2295f757f3fSDimitry Andric   bool hasVInstructionsF32() const { return HasStdExtZve32f; }
2305f757f3fSDimitry Andric   bool hasVInstructionsF64() const { return HasStdExtZve64d; }
231349cc55cSDimitry Andric   // F16 and F64 both require F32.
232349cc55cSDimitry Andric   bool hasVInstructionsAnyF() const { return hasVInstructionsF32(); }
23306c3fb27SDimitry Andric   bool hasVInstructionsFullMultiply() const { return HasStdExtV; }
234fe6060f1SDimitry Andric   unsigned getMaxInterleaveFactor() const {
235349cc55cSDimitry Andric     return hasVInstructions() ? MaxInterleaveFactor : 1;
236fe6060f1SDimitry Andric   }
2378bcb0991SDimitry Andric 
23806c3fb27SDimitry Andric   // Returns VLEN divided by DLEN. Where DLEN is the datapath width of the
23906c3fb27SDimitry Andric   // vector hardware implementation which may be less than VLEN.
24006c3fb27SDimitry Andric   unsigned getDLenFactor() const {
24106c3fb27SDimitry Andric     if (DLenFactor2)
24206c3fb27SDimitry Andric       return 2;
24306c3fb27SDimitry Andric     return 1;
24406c3fb27SDimitry Andric   }
24506c3fb27SDimitry Andric 
2468bcb0991SDimitry Andric protected:
2478bcb0991SDimitry Andric   // GlobalISel related APIs.
248*0fca6ea1SDimitry Andric   mutable std::unique_ptr<CallLowering> CallLoweringInfo;
249*0fca6ea1SDimitry Andric   mutable std::unique_ptr<InstructionSelector> InstSelector;
250*0fca6ea1SDimitry Andric   mutable std::unique_ptr<LegalizerInfo> Legalizer;
251*0fca6ea1SDimitry Andric   mutable std::unique_ptr<RISCVRegisterBankInfo> RegBankInfo;
2528bcb0991SDimitry Andric 
25381ad6265SDimitry Andric   // Return the known range for the bit length of RVV data registers as set
25481ad6265SDimitry Andric   // at the command line. A value of 0 means nothing is known about that particular
25581ad6265SDimitry Andric   // limit beyond what's implied by the architecture.
25681ad6265SDimitry Andric   // NOTE: Please use getRealMinVLen and getRealMaxVLen instead!
25781ad6265SDimitry Andric   unsigned getMaxRVVVectorSizeInBits() const;
25881ad6265SDimitry Andric   unsigned getMinRVVVectorSizeInBits() const;
25981ad6265SDimitry Andric 
2608bcb0991SDimitry Andric public:
2618bcb0991SDimitry Andric   const CallLowering *getCallLowering() const override;
2628bcb0991SDimitry Andric   InstructionSelector *getInstructionSelector() const override;
2638bcb0991SDimitry Andric   const LegalizerInfo *getLegalizerInfo() const override;
264*0fca6ea1SDimitry Andric   const RISCVRegisterBankInfo *getRegBankInfo() const override;
265fe6060f1SDimitry Andric 
266*0fca6ea1SDimitry Andric   bool isTargetAndroid() const { return getTargetTriple().isAndroid(); }
2671ac55f4cSDimitry Andric   bool isTargetFuchsia() const { return getTargetTriple().isOSFuchsia(); }
2681ac55f4cSDimitry Andric 
26904eeddc0SDimitry Andric   bool useConstantPoolForLargeInts() const;
27004eeddc0SDimitry Andric 
27104eeddc0SDimitry Andric   // Maximum cost used for building integers, integers will be put into constant
27204eeddc0SDimitry Andric   // pool if exceeded.
27304eeddc0SDimitry Andric   unsigned getMaxBuildIntsCost() const;
27404eeddc0SDimitry Andric 
275fe6060f1SDimitry Andric   unsigned getMaxLMULForFixedLengthVectors() const;
276fe6060f1SDimitry Andric   bool useRVVForFixedLengthVectors() const;
27781ad6265SDimitry Andric 
27881ad6265SDimitry Andric   bool enableSubRegLiveness() const override;
27981ad6265SDimitry Andric 
28081ad6265SDimitry Andric   void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
28181ad6265SDimitry Andric                               &Mutations) const override;
2825f757f3fSDimitry Andric 
2835f757f3fSDimitry Andric   bool useAA() const override;
2845f757f3fSDimitry Andric 
2855f757f3fSDimitry Andric   unsigned getCacheLineSize() const override {
2865f757f3fSDimitry Andric     return TuneInfo->CacheLineSize;
2875f757f3fSDimitry Andric   };
2885f757f3fSDimitry Andric   unsigned getPrefetchDistance() const override {
2895f757f3fSDimitry Andric     return TuneInfo->PrefetchDistance;
2905f757f3fSDimitry Andric   };
2915f757f3fSDimitry Andric   unsigned getMinPrefetchStride(unsigned NumMemAccesses,
2925f757f3fSDimitry Andric                                 unsigned NumStridedMemAccesses,
2935f757f3fSDimitry Andric                                 unsigned NumPrefetches,
2945f757f3fSDimitry Andric                                 bool HasCall) const override {
2955f757f3fSDimitry Andric     return TuneInfo->MinPrefetchStride;
2965f757f3fSDimitry Andric   };
2975f757f3fSDimitry Andric   unsigned getMaxPrefetchIterationsAhead() const override {
2985f757f3fSDimitry Andric     return TuneInfo->MaxPrefetchIterationsAhead;
2995f757f3fSDimitry Andric   };
3005f757f3fSDimitry Andric 
3015f757f3fSDimitry Andric   unsigned getMinimumJumpTableEntries() const;
302*0fca6ea1SDimitry Andric 
303*0fca6ea1SDimitry Andric   bool supportsInitUndef() const override { return hasVInstructions(); }
3040b57cec5SDimitry Andric };
3050b57cec5SDimitry Andric } // End llvm namespace
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric #endif
308