1//===-- MipsSubtarget.cpp - Mips 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 Mips specific subclass of TargetSubtargetInfo.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsSubtarget.h"
14#include "Mips.h"
15#include "MipsCallLowering.h"
16#include "MipsLegalizerInfo.h"
17#include "MipsRegisterBankInfo.h"
18#include "MipsRegisterInfo.h"
19#include "MipsSelectionDAGInfo.h"
20#include "MipsTargetMachine.h"
21#include "llvm/IR/Attributes.h"
22#include "llvm/IR/Function.h"
23#include "llvm/MC/TargetRegistry.h"
24#include "llvm/Support/CommandLine.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/raw_ostream.h"
27
28using namespace llvm;
29
30cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy(
31 "mips-compact-branches", cl::init(Val: CB_Optimal),
32 cl::desc("MIPS Specific: Compact branch policy."),
33 cl::values(clEnumValN(CB_Never, "never",
34 "Do not use compact branches if possible."),
35 clEnumValN(CB_Optimal, "optimal",
36 "Use compact branches where appropriate (default)."),
37 clEnumValN(CB_Always, "always",
38 "Always use compact branches if possible.")));
39
40#define DEBUG_TYPE "mips-subtarget"
41
42#define GET_SUBTARGETINFO_TARGET_DESC
43#define GET_SUBTARGETINFO_CTOR
44#include "MipsGenSubtargetInfo.inc"
45
46static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden,
47 cl::desc("Enable mips16 hard float."),
48 cl::init(Val: false));
49
50static cl::opt<bool>
51 Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden,
52 cl::desc("Enable mips16 constant islands."),
53 cl::init(Val: true));
54
55static cl::opt<bool>
56 GPOpt("mgpopt", cl::Hidden,
57 cl::desc("Enable gp-relative addressing of mips small data items"));
58
59bool MipsSubtarget::DspWarningPrinted = false;
60bool MipsSubtarget::MSAWarningPrinted = false;
61bool MipsSubtarget::VirtWarningPrinted = false;
62bool MipsSubtarget::CRCWarningPrinted = false;
63bool MipsSubtarget::GINVWarningPrinted = false;
64
65void MipsSubtarget::anchor() {}
66
67MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
68 StringRef ABIName, bool little,
69 const MipsTargetMachine &TM,
70 MaybeAlign StackAlignOverride)
71 : MipsGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
72 MipsArchVersion(MipsDefault), IsLittle(little), IsSoftFloat(false),
73 IsSingleFloat(false), IsFPXX(false), NoABICalls(false), Abs2008(false),
74 IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false),
75 IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasCnMipsP(false),
76 IsR5900(false), FixR5900(false), HasMips3_32(false), HasMips3_32r2(false),
77 HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false),
78 InMips16Mode(false), InMips16HardFloat(Mips16HardFloat),
79 InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), HasDSPR3(false),
80 HasMSA(false), UseTCCInDIV(false), HasSym32(false), HasEVA(false),
81 DisableMadd4(false), HasMT(false), HasCRC(false), HasVirt(false),
82 HasGINV(false), UseIndirectJumpsHazard(false), StrictAlign(false),
83 UseCompactBranches(MipsCompactBranchPolicy != CB_Never),
84 StackAlignOverride(StackAlignOverride), TM(TM),
85 ABI(MipsABIInfo::computeTargetABI(TT, ABIName)),
86 InstrInfo(
87 MipsInstrInfo::create(STI&: initializeSubtargetDependencies(CPU, FS, TM))),
88 FrameLowering(MipsFrameLowering::create(ST: *this)),
89 TLInfo(MipsTargetLowering::create(TM, STI: *this)) {
90
91 if (MipsArchVersion == MipsDefault)
92 MipsArchVersion = Mips32;
93
94 // Don't even attempt to generate code for MIPS-V. It has not
95 // been tested and currently exists for the integrated assembler only.
96 if (MipsArchVersion == Mips5)
97 report_fatal_error(reason: "Code generation for MIPS-V is not implemented", gen_crash_diag: false);
98
99 // Check if Architecture and ABI are compatible.
100 assert(((!isGP64bit() && isABI_O32()) || isGP64bit()) &&
101 "Invalid Arch & ABI pair.");
102
103 if (hasMSA() && !isFP64bit())
104 report_fatal_error(reason: "MSA requires a 64-bit FPU register file (FR=1 mode). "
105 "See -mattr=+fp64.",
106 gen_crash_diag: false);
107
108 if (isFP64bit() && !hasMips64() && hasMips32() && !hasMips32r2())
109 report_fatal_error(
110 reason: "FPU with 64-bit registers is not available on MIPS32 pre revision 2. "
111 "Use -mcpu=mips32r2 or greater.", gen_crash_diag: false);
112
113 if (!isABI_O32() && !useOddSPReg())
114 report_fatal_error(reason: "-mattr=+nooddspreg requires the O32 ABI.", gen_crash_diag: false);
115
116 if (IsFPXX && (isABI_N32() || isABI_N64()))
117 report_fatal_error(reason: "FPXX is not permitted for the N32/N64 ABI's.", gen_crash_diag: false);
118
119 if (hasMips64r6() && InMicroMipsMode)
120 report_fatal_error(reason: "microMIPS64R6 is not supported", gen_crash_diag: false);
121
122 if (!isABI_O32() && InMicroMipsMode)
123 report_fatal_error(reason: "microMIPS64 is not supported.", gen_crash_diag: false);
124
125 if (UseIndirectJumpsHazard) {
126 if (InMicroMipsMode)
127 report_fatal_error(
128 reason: "cannot combine indirect jumps with hazard barriers and microMIPS");
129 if (!hasMips32r2())
130 report_fatal_error(
131 reason: "indirect jumps with hazard barriers requires MIPS32R2 or later");
132 }
133 if (inAbs2008Mode() && hasMips32() && !hasMips32r2()) {
134 report_fatal_error(reason: "IEEE 754-2008 abs.fmt is not supported for the given "
135 "architecture.",
136 gen_crash_diag: false);
137 }
138
139 if (hasMips32r6()) {
140 StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
141
142 assert(isFP64bit());
143 assert(isNaN2008());
144 assert(inAbs2008Mode());
145 if (hasDSP())
146 report_fatal_error(reason: ISA + " is not compatible with the DSP ASE", gen_crash_diag: false);
147 }
148
149 if (NoABICalls && TM.isPositionIndependent())
150 report_fatal_error(reason: "position-independent code requires '-mabicalls'");
151
152 if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32())
153 NoABICalls = true;
154
155 // Set UseSmallSection.
156 UseSmallSection = GPOpt;
157 if (!NoABICalls && GPOpt) {
158 errs() << "warning: cannot use small-data accesses for '-mabicalls'"
159 << "\n";
160 UseSmallSection = false;
161 }
162
163 if (hasDSPR2() && !DspWarningPrinted) {
164 if (hasMips64() && !hasMips64r2()) {
165 errs() << "warning: the 'dspr2' ASE requires MIPS64 revision 2 or "
166 << "greater\n";
167 DspWarningPrinted = true;
168 } else if (hasMips32() && !hasMips32r2()) {
169 errs() << "warning: the 'dspr2' ASE requires MIPS32 revision 2 or "
170 << "greater\n";
171 DspWarningPrinted = true;
172 }
173 } else if (hasDSP() && !DspWarningPrinted) {
174 if (hasMips64() && !hasMips64r2()) {
175 errs() << "warning: the 'dsp' ASE requires MIPS64 revision 2 or "
176 << "greater\n";
177 DspWarningPrinted = true;
178 } else if (hasMips32() && !hasMips32r2()) {
179 errs() << "warning: the 'dsp' ASE requires MIPS32 revision 2 or "
180 << "greater\n";
181 DspWarningPrinted = true;
182 }
183 }
184
185 StringRef ArchName = hasMips64() ? "MIPS64" : "MIPS32";
186
187 if (!hasMips32r5() && hasMSA() && !MSAWarningPrinted) {
188 errs() << "warning: the 'msa' ASE requires " << ArchName
189 << " revision 5 or greater\n";
190 MSAWarningPrinted = true;
191 }
192 if (!hasMips32r5() && hasVirt() && !VirtWarningPrinted) {
193 errs() << "warning: the 'virt' ASE requires " << ArchName
194 << " revision 5 or greater\n";
195 VirtWarningPrinted = true;
196 }
197 if (!hasMips32r6() && hasCRC() && !CRCWarningPrinted) {
198 errs() << "warning: the 'crc' ASE requires " << ArchName
199 << " revision 6 or greater\n";
200 CRCWarningPrinted = true;
201 }
202 if (!hasMips32r6() && hasGINV() && !GINVWarningPrinted) {
203 errs() << "warning: the 'ginv' ASE requires " << ArchName
204 << " revision 6 or greater\n";
205 GINVWarningPrinted = true;
206 }
207
208 TSInfo = std::make_unique<MipsSelectionDAGInfo>();
209
210 CallLoweringInfo.reset(p: new MipsCallLowering(*getTargetLowering()));
211 Legalizer.reset(p: new MipsLegalizerInfo(*this));
212
213 auto *RBI = new MipsRegisterBankInfo(*getRegisterInfo());
214 RegBankInfo.reset(p: RBI);
215 InstSelector.reset(p: createMipsInstructionSelector(TM, *this, *RBI));
216}
217
218MipsSubtarget::~MipsSubtarget() = default;
219
220bool MipsSubtarget::isPositionIndependent() const {
221 return TM.isPositionIndependent();
222}
223
224/// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
225bool MipsSubtarget::enablePostRAScheduler() const { return true; }
226
227void MipsSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
228 CriticalPathRCs.clear();
229 CriticalPathRCs.push_back(Elt: isGP64bit() ? &Mips::GPR64RegClass
230 : &Mips::GPR32RegClass);
231}
232
233CodeGenOptLevel MipsSubtarget::getOptLevelToEnablePostRAScheduler() const {
234 return CodeGenOptLevel::Aggressive;
235}
236
237MipsSubtarget &
238MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,
239 const TargetMachine &TM) {
240 StringRef CPUName = MIPS_MC::selectMipsCPU(TT: TM.getTargetTriple(), CPU);
241
242 // Parse features string.
243 ParseSubtargetFeatures(CPU: CPUName, /*TuneCPU*/ CPUName, FS);
244
245 // O32 uses 32-bit GPRs even when the selected CPU supports a 64-bit ISA.
246 if (isABI_O32())
247 IsGP64bit = false;
248
249 if (InMips16Mode && !IsSoftFloat)
250 InMips16HardFloat = true;
251
252 if (StackAlignOverride)
253 stackAlignment = *StackAlignOverride;
254 else if (isABI_N32() || isABI_N64())
255 stackAlignment = Align(16);
256 else {
257 assert(isABI_O32() && "Unknown ABI for stack alignment!");
258 stackAlignment = Align(8);
259 }
260
261 if ((isABI_N32() || isABI_N64()) && !isGP64bit())
262 reportFatalUsageError(reason: "64-bit code requested on a subtarget that doesn't "
263 "support it!");
264
265 return *this;
266}
267
268bool MipsSubtarget::useConstantIslands() {
269 LLVM_DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands
270 << "\n");
271 return Mips16ConstantIslands;
272}
273
274Reloc::Model MipsSubtarget::getRelocationModel() const {
275 return TM.getRelocationModel();
276}
277
278bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); }
279bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); }
280bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); }
281
282const SelectionDAGTargetInfo *MipsSubtarget::getSelectionDAGInfo() const {
283 return TSInfo.get();
284}
285
286const CallLowering *MipsSubtarget::getCallLowering() const {
287 return CallLoweringInfo.get();
288}
289
290const LegalizerInfo *MipsSubtarget::getLegalizerInfo() const {
291 return Legalizer.get();
292}
293
294const RegisterBankInfo *MipsSubtarget::getRegBankInfo() const {
295 return RegBankInfo.get();
296}
297
298InstructionSelector *MipsSubtarget::getInstructionSelector() const {
299 return InstSelector.get();
300}
301
302// Libcalls for which no helper is generated. Sorted by name for binary search.
303const RTLIB::LibcallImpl MipsSubtarget::HardFloatLibCalls[34] = {
304 RTLIB::impl___mips16_adddf3, RTLIB::impl___mips16_addsf3,
305 RTLIB::impl___mips16_divdf3, RTLIB::impl___mips16_divsf3,
306 RTLIB::impl___mips16_eqdf2, RTLIB::impl___mips16_eqsf2,
307 RTLIB::impl___mips16_extendsfdf2, RTLIB::impl___mips16_fix_truncdfsi,
308 RTLIB::impl___mips16_fix_truncsfsi, RTLIB::impl___mips16_floatsidf,
309 RTLIB::impl___mips16_floatsisf, RTLIB::impl___mips16_floatunsidf,
310 RTLIB::impl___mips16_floatunsisf, RTLIB::impl___mips16_gedf2,
311 RTLIB::impl___mips16_gesf2, RTLIB::impl___mips16_gtdf2,
312 RTLIB::impl___mips16_gtsf2, RTLIB::impl___mips16_ledf2,
313 RTLIB::impl___mips16_lesf2, RTLIB::impl___mips16_ltdf2,
314 RTLIB::impl___mips16_ltsf2, RTLIB::impl___mips16_muldf3,
315 RTLIB::impl___mips16_mulsf3, RTLIB::impl___mips16_nedf2,
316 RTLIB::impl___mips16_nesf2, RTLIB::impl___mips16_ret_dc,
317 RTLIB::impl___mips16_ret_df, RTLIB::impl___mips16_ret_sc,
318 RTLIB::impl___mips16_ret_sf, RTLIB::impl___mips16_subdf3,
319 RTLIB::impl___mips16_subsf3, RTLIB::impl___mips16_truncdfsf2,
320 RTLIB::impl___mips16_unorddf2, RTLIB::impl___mips16_unordsf2};
321
322void MipsSubtarget::initLibcallLoweringInfo(LibcallLoweringInfo &Info) const {
323 if (inMips16Mode() && !useSoftFloat()) {
324 for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {
325 assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&
326 "Array not sorted!");
327 RTLIB::Libcall LC =
328 RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(Impl: HardFloatLibCalls[I]);
329 Info.setLibcallImpl(Call: LC, Impl: HardFloatLibCalls[I]);
330 }
331 }
332}
333