LLVM 17.0.0git
MipsSubtarget.cpp
Go to the documentation of this file.
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 "MipsMachineFunction.h"
19#include "MipsRegisterInfo.h"
20#include "MipsTargetMachine.h"
21#include "llvm/IR/Attributes.h"
22#include "llvm/IR/Function.h"
25#include "llvm/Support/Debug.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// FIXME: Maybe this should be on by default when Mips16 is specified
37//
38static cl::opt<bool>
39 Mixed16_32("mips-mixed-16-32", cl::init(false),
40 cl::desc("Allow for a mixture of Mips16 "
41 "and Mips32 code in a single output file"),
43
44static cl::opt<bool> Mips_Os16("mips-os16", cl::init(false),
45 cl::desc("Compile all functions that don't use "
46 "floating point as Mips 16"),
48
49static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden,
50 cl::desc("Enable mips16 hard float."),
51 cl::init(false));
52
53static cl::opt<bool>
54 Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden,
55 cl::desc("Enable mips16 constant islands."),
56 cl::init(true));
57
58static cl::opt<bool>
59 GPOpt("mgpopt", cl::Hidden,
60 cl::desc("Enable gp-relative addressing of mips small data items"));
61
62bool MipsSubtarget::DspWarningPrinted = false;
63bool MipsSubtarget::MSAWarningPrinted = false;
64bool MipsSubtarget::VirtWarningPrinted = false;
65bool MipsSubtarget::CRCWarningPrinted = false;
66bool MipsSubtarget::GINVWarningPrinted = false;
67bool MipsSubtarget::MIPS1WarningPrinted = false;
68
69void MipsSubtarget::anchor() {}
70
72 bool little, const MipsTargetMachine &TM,
73 MaybeAlign StackAlignOverride)
74 : MipsGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
75 MipsArchVersion(MipsDefault), IsLittle(little), IsSoftFloat(false),
76 IsSingleFloat(false), IsFPXX(false), NoABICalls(false), Abs2008(false),
77 IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false),
78 IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasCnMipsP(false),
79 HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false),
80 HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false),
81 InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false),
82 HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 || Mips_Os16),
83 Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false),
84 HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false),
85 HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false),
86 StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT),
87 TSInfo(), InstrInfo(MipsInstrInfo::create(
88 initializeSubtargetDependencies(CPU, FS, TM))),
89 FrameLowering(MipsFrameLowering::create(*this)),
90 TLInfo(MipsTargetLowering::create(TM, *this)) {
91
92 if (MipsArchVersion == MipsDefault)
93 MipsArchVersion = Mips32;
94
95 // MIPS-I has not been tested.
96 if (MipsArchVersion == Mips1 && !MIPS1WarningPrinted) {
97 errs() << "warning: MIPS-I support is experimental\n";
98 MIPS1WarningPrinted = true;
99 }
100
101 // Don't even attempt to generate code for MIPS-V. It has not
102 // been tested and currently exists for the integrated assembler only.
103 if (MipsArchVersion == Mips5)
104 report_fatal_error("Code generation for MIPS-V is not implemented", false);
105
106 // Check if Architecture and ABI are compatible.
107 assert(((!isGP64bit() && isABI_O32()) ||
108 (isGP64bit() && (isABI_N32() || isABI_N64()))) &&
109 "Invalid Arch & ABI pair.");
110
111 if (hasMSA() && !isFP64bit())
112 report_fatal_error("MSA requires a 64-bit FPU register file (FR=1 mode). "
113 "See -mattr=+fp64.",
114 false);
115
116 if (isFP64bit() && !hasMips64() && hasMips32() && !hasMips32r2())
118 "FPU with 64-bit registers is not available on MIPS32 pre revision 2. "
119 "Use -mcpu=mips32r2 or greater.", false);
120
121 if (!isABI_O32() && !useOddSPReg())
122 report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false);
123
124 if (IsFPXX && (isABI_N32() || isABI_N64()))
125 report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false);
126
127 if (hasMips64r6() && InMicroMipsMode)
128 report_fatal_error("microMIPS64R6 is not supported", false);
129
130 if (!isABI_O32() && InMicroMipsMode)
131 report_fatal_error("microMIPS64 is not supported.", false);
132
133 if (UseIndirectJumpsHazard) {
134 if (InMicroMipsMode)
136 "cannot combine indirect jumps with hazard barriers and microMIPS");
137 if (!hasMips32r2())
139 "indirect jumps with hazard barriers requires MIPS32R2 or later");
140 }
141 if (inAbs2008Mode() && hasMips32() && !hasMips32r2()) {
142 report_fatal_error("IEEE 754-2008 abs.fmt is not supported for the given "
143 "architecture.",
144 false);
145 }
146
147 if (hasMips32r6()) {
148 StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
149
150 assert(isFP64bit());
151 assert(isNaN2008());
153 if (hasDSP())
154 report_fatal_error(ISA + " is not compatible with the DSP ASE", false);
155 }
156
157 if (NoABICalls && TM.isPositionIndependent())
158 report_fatal_error("position-independent code requires '-mabicalls'");
159
160 if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32())
161 NoABICalls = true;
162
163 // Set UseSmallSection.
164 UseSmallSection = GPOpt;
165 if (!NoABICalls && GPOpt) {
166 errs() << "warning: cannot use small-data accesses for '-mabicalls'"
167 << "\n";
168 UseSmallSection = false;
169 }
170
171 if (hasDSPR2() && !DspWarningPrinted) {
172 if (hasMips64() && !hasMips64r2()) {
173 errs() << "warning: the 'dspr2' ASE requires MIPS64 revision 2 or "
174 << "greater\n";
175 DspWarningPrinted = true;
176 } else if (hasMips32() && !hasMips32r2()) {
177 errs() << "warning: the 'dspr2' ASE requires MIPS32 revision 2 or "
178 << "greater\n";
179 DspWarningPrinted = true;
180 }
181 } else if (hasDSP() && !DspWarningPrinted) {
182 if (hasMips64() && !hasMips64r2()) {
183 errs() << "warning: the 'dsp' ASE requires MIPS64 revision 2 or "
184 << "greater\n";
185 DspWarningPrinted = true;
186 } else if (hasMips32() && !hasMips32r2()) {
187 errs() << "warning: the 'dsp' ASE requires MIPS32 revision 2 or "
188 << "greater\n";
189 DspWarningPrinted = true;
190 }
191 }
192
193 StringRef ArchName = hasMips64() ? "MIPS64" : "MIPS32";
194
195 if (!hasMips32r5() && hasMSA() && !MSAWarningPrinted) {
196 errs() << "warning: the 'msa' ASE requires " << ArchName
197 << " revision 5 or greater\n";
198 MSAWarningPrinted = true;
199 }
200 if (!hasMips32r5() && hasVirt() && !VirtWarningPrinted) {
201 errs() << "warning: the 'virt' ASE requires " << ArchName
202 << " revision 5 or greater\n";
203 VirtWarningPrinted = true;
204 }
205 if (!hasMips32r6() && hasCRC() && !CRCWarningPrinted) {
206 errs() << "warning: the 'crc' ASE requires " << ArchName
207 << " revision 6 or greater\n";
208 CRCWarningPrinted = true;
209 }
210 if (!hasMips32r6() && hasGINV() && !GINVWarningPrinted) {
211 errs() << "warning: the 'ginv' ASE requires " << ArchName
212 << " revision 6 or greater\n";
213 GINVWarningPrinted = true;
214 }
215
217 Legalizer.reset(new MipsLegalizerInfo(*this));
218
219 auto *RBI = new MipsRegisterBankInfo(*getRegisterInfo());
220 RegBankInfo.reset(RBI);
222 *static_cast<const MipsTargetMachine *>(&TM), *this, *RBI));
223}
224
226 return TM.isPositionIndependent();
227}
228
229/// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
230bool MipsSubtarget::enablePostRAScheduler() const { return true; }
231
232void MipsSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
233 CriticalPathRCs.clear();
234 CriticalPathRCs.push_back(isGP64bit() ? &Mips::GPR64RegClass
235 : &Mips::GPR32RegClass);
236}
237
240}
241
244 const TargetMachine &TM) {
245 StringRef CPUName = MIPS_MC::selectMipsCPU(TM.getTargetTriple(), CPU);
246
247 // Parse features string.
248 ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);
249 // Initialize scheduling itinerary for the specified CPU.
250 InstrItins = getInstrItineraryForCPU(CPUName);
251
252 if (InMips16Mode && !IsSoftFloat)
253 InMips16HardFloat = true;
254
255 if (StackAlignOverride)
256 stackAlignment = *StackAlignOverride;
257 else if (isABI_N32() || isABI_N64())
258 stackAlignment = Align(16);
259 else {
260 assert(isABI_O32() && "Unknown ABI for stack alignment!");
261 stackAlignment = Align(8);
262 }
263
264 if ((isABI_N32() || isABI_N64()) && !isGP64bit())
265 report_fatal_error("64-bit code requested on a subtarget that doesn't "
266 "support it!");
267
268 return *this;
269}
270
272 LLVM_DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands
273 << "\n");
275}
276
278 return TM.getRelocationModel();
279}
280
281bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); }
282bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); }
283bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); }
284const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); }
285
287 return CallLoweringInfo.get();
288}
289
291 return Legalizer.get();
292}
293
295 return RegBankInfo.get();
296}
297
299 return InstSelector.get();
300}
This file contains the simple types necessary to represent the attributes associated with functions a...
basic Basic Alias true
#define LLVM_DEBUG(X)
Definition: Debug.h:101
This file describes how to lower LLVM calls to machine code calls.
This file declares the targeting of the Machinelegalizer class for Mips.
This file declares the targeting of the RegisterBankInfo class for Mips.
static cl::opt< bool > Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden, cl::desc("Enable mips16 constant islands."), cl::init(true))
static cl::opt< bool > Mixed16_32("mips-mixed-16-32", cl::init(false), cl::desc("Allow for a mixture of Mips16 " "and Mips32 code in a single output file"), cl::Hidden)
static cl::opt< bool > Mips16HardFloat("mips16-hard-float", cl::NotHidden, cl::desc("Enable mips16 hard float."), cl::init(false))
static cl::opt< bool > Mips_Os16("mips-os16", cl::init(false), cl::desc("Compile all functions that don't use " "floating point as Mips 16"), cl::Hidden)
static cl::opt< bool > GPOpt("mgpopt", cl::Hidden, cl::desc("Enable gp-relative addressing of mips small data items"))
const char LLVMTargetMachineRef TM
return InstrInfo
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Provides the logic to select generic machine instructions.
bool IsN64() const
Definition: MipsABIInfo.h:42
bool IsN32() const
Definition: MipsABIInfo.h:41
bool IsO32() const
Definition: MipsABIInfo.h:40
This class provides legalization strategies.
This class provides the information for the target register banks.
bool hasMips32r6() const
const LegalizerInfo * getLegalizerInfo() const override
static bool useConstantIslands()
bool hasMips64r2() const
bool isFP64bit() const
bool enablePostRAScheduler() const override
This overrides the PostRAScheduler bit in the SchedModel for each CPU.
bool hasMips32r5() const
std::unique_ptr< InstructionSelector > InstSelector
bool hasVirt() const
CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override
bool hasDSPR2() const
bool isABI_N64() const
bool hasMips64r6() const
bool isNaN2008() const
bool useOddSPReg() const
MipsSubtarget & initializeSubtargetDependencies(StringRef CPU, StringRef FS, const TargetMachine &TM)
const CallLowering * getCallLowering() const override
std::unique_ptr< RegisterBankInfo > RegBankInfo
bool hasMips64() const
bool hasMips32() const
bool hasSym32() const
bool inAbs2008Mode() const
std::unique_ptr< CallLowering > CallLoweringInfo
const MipsRegisterInfo * getRegisterInfo() const override
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS)
ParseSubtargetFeatures - Parses features string setting specified subtarget options.
const RegisterBankInfo * getRegBankInfo() const override
bool isPositionIndependent() const
bool isGP64bit() const
bool hasMips32r2() const
bool hasDSP() const
InstructionSelector * getInstructionSelector() const override
bool hasMSA() const
bool isABI_O32() const
bool hasGINV() const
bool isABI_N32() const
bool hasCRC() const
const MipsTargetLowering * getTargetLowering() const override
void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override
MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, bool little, const MipsTargetMachine &TM, MaybeAlign StackAlignOverride)
This constructor initializes the data members to match that of the specified triple.
Reloc::Model getRelocationModel() const
const MipsABIInfo & getABI() const
const MipsABIInfo & getABI() const
Holds all the information related to register banks.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
bool isPositionIndependent() const
Reloc::Model getRelocationModel() const
Returns the code generation relocation model.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
Level
Code generation optimization level.
Definition: CodeGen.h:57
@ Aggressive
-O3
Definition: CodeGen.h:61
StringRef selectMipsCPU(const Triple &TT, StringRef CPU)
Select the Mips CPU for the given triple and cpu name.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
InstructionSelector * createMipsInstructionSelector(const MipsTargetMachine &, MipsSubtarget &, MipsRegisterBankInfo &)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117