LLVM 19.0.0git
MipsTargetMachine.cpp
Go to the documentation of this file.
1//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
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// Implements the info about Mips target spec.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MipsTargetMachine.h"
16#include "Mips.h"
17#include "Mips16ISelDAGToDAG.h"
18#include "MipsMachineFunction.h"
19#include "MipsSEISelDAGToDAG.h"
20#include "MipsSubtarget.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/StringRef.h"
34#include "llvm/CodeGen/Passes.h"
36#include "llvm/IR/Attributes.h"
37#include "llvm/IR/Function.h"
41#include "llvm/Support/Debug.h"
44#include <optional>
45#include <string>
46
47using namespace llvm;
48
49#define DEBUG_TYPE "mips"
50
51static cl::opt<bool>
52 EnableMulMulFix("mfix4300", cl::init(false),
53 cl::desc("Enable the VR4300 mulmul bug fix."), cl::Hidden);
54
56 // Register the target.
61
71}
72
73static std::string computeDataLayout(const Triple &TT, StringRef CPU,
75 bool isLittle) {
76 std::string Ret;
77 MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions);
78
79 // There are both little and big endian mips.
80 if (isLittle)
81 Ret += "e";
82 else
83 Ret += "E";
84
85 if (ABI.IsO32())
86 Ret += "-m:m";
87 else
88 Ret += "-m:e";
89
90 // Pointers are 32 bit on some ABIs.
91 if (!ABI.IsN64())
92 Ret += "-p:32:32";
93
94 // 8 and 16 bit integers only need to have natural alignment, but try to
95 // align them to 32 bits. 64 bit integers have natural alignment.
96 Ret += "-i8:8:32-i16:16:32-i64:64";
97
98 // 32 bit registers are always available and the stack is at least 64 bit
99 // aligned. On N64 64 bit registers are also available and the stack is
100 // 128 bit aligned.
101 if (ABI.IsN64() || ABI.IsN32())
102 Ret += "-n32:64-S128";
103 else
104 Ret += "-n32-S64";
105
106 return Ret;
107}
108
110 std::optional<Reloc::Model> RM) {
111 if (!RM || JIT)
112 return Reloc::Static;
113 return *RM;
114}
115
116// On function prologue, the stack is created by decrementing
117// its pointer. Once decremented, all references are done with positive
118// offset from the stack/frame pointer, using StackGrowsUp enables
119// an easier handling.
120// Using CodeModel::Large enables different CALL behavior.
122 StringRef CPU, StringRef FS,
123 const TargetOptions &Options,
124 std::optional<Reloc::Model> RM,
125 std::optional<CodeModel::Model> CM,
126 CodeGenOptLevel OL, bool JIT,
127 bool isLittle)
128 : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
129 CPU, FS, Options, getEffectiveRelocModel(JIT, RM),
130 getEffectiveCodeModel(CM, CodeModel::Small), OL),
131 isLittle(isLittle), TLOF(std::make_unique<MipsTargetObjectFile>()),
132 ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)),
133 Subtarget(nullptr),
134 DefaultSubtarget(TT, CPU, FS, isLittle, *this, std::nullopt),
135 NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
136 isLittle, *this, std::nullopt),
137 Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16",
138 isLittle, *this, std::nullopt) {
139 Subtarget = &DefaultSubtarget;
140 initAsmInfo();
141
142 // Mips supports the debug entry values.
144}
145
147
148void MipsebTargetMachine::anchor() {}
149
151 StringRef CPU, StringRef FS,
152 const TargetOptions &Options,
153 std::optional<Reloc::Model> RM,
154 std::optional<CodeModel::Model> CM,
155 CodeGenOptLevel OL, bool JIT)
156 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}
157
158void MipselTargetMachine::anchor() {}
159
161 StringRef CPU, StringRef FS,
162 const TargetOptions &Options,
163 std::optional<Reloc::Model> RM,
164 std::optional<CodeModel::Model> CM,
165 CodeGenOptLevel OL, bool JIT)
166 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {}
167
168const MipsSubtarget *
170 Attribute CPUAttr = F.getFnAttribute("target-cpu");
171 Attribute FSAttr = F.getFnAttribute("target-features");
172
173 std::string CPU =
174 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
175 std::string FS =
176 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
177 bool hasMips16Attr = F.getFnAttribute("mips16").isValid();
178 bool hasNoMips16Attr = F.getFnAttribute("nomips16").isValid();
179
180 bool HasMicroMipsAttr = F.getFnAttribute("micromips").isValid();
181 bool HasNoMicroMipsAttr = F.getFnAttribute("nomicromips").isValid();
182
183 // FIXME: This is related to the code below to reset the target options,
184 // we need to know whether or not the soft float flag is set on the
185 // function, so we can enable it as a subtarget feature.
186 bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
187
188 if (hasMips16Attr)
189 FS += FS.empty() ? "+mips16" : ",+mips16";
190 else if (hasNoMips16Attr)
191 FS += FS.empty() ? "-mips16" : ",-mips16";
192 if (HasMicroMipsAttr)
193 FS += FS.empty() ? "+micromips" : ",+micromips";
194 else if (HasNoMicroMipsAttr)
195 FS += FS.empty() ? "-micromips" : ",-micromips";
196 if (softFloat)
197 FS += FS.empty() ? "+soft-float" : ",+soft-float";
198
199 auto &I = SubtargetMap[CPU + FS];
200 if (!I) {
201 // This needs to be done before we create a new subtarget since any
202 // creation will depend on the TM and the code generation flags on the
203 // function that reside in TargetOptions.
205 I = std::make_unique<MipsSubtarget>(
206 TargetTriple, CPU, FS, isLittle, *this,
207 MaybeAlign(F.getParent()->getOverrideStackAlignment()));
208 }
209 return I.get();
210}
211
213 LLVM_DEBUG(dbgs() << "resetSubtarget\n");
214
215 Subtarget = &MF->getSubtarget<MipsSubtarget>();
216}
217
218namespace {
219
220/// Mips Code Generator Pass Configuration Options.
221class MipsPassConfig : public TargetPassConfig {
222public:
223 MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM)
224 : TargetPassConfig(TM, PM) {
225 // The current implementation of long branch pass requires a scratch
226 // register ($at) to be available before branch instructions. Tail merging
227 // can break this requirement, so disable it when long branch pass is
228 // enabled.
229 EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
230 }
231
232 MipsTargetMachine &getMipsTargetMachine() const {
233 return getTM<MipsTargetMachine>();
234 }
235
236 const MipsSubtarget &getMipsSubtarget() const {
237 return *getMipsTargetMachine().getSubtargetImpl();
238 }
239
240 void addIRPasses() override;
241 bool addInstSelector() override;
242 void addPreEmitPass() override;
243 void addPreRegAlloc() override;
244 bool addIRTranslator() override;
245 void addPreLegalizeMachineIR() override;
246 bool addLegalizeMachineIR() override;
247 void addPreRegBankSelect() override;
248 bool addRegBankSelect() override;
249 bool addGlobalInstructionSelect() override;
250
251 std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
252};
253
254} // end anonymous namespace
255
257 return new MipsPassConfig(*this, PM);
258}
259
260std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const {
261 return getStandardCSEConfigForOpt(TM->getOptLevel());
262}
263
264void MipsPassConfig::addIRPasses() {
267 if (getMipsSubtarget().os16())
268 addPass(createMipsOs16Pass());
269 if (getMipsSubtarget().inMips16HardFloat())
270 addPass(createMips16HardFloatPass());
271}
272// Install an instruction selector pass using
273// the ISelDag to gen Mips code.
274bool MipsPassConfig::addInstSelector() {
276 addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel()));
277 addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel()));
278 return false;
279}
280
281void MipsPassConfig::addPreRegAlloc() {
283}
284
287 if (Subtarget->allowMixed16_32()) {
288 LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n");
289 // FIXME: This is no longer necessary as the TTI returned is per-function.
290 return TargetTransformInfo(F.getParent()->getDataLayout());
291 }
292
293 LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n");
294 return TargetTransformInfo(MipsTTIImpl(this, F));
295}
296
298 BumpPtrAllocator &Allocator, const Function &F,
299 const TargetSubtargetInfo *STI) const {
300 return MipsFunctionInfo::create<MipsFunctionInfo>(Allocator, F, STI);
301}
302
303// Implemented by targets that want to run passes immediately before
304// machine code is emitted.
305void MipsPassConfig::addPreEmitPass() {
306 // Expand pseudo instructions that are sensitive to register allocation.
308
309 // The microMIPS size reduction pass performs instruction reselection for
310 // instructions which can be remapped to a 16 bit instruction.
312
313 // This pass inserts a nop instruction between two back-to-back multiplication
314 // instructions when the "mfix4300" flag is passed.
315 if (EnableMulMulFix)
316 addPass(createMipsMulMulBugPass());
317
318 // The delay slot filler pass can potientially create forbidden slot hazards
319 // for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
321
322 // This pass expands branches and takes care about the forbidden slot hazards.
323 // Expanding branches may potentially create forbidden slot hazards for
324 // MIPSR6, and fixing such hazard may potentially break a branch by extending
325 // its offset out of range. That's why this pass combine these two tasks, and
326 // runs them alternately until one of them finishes without any changes. Only
327 // then we can be sure that all branches are expanded properly and no hazards
328 // exists.
329 // Any new pass should go before this pass.
330 addPass(createMipsBranchExpansion());
331
333}
334
335bool MipsPassConfig::addIRTranslator() {
336 addPass(new IRTranslator(getOptLevel()));
337 return false;
338}
339
340void MipsPassConfig::addPreLegalizeMachineIR() {
342}
343
344bool MipsPassConfig::addLegalizeMachineIR() {
345 addPass(new Legalizer());
346 return false;
347}
348
349void MipsPassConfig::addPreRegBankSelect() {
350 bool IsOptNone = getOptLevel() == CodeGenOptLevel::None;
351 addPass(createMipsPostLegalizeCombiner(IsOptNone));
352}
353
354bool MipsPassConfig::addRegBankSelect() {
355 addPass(new RegBankSelect());
356 return false;
357}
358
359bool MipsPassConfig::addGlobalInstructionSelect() {
360 addPass(new InstructionSelect(getOptLevel()));
361 return false;
362}
static ARMBaseTargetMachine::ARMABI computeTargetABI(const Triple &TT, StringRef CPU, const TargetOptions &Options)
This file contains the simple types necessary to represent the attributes associated with functions a...
basic Basic Alias true
This file provides a helper that implements much of the TTI interface in terms of the target-independ...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Provides analysis for continuously CSEing during GISel passes.
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file declares the IRTranslator pass.
static LVOptions Options
Definition: LVOptions.cpp:25
static std::string computeDataLayout()
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
static Reloc::Model getEffectiveRelocModel(bool JIT, std::optional< Reloc::Model > RM)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget()
static cl::opt< bool > EnableMulMulFix("mfix4300", cl::init(false), cl::desc("Enable the VR4300 mulmul bug fix."), cl::Hidden)
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const char LLVMTargetMachineRef TM
Basic Register Allocator
This file describes the interface of the MachineFunctionPass responsible for assigning the generic vi...
This file contains some templates that are useful if you are working with the STL at all.
Target-Independent Code Generator Pass Configuration Options pass.
This pass exposes codegen information to IR-level passes.
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:349
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:193
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:66
This pass is responsible for selecting generic machine instructions to target-specific instructions.
This class describes a target machine that is implemented with the LLVM target-independent code gener...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static MipsABIInfo computeTargetABI(const Triple &TT, StringRef CPU, const MCTargetOptions &Options)
Definition: MipsABIInfo.cpp:57
bool allowMixed16_32() const
TargetTransformInfo getTargetTransformInfo(const Function &F) const override
Get a TargetTransformInfo implementation for the target.
MachineFunctionInfo * createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override
Create the target's instance of MachineFunctionInfo.
MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOptLevel OL, bool JIT, bool isLittle)
TargetPassConfig * createPassConfig(PassManagerBase &PM) override
Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...
~MipsTargetMachine() override
void resetSubtarget(MachineFunction *MF)
Reset the subtarget for the Mips target.
const MipsSubtarget * getSubtargetImpl() const
MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOptLevel OL, bool JIT)
MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOptLevel OL, bool JIT)
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This pass implements the reg bank selector pass used in the GlobalISel pipeline.
Definition: RegBankSelect.h:91
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
void setSupportsDebugEntryValues(bool Enable)
Triple TargetTriple
Triple string, CPU name, and target feature strings the TargetMachine instance is created with.
Definition: TargetMachine.h:95
std::string TargetFS
Definition: TargetMachine.h:97
std::string TargetCPU
Definition: TargetMachine.h:96
std::unique_ptr< const MCSubtargetInfo > STI
void resetTargetOptions(const Function &F) const
Reset the target options based on the function's attributes.
Target-Independent Code Generator Pass Configuration Options.
virtual void addIRPasses()
Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...
TargetSubtargetInfo - Generic base class for all target subtargets.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
PassManagerBase - An abstract interface to allow code to add passes to a pass manager without having ...
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheMips64Target()
FunctionPass * createMipsConstantIslandPass()
Returns a pass that converts branches to long branches.
void initializeMipsPreLegalizerCombinerPass(PassRegistry &)
void initializeMipsBranchExpansionPass(PassRegistry &)
void initializeMipsDelaySlotFillerPass(PassRegistry &)
void initializeMipsMulMulBugFixPass(PassRegistry &)
FunctionPass * createMipsOptimizePICCallPass()
Return an OptimizeCall object.
std::unique_ptr< CSEConfigBase > getStandardCSEConfigForOpt(CodeGenOptLevel Level)
Definition: CSEInfo.cpp:79
FunctionPass * createMipsModuleISelDagPass()
CodeModel::Model getEffectiveCodeModel(std::optional< CodeModel::Model > CM, CodeModel::Model Default)
Helper method for getting the code model, returning Default if CM does not have a value.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
FunctionPass * createMipsPreLegalizeCombiner()
void initializeMipsPostLegalizerCombinerPass(PassRegistry &)
FunctionPass * createMicroMipsSizeReducePass()
Returns an instance of the MicroMips size reduction pass.
FunctionPass * createMipsSEISelDag(MipsTargetMachine &TM, CodeGenOptLevel OptLevel)
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
FunctionPass * createMipsBranchExpansion()
Target & getTheMips64elTarget()
void initializeMipsDAGToDAGISelPass(PassRegistry &)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createMipsMulMulBugPass()
void initializeMicroMipsSizeReducePass(PassRegistry &)
void initializeGlobalISel(PassRegistry &)
Initialize all passes linked into the GlobalISel library.
Definition: GlobalISel.cpp:17
Target & getTheMipselTarget()
FunctionPass * createMips16ISelDag(MipsTargetMachine &TM, CodeGenOptLevel OptLevel)
ModulePass * createMips16HardFloatPass()
FunctionPass * createMipsExpandPseudoPass()
createMipsExpandPseudoPass - returns an instance of the pseudo instruction expansion pass.
FunctionPass * createMipsDelaySlotFillerPass()
createMipsDelaySlotFillerPass - Returns a pass that fills in delay slots in Mips MachineFunctions
FunctionPass * createAtomicExpandLegacyPass()
AtomicExpandPass - At IR level this pass replace atomic instructions with __atomic_* library calls,...
Target & getTheMipsTarget()
ModulePass * createMipsOs16Pass()
Definition: MipsOs16.cpp:160
FunctionPass * createMipsPostLegalizeCombiner(bool IsOptNone)
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
MachineFunctionInfo - This class can be derived from and used by targets to hold private target-speci...
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117
RegisterTargetMachine - Helper template for registering a target machine implementation,...