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