xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVSubtarget.cpp (revision a8089ea5aee578e08acab2438e82fc9a9ae50ed8)
1 //===-- RISCVSubtarget.cpp - RISC-V Subtarget Information -----------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the RISC-V specific subclass of TargetSubtargetInfo.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "RISCVSubtarget.h"
14 #include "GISel/RISCVCallLowering.h"
15 #include "GISel/RISCVLegalizerInfo.h"
16 #include "GISel/RISCVRegisterBankInfo.h"
17 #include "RISCV.h"
18 #include "RISCVFrameLowering.h"
19 #include "RISCVTargetMachine.h"
20 #include "llvm/CodeGen/MacroFusion.h"
21 #include "llvm/CodeGen/ScheduleDAGMutation.h"
22 #include "llvm/MC/TargetRegistry.h"
23 #include "llvm/Support/ErrorHandling.h"
24 
25 using namespace llvm;
26 
27 #define DEBUG_TYPE "riscv-subtarget"
28 
29 #define GET_SUBTARGETINFO_TARGET_DESC
30 #define GET_SUBTARGETINFO_CTOR
31 #include "RISCVGenSubtargetInfo.inc"
32 
33 #define GET_RISCV_MACRO_FUSION_PRED_IMPL
34 #include "RISCVGenMacroFusion.inc"
35 
36 namespace llvm::RISCVTuneInfoTable {
37 
38 #define GET_RISCVTuneInfoTable_IMPL
39 #include "RISCVGenSearchableTables.inc"
40 } // namespace llvm::RISCVTuneInfoTable
41 
42 static cl::opt<bool> EnableSubRegLiveness("riscv-enable-subreg-liveness",
43                                           cl::init(true), cl::Hidden);
44 
45 static cl::opt<unsigned> RVVVectorLMULMax(
46     "riscv-v-fixed-length-vector-lmul-max",
47     cl::desc("The maximum LMUL value to use for fixed length vectors. "
48              "Fractional LMUL values are not supported."),
49     cl::init(8), cl::Hidden);
50 
51 static cl::opt<bool> RISCVDisableUsingConstantPoolForLargeInts(
52     "riscv-disable-using-constant-pool-for-large-ints",
53     cl::desc("Disable using constant pool for large integers."),
54     cl::init(false), cl::Hidden);
55 
56 static cl::opt<unsigned> RISCVMaxBuildIntsCost(
57     "riscv-max-build-ints-cost",
58     cl::desc("The maximum cost used for building integers."), cl::init(0),
59     cl::Hidden);
60 
61 static cl::opt<bool> UseAA("riscv-use-aa", cl::init(true),
62                            cl::desc("Enable the use of AA during codegen."));
63 
64 static cl::opt<unsigned> RISCVMinimumJumpTableEntries(
65     "riscv-min-jump-table-entries", cl::Hidden,
66     cl::desc("Set minimum number of entries to use a jump table on RISCV"));
67 
68 void RISCVSubtarget::anchor() {}
69 
70 RISCVSubtarget &
71 RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU,
72                                                 StringRef TuneCPU, StringRef FS,
73                                                 StringRef ABIName) {
74   // Determine default and user-specified characteristics
75   bool Is64Bit = TT.isArch64Bit();
76   if (CPU.empty() || CPU == "generic")
77     CPU = Is64Bit ? "generic-rv64" : "generic-rv32";
78 
79   if (TuneCPU.empty())
80     TuneCPU = CPU;
81 
82   TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo(TuneCPU);
83   // If there is no TuneInfo for this CPU, we fail back to generic.
84   if (!TuneInfo)
85     TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo("generic");
86   assert(TuneInfo && "TuneInfo shouldn't be nullptr!");
87 
88   ParseSubtargetFeatures(CPU, TuneCPU, FS);
89   TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName);
90   RISCVFeatures::validate(TT, getFeatureBits());
91   return *this;
92 }
93 
94 RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
95                                StringRef TuneCPU, StringRef FS,
96                                StringRef ABIName, unsigned RVVVectorBitsMin,
97                                unsigned RVVVectorBitsMax,
98                                const TargetMachine &TM)
99     : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS),
100       RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax),
101       FrameLowering(
102           initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
103       InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {
104   CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
105   Legalizer.reset(new RISCVLegalizerInfo(*this));
106 
107   auto *RBI = new RISCVRegisterBankInfo(getHwMode());
108   RegBankInfo.reset(RBI);
109   InstSelector.reset(createRISCVInstructionSelector(
110       *static_cast<const RISCVTargetMachine *>(&TM), *this, *RBI));
111 }
112 
113 const CallLowering *RISCVSubtarget::getCallLowering() const {
114   return CallLoweringInfo.get();
115 }
116 
117 InstructionSelector *RISCVSubtarget::getInstructionSelector() const {
118   return InstSelector.get();
119 }
120 
121 const LegalizerInfo *RISCVSubtarget::getLegalizerInfo() const {
122   return Legalizer.get();
123 }
124 
125 const RegisterBankInfo *RISCVSubtarget::getRegBankInfo() const {
126   return RegBankInfo.get();
127 }
128 
129 bool RISCVSubtarget::useConstantPoolForLargeInts() const {
130   return !RISCVDisableUsingConstantPoolForLargeInts;
131 }
132 
133 unsigned RISCVSubtarget::getMaxBuildIntsCost() const {
134   // Loading integer from constant pool needs two instructions (the reason why
135   // the minimum cost is 2): an address calculation instruction and a load
136   // instruction. Usually, address calculation and instructions used for
137   // building integers (addi, slli, etc.) can be done in one cycle, so here we
138   // set the default cost to (LoadLatency + 1) if no threshold is provided.
139   return RISCVMaxBuildIntsCost == 0
140              ? getSchedModel().LoadLatency + 1
141              : std::max<unsigned>(2, RISCVMaxBuildIntsCost);
142 }
143 
144 unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const {
145   assert(hasVInstructions() &&
146          "Tried to get vector length without Zve or V extension support!");
147 
148   // ZvlLen specifies the minimum required vlen. The upper bound provided by
149   // riscv-v-vector-bits-max should be no less than it.
150   if (RVVVectorBitsMax != 0 && RVVVectorBitsMax < ZvlLen)
151     report_fatal_error("riscv-v-vector-bits-max specified is lower "
152                        "than the Zvl*b limitation");
153 
154   return RVVVectorBitsMax;
155 }
156 
157 unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const {
158   assert(hasVInstructions() &&
159          "Tried to get vector length without Zve or V extension support!");
160 
161   if (RVVVectorBitsMin == -1U)
162     return ZvlLen;
163 
164   // ZvlLen specifies the minimum required vlen. The lower bound provided by
165   // riscv-v-vector-bits-min should be no less than it.
166   if (RVVVectorBitsMin != 0 && RVVVectorBitsMin < ZvlLen)
167     report_fatal_error("riscv-v-vector-bits-min specified is lower "
168                        "than the Zvl*b limitation");
169 
170   return RVVVectorBitsMin;
171 }
172 
173 unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const {
174   assert(hasVInstructions() &&
175          "Tried to get vector length without Zve or V extension support!");
176   assert(RVVVectorLMULMax <= 8 &&
177          llvm::has_single_bit<uint32_t>(RVVVectorLMULMax) &&
178          "V extension requires a LMUL to be at most 8 and a power of 2!");
179   return llvm::bit_floor(std::clamp<unsigned>(RVVVectorLMULMax, 1, 8));
180 }
181 
182 bool RISCVSubtarget::useRVVForFixedLengthVectors() const {
183   return hasVInstructions() && getMinRVVVectorSizeInBits() != 0;
184 }
185 
186 bool RISCVSubtarget::enableSubRegLiveness() const {
187   // FIXME: Enable subregister liveness by default for RVV to better handle
188   // LMUL>1 and segment load/store.
189   return EnableSubRegLiveness;
190 }
191 
192 void RISCVSubtarget::getPostRAMutations(
193     std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
194   Mutations.push_back(createMacroFusionDAGMutation(getMacroFusions()));
195 }
196 
197   /// Enable use of alias analysis during code generation (during MI
198   /// scheduling, DAGCombine, etc.).
199 bool RISCVSubtarget::useAA() const { return UseAA; }
200 
201 unsigned RISCVSubtarget::getMinimumJumpTableEntries() const {
202   return RISCVMinimumJumpTableEntries.getNumOccurrences() > 0
203              ? RISCVMinimumJumpTableEntries
204              : TuneInfo->MinimumJumpTableEntries;
205 }
206