xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSubtarget.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
106c3fb27SDimitry Andric //===-- RISCVSubtarget.cpp - RISC-V Subtarget Information -----------------===//
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 implements the RISC-V specific subclass of TargetSubtargetInfo.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "RISCVSubtarget.h"
1406c3fb27SDimitry Andric #include "GISel/RISCVCallLowering.h"
1506c3fb27SDimitry Andric #include "GISel/RISCVLegalizerInfo.h"
160b57cec5SDimitry Andric #include "RISCV.h"
170b57cec5SDimitry Andric #include "RISCVFrameLowering.h"
188bcb0991SDimitry Andric #include "RISCVTargetMachine.h"
19b3edf446SDimitry Andric #include "llvm/CodeGen/MacroFusion.h"
20b3edf446SDimitry Andric #include "llvm/CodeGen/ScheduleDAGMutation.h"
21349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
2204eeddc0SDimitry Andric #include "llvm/Support/ErrorHandling.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "riscv-subtarget"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
290b57cec5SDimitry Andric #define GET_SUBTARGETINFO_CTOR
300b57cec5SDimitry Andric #include "RISCVGenSubtargetInfo.inc"
310b57cec5SDimitry Andric 
32b3edf446SDimitry Andric #define GET_RISCV_MACRO_FUSION_PRED_IMPL
33b3edf446SDimitry Andric #include "RISCVGenMacroFusion.inc"
34b3edf446SDimitry Andric 
355f757f3fSDimitry Andric namespace llvm::RISCVTuneInfoTable {
365f757f3fSDimitry Andric 
375f757f3fSDimitry Andric #define GET_RISCVTuneInfoTable_IMPL
385f757f3fSDimitry Andric #include "RISCVGenSearchableTables.inc"
395f757f3fSDimitry Andric } // namespace llvm::RISCVTuneInfoTable
405f757f3fSDimitry Andric 
41fe6060f1SDimitry Andric static cl::opt<unsigned> RVVVectorLMULMax(
42fe6060f1SDimitry Andric     "riscv-v-fixed-length-vector-lmul-max",
43fe6060f1SDimitry Andric     cl::desc("The maximum LMUL value to use for fixed length vectors. "
44fe6060f1SDimitry Andric              "Fractional LMUL values are not supported."),
45fe6060f1SDimitry Andric     cl::init(8), cl::Hidden);
46fe6060f1SDimitry Andric 
4704eeddc0SDimitry Andric static cl::opt<bool> RISCVDisableUsingConstantPoolForLargeInts(
4804eeddc0SDimitry Andric     "riscv-disable-using-constant-pool-for-large-ints",
4904eeddc0SDimitry Andric     cl::desc("Disable using constant pool for large integers."),
5004eeddc0SDimitry Andric     cl::init(false), cl::Hidden);
5104eeddc0SDimitry Andric 
5204eeddc0SDimitry Andric static cl::opt<unsigned> RISCVMaxBuildIntsCost(
5304eeddc0SDimitry Andric     "riscv-max-build-ints-cost",
5404eeddc0SDimitry Andric     cl::desc("The maximum cost used for building integers."), cl::init(0),
5504eeddc0SDimitry Andric     cl::Hidden);
5604eeddc0SDimitry Andric 
575f757f3fSDimitry Andric static cl::opt<bool> UseAA("riscv-use-aa", cl::init(true),
585f757f3fSDimitry Andric                            cl::desc("Enable the use of AA during codegen."));
595f757f3fSDimitry Andric 
605f757f3fSDimitry Andric static cl::opt<unsigned> RISCVMinimumJumpTableEntries(
615f757f3fSDimitry Andric     "riscv-min-jump-table-entries", cl::Hidden,
625f757f3fSDimitry Andric     cl::desc("Set minimum number of entries to use a jump table on RISCV"));
635f757f3fSDimitry Andric 
640b57cec5SDimitry Andric void RISCVSubtarget::anchor() {}
650b57cec5SDimitry Andric 
66fe6060f1SDimitry Andric RISCVSubtarget &
67fe6060f1SDimitry Andric RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU,
68fe6060f1SDimitry Andric                                                 StringRef TuneCPU, StringRef FS,
69fe6060f1SDimitry Andric                                                 StringRef ABIName) {
700b57cec5SDimitry Andric   // Determine default and user-specified characteristics
710b57cec5SDimitry Andric   bool Is64Bit = TT.isArch64Bit();
7281ad6265SDimitry Andric   if (CPU.empty() || CPU == "generic")
73fe6060f1SDimitry Andric     CPU = Is64Bit ? "generic-rv64" : "generic-rv32";
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric   if (TuneCPU.empty())
76fe6060f1SDimitry Andric     TuneCPU = CPU;
77fe6060f1SDimitry Andric 
785f757f3fSDimitry Andric   TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo(TuneCPU);
795f757f3fSDimitry Andric   // If there is no TuneInfo for this CPU, we fail back to generic.
805f757f3fSDimitry Andric   if (!TuneInfo)
815f757f3fSDimitry Andric     TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo("generic");
825f757f3fSDimitry Andric   assert(TuneInfo && "TuneInfo shouldn't be nullptr!");
830b57cec5SDimitry Andric 
845f757f3fSDimitry Andric   ParseSubtargetFeatures(CPU, TuneCPU, FS);
850b57cec5SDimitry Andric   TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName);
860b57cec5SDimitry Andric   RISCVFeatures::validate(TT, getFeatureBits());
870b57cec5SDimitry Andric   return *this;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
90e8d8bef9SDimitry Andric RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
91e8d8bef9SDimitry Andric                                StringRef TuneCPU, StringRef FS,
92bdd1243dSDimitry Andric                                StringRef ABIName, unsigned RVVVectorBitsMin,
93bdd1243dSDimitry Andric                                unsigned RVVVectorBitsMax,
94bdd1243dSDimitry Andric                                const TargetMachine &TM)
95e8d8bef9SDimitry Andric     : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS),
96bdd1243dSDimitry Andric       RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax),
97bdd1243dSDimitry Andric       FrameLowering(
98bdd1243dSDimitry Andric           initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
99*0fca6ea1SDimitry Andric       InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {}
1008bcb0991SDimitry Andric 
1018bcb0991SDimitry Andric const CallLowering *RISCVSubtarget::getCallLowering() const {
102*0fca6ea1SDimitry Andric   if (!CallLoweringInfo)
103*0fca6ea1SDimitry Andric     CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
1048bcb0991SDimitry Andric   return CallLoweringInfo.get();
1058bcb0991SDimitry Andric }
1068bcb0991SDimitry Andric 
1078bcb0991SDimitry Andric InstructionSelector *RISCVSubtarget::getInstructionSelector() const {
108*0fca6ea1SDimitry Andric   if (!InstSelector) {
109*0fca6ea1SDimitry Andric     InstSelector.reset(createRISCVInstructionSelector(
110*0fca6ea1SDimitry Andric         *static_cast<const RISCVTargetMachine *>(&TLInfo.getTargetMachine()),
111*0fca6ea1SDimitry Andric         *this, *getRegBankInfo()));
112*0fca6ea1SDimitry Andric   }
1138bcb0991SDimitry Andric   return InstSelector.get();
1148bcb0991SDimitry Andric }
1158bcb0991SDimitry Andric 
1168bcb0991SDimitry Andric const LegalizerInfo *RISCVSubtarget::getLegalizerInfo() const {
117*0fca6ea1SDimitry Andric   if (!Legalizer)
118*0fca6ea1SDimitry Andric     Legalizer.reset(new RISCVLegalizerInfo(*this));
1198bcb0991SDimitry Andric   return Legalizer.get();
1208bcb0991SDimitry Andric }
1218bcb0991SDimitry Andric 
122*0fca6ea1SDimitry Andric const RISCVRegisterBankInfo *RISCVSubtarget::getRegBankInfo() const {
123*0fca6ea1SDimitry Andric   if (!RegBankInfo)
124*0fca6ea1SDimitry Andric     RegBankInfo.reset(new RISCVRegisterBankInfo(getHwMode()));
1258bcb0991SDimitry Andric   return RegBankInfo.get();
1268bcb0991SDimitry Andric }
127fe6060f1SDimitry Andric 
12804eeddc0SDimitry Andric bool RISCVSubtarget::useConstantPoolForLargeInts() const {
12904eeddc0SDimitry Andric   return !RISCVDisableUsingConstantPoolForLargeInts;
13004eeddc0SDimitry Andric }
13104eeddc0SDimitry Andric 
13204eeddc0SDimitry Andric unsigned RISCVSubtarget::getMaxBuildIntsCost() const {
13304eeddc0SDimitry Andric   // Loading integer from constant pool needs two instructions (the reason why
13404eeddc0SDimitry Andric   // the minimum cost is 2): an address calculation instruction and a load
13504eeddc0SDimitry Andric   // instruction. Usually, address calculation and instructions used for
13604eeddc0SDimitry Andric   // building integers (addi, slli, etc.) can be done in one cycle, so here we
13704eeddc0SDimitry Andric   // set the default cost to (LoadLatency + 1) if no threshold is provided.
13804eeddc0SDimitry Andric   return RISCVMaxBuildIntsCost == 0
13904eeddc0SDimitry Andric              ? getSchedModel().LoadLatency + 1
14004eeddc0SDimitry Andric              : std::max<unsigned>(2, RISCVMaxBuildIntsCost);
14104eeddc0SDimitry Andric }
14204eeddc0SDimitry Andric 
143fe6060f1SDimitry Andric unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const {
144349cc55cSDimitry Andric   assert(hasVInstructions() &&
145349cc55cSDimitry Andric          "Tried to get vector length without Zve or V extension support!");
14604eeddc0SDimitry Andric 
14704eeddc0SDimitry Andric   // ZvlLen specifies the minimum required vlen. The upper bound provided by
14804eeddc0SDimitry Andric   // riscv-v-vector-bits-max should be no less than it.
149bdd1243dSDimitry Andric   if (RVVVectorBitsMax != 0 && RVVVectorBitsMax < ZvlLen)
15004eeddc0SDimitry Andric     report_fatal_error("riscv-v-vector-bits-max specified is lower "
15104eeddc0SDimitry Andric                        "than the Zvl*b limitation");
15204eeddc0SDimitry Andric 
153bdd1243dSDimitry Andric   return RVVVectorBitsMax;
154fe6060f1SDimitry Andric }
155fe6060f1SDimitry Andric 
156fe6060f1SDimitry Andric unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const {
15781ad6265SDimitry Andric   assert(hasVInstructions() &&
15881ad6265SDimitry Andric          "Tried to get vector length without Zve or V extension support!");
15981ad6265SDimitry Andric 
160bdd1243dSDimitry Andric   if (RVVVectorBitsMin == -1U)
16181ad6265SDimitry Andric     return ZvlLen;
16281ad6265SDimitry Andric 
16304eeddc0SDimitry Andric   // ZvlLen specifies the minimum required vlen. The lower bound provided by
16404eeddc0SDimitry Andric   // riscv-v-vector-bits-min should be no less than it.
165bdd1243dSDimitry Andric   if (RVVVectorBitsMin != 0 && RVVVectorBitsMin < ZvlLen)
16604eeddc0SDimitry Andric     report_fatal_error("riscv-v-vector-bits-min specified is lower "
16704eeddc0SDimitry Andric                        "than the Zvl*b limitation");
16804eeddc0SDimitry Andric 
169bdd1243dSDimitry Andric   return RVVVectorBitsMin;
170fe6060f1SDimitry Andric }
171fe6060f1SDimitry Andric 
172fe6060f1SDimitry Andric unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const {
173349cc55cSDimitry Andric   assert(hasVInstructions() &&
174349cc55cSDimitry Andric          "Tried to get vector length without Zve or V extension support!");
17506c3fb27SDimitry Andric   assert(RVVVectorLMULMax <= 8 &&
17606c3fb27SDimitry Andric          llvm::has_single_bit<uint32_t>(RVVVectorLMULMax) &&
177fe6060f1SDimitry Andric          "V extension requires a LMUL to be at most 8 and a power of 2!");
17806c3fb27SDimitry Andric   return llvm::bit_floor(std::clamp<unsigned>(RVVVectorLMULMax, 1, 8));
179349cc55cSDimitry Andric }
180349cc55cSDimitry Andric 
181fe6060f1SDimitry Andric bool RISCVSubtarget::useRVVForFixedLengthVectors() const {
182349cc55cSDimitry Andric   return hasVInstructions() && getMinRVVVectorSizeInBits() != 0;
183fe6060f1SDimitry Andric }
18481ad6265SDimitry Andric 
185*0fca6ea1SDimitry Andric bool RISCVSubtarget::enableSubRegLiveness() const { return true; }
18681ad6265SDimitry Andric 
18781ad6265SDimitry Andric void RISCVSubtarget::getPostRAMutations(
18881ad6265SDimitry Andric     std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
189b3edf446SDimitry Andric   Mutations.push_back(createMacroFusionDAGMutation(getMacroFusions()));
19081ad6265SDimitry Andric }
1915f757f3fSDimitry Andric 
1925f757f3fSDimitry Andric   /// Enable use of alias analysis during code generation (during MI
1935f757f3fSDimitry Andric   /// scheduling, DAGCombine, etc.).
1945f757f3fSDimitry Andric bool RISCVSubtarget::useAA() const { return UseAA; }
1955f757f3fSDimitry Andric 
1965f757f3fSDimitry Andric unsigned RISCVSubtarget::getMinimumJumpTableEntries() const {
1975f757f3fSDimitry Andric   return RISCVMinimumJumpTableEntries.getNumOccurrences() > 0
1985f757f3fSDimitry Andric              ? RISCVMinimumJumpTableEntries
1995f757f3fSDimitry Andric              : TuneInfo->MinimumJumpTableEntries;
2005f757f3fSDimitry Andric }
201