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"
14#include "MCTargetDesc/MipsABIInfo.h"
15#include "MCTargetDesc/MipsMCTargetDesc.h"
16#include "Mips.h"
17#include "Mips16ISelDAGToDAG.h"
18#include "MipsMachineFunction.h"
19#include "MipsSEISelDAGToDAG.h"
20#include "MipsSubtarget.h"
21#include "MipsTargetObjectFile.h"
22#include "MipsTargetTransformInfo.h"
23#include "TargetInfo/MipsTargetInfo.h"
24#include "llvm/ADT/StringRef.h"
25#include "llvm/Analysis/TargetTransformInfo.h"
26#include "llvm/CodeGen/BasicTTIImpl.h"
27#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
28#include "llvm/CodeGen/GlobalISel/IRTranslator.h"
29#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
30#include "llvm/CodeGen/GlobalISel/Legalizer.h"
31#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
32#include "llvm/CodeGen/MachineFunction.h"
33#include "llvm/CodeGen/Passes.h"
34#include "llvm/CodeGen/TargetPassConfig.h"
35#include "llvm/IR/Attributes.h"
36#include "llvm/IR/Function.h"
37#include "llvm/InitializePasses.h"
38#include "llvm/MC/TargetRegistry.h"
39#include "llvm/Support/CodeGen.h"
40#include "llvm/Support/Compiler.h"
41#include "llvm/Support/Debug.h"
42#include "llvm/Support/raw_ostream.h"
43#include "llvm/Target/TargetOptions.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(Val: false),
53 cl::desc("Enable the VR4300 mulmul bug fix."), cl::Hidden);
54
55extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() {
56 // Register the target.
57 RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget());
58 RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget());
59 RegisterTargetMachine<MipsebTargetMachine> A(getTheMips64Target());
60 RegisterTargetMachine<MipselTargetMachine> B(getTheMips64elTarget());
61
62 PassRegistry *PR = PassRegistry::getPassRegistry();
63 initializeGlobalISel(*PR);
64 initializeMipsAsmPrinterPass(*PR);
65 initializeMipsDelaySlotFillerPass(*PR);
66 initializeMipsBranchExpansionPass(*PR);
67 initializeMicroMipsSizeReducePass(*PR);
68 initializeMipsPreLegalizerCombinerPass(*PR);
69 initializeMipsPostLegalizerCombinerPass(*PR);
70 initializeMipsMulMulBugFixPass(*PR);
71 initializeMipsDAGToDAGISelLegacyPass(*PR);
72 initializeMipsSetMachineRegisterFlagsPass(*PR);
73}
74
75static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
76 if (TT.isOSBinFormatCOFF())
77 return std::make_unique<TargetLoweringObjectFileCOFF>();
78 return std::make_unique<MipsTargetObjectFile>();
79}
80
81static Reloc::Model getEffectiveRelocModel(bool JIT,
82 std::optional<Reloc::Model> RM) {
83 if (!RM || JIT)
84 return Reloc::Static;
85 return *RM;
86}
87
88// On function prologue, the stack is created by decrementing
89// its pointer. Once decremented, all references are done with positive
90// offset from the stack/frame pointer, using StackGrowsUp enables
91// an easier handling.
92// Using CodeModel::Large enables different CALL behavior.
93MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT,
94 StringRef CPU, StringRef FS,
95 const TargetOptions &Options,
96 std::optional<Reloc::Model> RM,
97 std::optional<CodeModel::Model> CM,
98 CodeGenOptLevel OL, bool JIT,
99 bool isLittle)
100 : CodeGenTargetMachineImpl(
101 T, TT.computeDataLayout(ABIName: Options.MCOptions.getABIName()), TT, CPU, FS,
102 Options, getEffectiveRelocModel(JIT, RM),
103 getEffectiveCodeModel(CM, Default: CodeModel::Small), OL),
104 isLittle(isLittle), TLOF(createTLOF(TT: getTargetTriple())),
105 ABI(MipsABIInfo::computeTargetABI(TT, ABIName: Options.MCOptions.getABIName())),
106 Subtarget(nullptr),
107 DefaultSubtarget(TT, CPU, FS, isLittle, *this, std::nullopt),
108 NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
109 isLittle, *this, std::nullopt),
110 Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16",
111 isLittle, *this, std::nullopt) {
112 Subtarget = &DefaultSubtarget;
113 initAsmInfo();
114
115 // Mips supports the debug entry values.
116 setSupportsDebugEntryValues(true);
117}
118
119MipsTargetMachine::~MipsTargetMachine() = default;
120
121void MipsebTargetMachine::anchor() {}
122
123MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT,
124 StringRef CPU, StringRef FS,
125 const TargetOptions &Options,
126 std::optional<Reloc::Model> RM,
127 std::optional<CodeModel::Model> CM,
128 CodeGenOptLevel OL, bool JIT)
129 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}
130
131void MipselTargetMachine::anchor() {}
132
133MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT,
134 StringRef CPU, StringRef FS,
135 const TargetOptions &Options,
136 std::optional<Reloc::Model> RM,
137 std::optional<CodeModel::Model> CM,
138 CodeGenOptLevel OL, bool JIT)
139 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {}
140
141const MipsSubtarget *
142MipsTargetMachine::getSubtargetImpl(const Function &F) const {
143 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
144 Attribute FSAttr = F.getFnAttribute(Kind: "target-features");
145
146 std::string CPU =
147 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
148 std::string FS =
149 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
150 bool hasMips16Attr = F.getFnAttribute(Kind: "mips16").isValid();
151 bool hasNoMips16Attr = F.getFnAttribute(Kind: "nomips16").isValid();
152
153 bool HasMicroMipsAttr = F.getFnAttribute(Kind: "micromips").isValid();
154 bool HasNoMicroMipsAttr = F.getFnAttribute(Kind: "nomicromips").isValid();
155
156 // FIXME: This is related to the code below to reset the target options,
157 // we need to know whether or not the soft float flag is set on the
158 // function, so we can enable it as a subtarget feature.
159 bool softFloat = F.getFnAttribute(Kind: "use-soft-float").getValueAsBool();
160
161 if (hasMips16Attr)
162 FS += FS.empty() ? "+mips16" : ",+mips16";
163 else if (hasNoMips16Attr)
164 FS += FS.empty() ? "-mips16" : ",-mips16";
165 if (HasMicroMipsAttr)
166 FS += FS.empty() ? "+micromips" : ",+micromips";
167 else if (HasNoMicroMipsAttr)
168 FS += FS.empty() ? "-micromips" : ",-micromips";
169 if (softFloat)
170 FS += FS.empty() ? "+soft-float" : ",+soft-float";
171
172 auto &I = SubtargetMap[CPU + FS];
173 if (!I) {
174 // This needs to be done before we create a new subtarget since any
175 // creation will depend on the TM and the code generation flags on the
176 // function that reside in TargetOptions.
177 resetTargetOptions(F);
178 I = std::make_unique<MipsSubtarget>(
179 args: TargetTriple, args&: CPU, args&: FS, args: isLittle, args: *this,
180 args: MaybeAlign(F.getParent()->getOverrideStackAlignment()));
181 }
182 return I.get();
183}
184
185void MipsTargetMachine::resetSubtarget(MachineFunction *MF) {
186 LLVM_DEBUG(dbgs() << "resetSubtarget\n");
187
188 Subtarget = &MF->getSubtarget<MipsSubtarget>();
189}
190
191namespace {
192
193/// Mips Code Generator Pass Configuration Options.
194class MipsPassConfig : public TargetPassConfig {
195public:
196 MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM)
197 : TargetPassConfig(TM, PM) {
198 // The current implementation of long branch pass requires a scratch
199 // register ($at) to be available before branch instructions. Tail merging
200 // can break this requirement, so disable it when long branch pass is
201 // enabled.
202 EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
203 EnableLoopTermFold = true;
204 }
205
206 MipsTargetMachine &getMipsTargetMachine() const {
207 return getTM<MipsTargetMachine>();
208 }
209
210 const MipsSubtarget &getMipsSubtarget() const {
211 return *getMipsTargetMachine().getSubtargetImpl();
212 }
213
214 void addIRPasses() override;
215 bool addInstSelector() override;
216 void addPreEmitPass() override;
217 void addPreRegAlloc() override;
218 bool addIRTranslator() override;
219 void addPreLegalizeMachineIR() override;
220 bool addLegalizeMachineIR() override;
221 void addPreRegBankSelect() override;
222 bool addRegBankSelect() override;
223 bool addGlobalInstructionSelect() override;
224
225 std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
226};
227
228} // end anonymous namespace
229
230TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
231 return new MipsPassConfig(*this, PM);
232}
233
234std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const {
235 return getStandardCSEConfigForOpt(Level: TM->getOptLevel());
236}
237
238void MipsPassConfig::addIRPasses() {
239 TargetPassConfig::addIRPasses();
240 addPass(P: createAtomicExpandLegacyPass());
241 if (getMipsSubtarget().os16())
242 addPass(P: createMipsOs16Pass());
243 if (getMipsSubtarget().inMips16HardFloat())
244 addPass(P: createMips16HardFloatPass());
245}
246// Install an instruction selector pass using
247// the ISelDag to gen Mips code.
248bool MipsPassConfig::addInstSelector() {
249 addPass(P: createMipsModuleISelDagPass());
250 addPass(P: createMips16ISelDag(TM&: getMipsTargetMachine(), OptLevel: getOptLevel()));
251 addPass(P: createMipsSEISelDag(TM&: getMipsTargetMachine(), OptLevel: getOptLevel()));
252 return false;
253}
254
255void MipsPassConfig::addPreRegAlloc() {
256 addPass(P: createMipsOptimizePICCallPass());
257 addPass(P: createMipsSetMachineRegisterFlagsPass());
258}
259
260TargetTransformInfo
261MipsTargetMachine::getTargetTransformInfo(const Function &F) const {
262 if (Subtarget->allowMixed16_32()) {
263 LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n");
264 // FIXME: This is no longer necessary as the TTI returned is per-function.
265 return TargetTransformInfo(F.getDataLayout());
266 }
267
268 LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n");
269 return TargetTransformInfo(std::make_unique<MipsTTIImpl>(args: this, args: F));
270}
271
272MachineFunctionInfo *MipsTargetMachine::createMachineFunctionInfo(
273 BumpPtrAllocator &Allocator, const Function &F,
274 const TargetSubtargetInfo *STI) const {
275 return MipsFunctionInfo::create<MipsFunctionInfo>(Allocator, F, STI);
276}
277
278// Implemented by targets that want to run passes immediately before
279// machine code is emitted.
280void MipsPassConfig::addPreEmitPass() {
281 // Expand pseudo instructions that are sensitive to register allocation.
282 addPass(P: createMipsExpandPseudoPass());
283
284 // The microMIPS size reduction pass performs instruction reselection for
285 // instructions which can be remapped to a 16 bit instruction.
286 addPass(P: createMicroMipsSizeReducePass());
287
288 // This pass inserts a nop instruction between two back-to-back multiplication
289 // instructions when the "mfix4300" flag is passed.
290 if (EnableMulMulFix)
291 addPass(P: createMipsMulMulBugPass());
292
293 // The delay slot filler pass can potientially create forbidden slot hazards
294 // for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
295 addPass(P: createMipsDelaySlotFillerPass());
296
297 // This pass expands branches and takes care about the forbidden slot hazards.
298 // Expanding branches may potentially create forbidden slot hazards for
299 // MIPSR6, and fixing such hazard may potentially break a branch by extending
300 // its offset out of range. That's why this pass combine these two tasks, and
301 // runs them alternately until one of them finishes without any changes. Only
302 // then we can be sure that all branches are expanded properly and no hazards
303 // exists.
304 // Any new pass should go before this pass.
305 addPass(P: createMipsBranchExpansion());
306
307 addPass(P: createMipsConstantIslandPass());
308}
309
310bool MipsPassConfig::addIRTranslator() {
311 addPass(P: new IRTranslator(getOptLevel()));
312 return false;
313}
314
315void MipsPassConfig::addPreLegalizeMachineIR() {
316 addPass(P: createMipsPreLegalizeCombiner());
317}
318
319bool MipsPassConfig::addLegalizeMachineIR() {
320 addPass(P: new Legalizer());
321 return false;
322}
323
324void MipsPassConfig::addPreRegBankSelect() {
325 bool IsOptNone = getOptLevel() == CodeGenOptLevel::None;
326 addPass(P: createMipsPostLegalizeCombiner(IsOptNone));
327}
328
329bool MipsPassConfig::addRegBankSelect() {
330 addPass(P: new RegBankSelect());
331 return false;
332}
333
334bool MipsPassConfig::addGlobalInstructionSelect() {
335 addPass(P: new InstructionSelect(getOptLevel()));
336 return false;
337}
338