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