xref: /llvm-project/llvm/lib/Target/RISCV/RISCVSubtarget.cpp (revision 0cb7636a462a8d4209e2b6344304eb43f02853eb)
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 "RISCV.h"
17 #include "RISCVFrameLowering.h"
18 #include "RISCVSelectionDAGInfo.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<unsigned> RVVVectorLMULMax(
43     "riscv-v-fixed-length-vector-lmul-max",
44     cl::desc("The maximum LMUL value to use for fixed length vectors. "
45              "Fractional LMUL values are not supported."),
46     cl::init(8), cl::Hidden);
47 
48 static cl::opt<bool> RISCVDisableUsingConstantPoolForLargeInts(
49     "riscv-disable-using-constant-pool-for-large-ints",
50     cl::desc("Disable using constant pool for large integers."),
51     cl::init(false), cl::Hidden);
52 
53 static cl::opt<unsigned> RISCVMaxBuildIntsCost(
54     "riscv-max-build-ints-cost",
55     cl::desc("The maximum cost used for building integers."), cl::init(0),
56     cl::Hidden);
57 
58 static cl::opt<bool> UseAA("riscv-use-aa", cl::init(true),
59                            cl::desc("Enable the use of AA during codegen."));
60 
61 static cl::opt<unsigned> RISCVMinimumJumpTableEntries(
62     "riscv-min-jump-table-entries", cl::Hidden,
63     cl::desc("Set minimum number of entries to use a jump table on RISCV"));
64 
65 static cl::opt<bool>
66     UseMIPSLoadStorePairsOpt("mips-riscv-load-store-pairs",
67                              cl::desc("RISCV: Optimize for load-store bonding"),
68                              cl::init(false), cl::Hidden);
69 
70 static cl::opt<bool>
71     UseCCMovInsn("riscv-ccmov", cl::desc("RISCV: Use 'mips.ccmov' instruction"),
72                  cl::init(true), cl::Hidden);
73 
74 void RISCVSubtarget::anchor() {}
75 
76 RISCVSubtarget &
77 RISCVSubtarget::initializeSubtargetDependencies(const Triple &TT, StringRef CPU,
78                                                 StringRef TuneCPU, StringRef FS,
79                                                 StringRef ABIName) {
80   // Determine default and user-specified characteristics
81   bool Is64Bit = TT.isArch64Bit();
82   if (CPU.empty() || CPU == "generic")
83     CPU = Is64Bit ? "generic-rv64" : "generic-rv32";
84 
85   if (TuneCPU.empty())
86     TuneCPU = CPU;
87 
88   TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo(TuneCPU);
89   // If there is no TuneInfo for this CPU, we fail back to generic.
90   if (!TuneInfo)
91     TuneInfo = RISCVTuneInfoTable::getRISCVTuneInfo("generic");
92   assert(TuneInfo && "TuneInfo shouldn't be nullptr!");
93 
94   ParseSubtargetFeatures(CPU, TuneCPU, FS);
95   TargetABI = RISCVABI::computeTargetABI(TT, getFeatureBits(), ABIName);
96   RISCVFeatures::validate(TT, getFeatureBits());
97   return *this;
98 }
99 
100 RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
101                                StringRef TuneCPU, StringRef FS,
102                                StringRef ABIName, unsigned RVVVectorBitsMin,
103                                unsigned RVVVectorBitsMax,
104                                const TargetMachine &TM)
105     : RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS),
106       RVVVectorBitsMin(RVVVectorBitsMin), RVVVectorBitsMax(RVVVectorBitsMax),
107       FrameLowering(
108           initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
109       InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {
110   TSInfo = std::make_unique<RISCVSelectionDAGInfo>();
111 }
112 
113 RISCVSubtarget::~RISCVSubtarget() = default;
114 
115 const SelectionDAGTargetInfo *RISCVSubtarget::getSelectionDAGInfo() const {
116   return TSInfo.get();
117 }
118 
119 const CallLowering *RISCVSubtarget::getCallLowering() const {
120   if (!CallLoweringInfo)
121     CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
122   return CallLoweringInfo.get();
123 }
124 
125 InstructionSelector *RISCVSubtarget::getInstructionSelector() const {
126   if (!InstSelector) {
127     InstSelector.reset(createRISCVInstructionSelector(
128         *static_cast<const RISCVTargetMachine *>(&TLInfo.getTargetMachine()),
129         *this, *getRegBankInfo()));
130   }
131   return InstSelector.get();
132 }
133 
134 const LegalizerInfo *RISCVSubtarget::getLegalizerInfo() const {
135   if (!Legalizer)
136     Legalizer.reset(new RISCVLegalizerInfo(*this));
137   return Legalizer.get();
138 }
139 
140 const RISCVRegisterBankInfo *RISCVSubtarget::getRegBankInfo() const {
141   if (!RegBankInfo)
142     RegBankInfo.reset(new RISCVRegisterBankInfo(getHwMode()));
143   return RegBankInfo.get();
144 }
145 
146 bool RISCVSubtarget::useConstantPoolForLargeInts() const {
147   return !RISCVDisableUsingConstantPoolForLargeInts;
148 }
149 
150 unsigned RISCVSubtarget::getMaxBuildIntsCost() const {
151   // Loading integer from constant pool needs two instructions (the reason why
152   // the minimum cost is 2): an address calculation instruction and a load
153   // instruction. Usually, address calculation and instructions used for
154   // building integers (addi, slli, etc.) can be done in one cycle, so here we
155   // set the default cost to (LoadLatency + 1) if no threshold is provided.
156   return RISCVMaxBuildIntsCost == 0
157              ? getSchedModel().LoadLatency + 1
158              : std::max<unsigned>(2, RISCVMaxBuildIntsCost);
159 }
160 
161 unsigned RISCVSubtarget::getMaxRVVVectorSizeInBits() const {
162   assert(hasVInstructions() &&
163          "Tried to get vector length without Zve or V extension support!");
164 
165   // ZvlLen specifies the minimum required vlen. The upper bound provided by
166   // riscv-v-vector-bits-max should be no less than it.
167   if (RVVVectorBitsMax != 0 && RVVVectorBitsMax < ZvlLen)
168     report_fatal_error("riscv-v-vector-bits-max specified is lower "
169                        "than the Zvl*b limitation");
170 
171   return RVVVectorBitsMax;
172 }
173 
174 unsigned RISCVSubtarget::getMinRVVVectorSizeInBits() const {
175   assert(hasVInstructions() &&
176          "Tried to get vector length without Zve or V extension support!");
177 
178   if (RVVVectorBitsMin == -1U)
179     return ZvlLen;
180 
181   // ZvlLen specifies the minimum required vlen. The lower bound provided by
182   // riscv-v-vector-bits-min should be no less than it.
183   if (RVVVectorBitsMin != 0 && RVVVectorBitsMin < ZvlLen)
184     report_fatal_error("riscv-v-vector-bits-min specified is lower "
185                        "than the Zvl*b limitation");
186 
187   return RVVVectorBitsMin;
188 }
189 
190 unsigned RISCVSubtarget::getMaxLMULForFixedLengthVectors() const {
191   assert(hasVInstructions() &&
192          "Tried to get vector length without Zve or V extension support!");
193   assert(RVVVectorLMULMax <= 8 &&
194          llvm::has_single_bit<uint32_t>(RVVVectorLMULMax) &&
195          "V extension requires a LMUL to be at most 8 and a power of 2!");
196   return llvm::bit_floor(std::clamp<unsigned>(RVVVectorLMULMax, 1, 8));
197 }
198 
199 bool RISCVSubtarget::useRVVForFixedLengthVectors() const {
200   return hasVInstructions() &&
201          getMinRVVVectorSizeInBits() >= RISCV::RVVBitsPerBlock;
202 }
203 
204 bool RISCVSubtarget::enableSubRegLiveness() const { return true; }
205 
206 bool RISCVSubtarget::enableMachinePipeliner() const {
207   return getSchedModel().hasInstrSchedModel();
208 }
209 
210   /// Enable use of alias analysis during code generation (during MI
211   /// scheduling, DAGCombine, etc.).
212 bool RISCVSubtarget::useAA() const { return UseAA; }
213 
214 unsigned RISCVSubtarget::getMinimumJumpTableEntries() const {
215   return RISCVMinimumJumpTableEntries.getNumOccurrences() > 0
216              ? RISCVMinimumJumpTableEntries
217              : TuneInfo->MinimumJumpTableEntries;
218 }
219 
220 void RISCVSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
221                                          unsigned NumRegionInstrs) const {
222   // Do bidirectional scheduling since it provides a more balanced scheduling
223   // leading to better performance. This will increase compile time.
224   Policy.OnlyTopDown = false;
225   Policy.OnlyBottomUp = false;
226 
227   // Disabling the latency heuristic can reduce the number of spills/reloads but
228   // will cause some regressions on some cores.
229   Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic;
230 
231   // Spilling is generally expensive on all RISC-V cores, so always enable
232   // register-pressure tracking. This will increase compile time.
233   Policy.ShouldTrackPressure = true;
234 }
235 
236 void RISCVSubtarget::overridePostRASchedPolicy(MachineSchedPolicy &Policy,
237                                                unsigned NumRegionInstrs) const {
238   MISched::Direction PostRASchedDirection = getPostRASchedDirection();
239   if (PostRASchedDirection == MISched::TopDown) {
240     Policy.OnlyTopDown = true;
241     Policy.OnlyBottomUp = false;
242   } else if (PostRASchedDirection == MISched::BottomUp) {
243     Policy.OnlyTopDown = false;
244     Policy.OnlyBottomUp = true;
245   } else if (PostRASchedDirection == MISched::Bidirectional) {
246     Policy.OnlyTopDown = false;
247     Policy.OnlyBottomUp = false;
248   }
249 }
250 
251 bool RISCVSubtarget::useCCMovInsn() const {
252   return UseCCMovInsn && HasVendorXMIPSCMove;
253 }
254