1009b1c42SEd Schouten //===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // Implements the info about Mips target spec.
10009b1c42SEd Schouten //
11009b1c42SEd Schouten //===----------------------------------------------------------------------===//
12009b1c42SEd Schouten
137ab83427SDimitry Andric #include "MipsTargetMachine.h"
1471d5a254SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h"
1571d5a254SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h"
1663faed5bSDimitry Andric #include "Mips.h"
175ca98fd9SDimitry Andric #include "Mips16ISelDAGToDAG.h"
18e3b55780SDimitry Andric #include "MipsMachineFunction.h"
1959d6cff9SDimitry Andric #include "MipsSEISelDAGToDAG.h"
2071d5a254SDimitry Andric #include "MipsSubtarget.h"
2167c32a98SDimitry Andric #include "MipsTargetObjectFile.h"
22145449b1SDimitry Andric #include "MipsTargetTransformInfo.h"
23e6d15924SDimitry Andric #include "TargetInfo/MipsTargetInfo.h"
2471d5a254SDimitry Andric #include "llvm/ADT/STLExtras.h"
2571d5a254SDimitry Andric #include "llvm/ADT/StringRef.h"
2659d6cff9SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
27706b4fc4SDimitry Andric #include "llvm/CodeGen/BasicTTIImpl.h"
28145449b1SDimitry Andric #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
29eb11fae6SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
30706b4fc4SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
31eb11fae6SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h"
32eb11fae6SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
3371d5a254SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
3463faed5bSDimitry Andric #include "llvm/CodeGen/Passes.h"
3501095a5dSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
3671d5a254SDimitry Andric #include "llvm/IR/Attributes.h"
3771d5a254SDimitry Andric #include "llvm/IR/Function.h"
38706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
39c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
4071d5a254SDimitry Andric #include "llvm/Support/CodeGen.h"
4159d6cff9SDimitry Andric #include "llvm/Support/Debug.h"
425ca98fd9SDimitry Andric #include "llvm/Support/raw_ostream.h"
4371d5a254SDimitry Andric #include "llvm/Target/TargetOptions.h"
44e3b55780SDimitry Andric #include <optional>
4571d5a254SDimitry Andric #include <string>
465a5ac124SDimitry Andric
47009b1c42SEd Schouten using namespace llvm;
48009b1c42SEd Schouten
495ca98fd9SDimitry Andric #define DEBUG_TYPE "mips"
5059d6cff9SDimitry Andric
516f8fc217SDimitry Andric static cl::opt<bool>
526f8fc217SDimitry Andric EnableMulMulFix("mfix4300", cl::init(false),
536f8fc217SDimitry Andric cl::desc("Enable the VR4300 mulmul bug fix."), cl::Hidden);
546f8fc217SDimitry Andric
LLVMInitializeMipsTarget()55706b4fc4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() {
56009b1c42SEd Schouten // Register the target.
57b915e9e0SDimitry Andric RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget());
58b915e9e0SDimitry Andric RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget());
59b915e9e0SDimitry Andric RegisterTargetMachine<MipsebTargetMachine> A(getTheMips64Target());
60b915e9e0SDimitry Andric RegisterTargetMachine<MipselTargetMachine> B(getTheMips64elTarget());
61eb11fae6SDimitry Andric
62eb11fae6SDimitry Andric PassRegistry *PR = PassRegistry::getPassRegistry();
63eb11fae6SDimitry Andric initializeGlobalISel(*PR);
64eb11fae6SDimitry Andric initializeMipsDelaySlotFillerPass(*PR);
65eb11fae6SDimitry Andric initializeMipsBranchExpansionPass(*PR);
66eb11fae6SDimitry Andric initializeMicroMipsSizeReducePass(*PR);
67d8e91e46SDimitry Andric initializeMipsPreLegalizerCombinerPass(*PR);
68145449b1SDimitry Andric initializeMipsPostLegalizerCombinerPass(*PR);
696f8fc217SDimitry Andric initializeMipsMulMulBugFixPass(*PR);
70ac9a064cSDimitry Andric initializeMipsDAGToDAGISelLegacyPass(*PR);
71009b1c42SEd Schouten }
72009b1c42SEd Schouten
computeDataLayout(const Triple & TT,StringRef CPU,const TargetOptions & Options,bool isLittle)733a0822f0SDimitry Andric static std::string computeDataLayout(const Triple &TT, StringRef CPU,
745a5ac124SDimitry Andric const TargetOptions &Options,
755a5ac124SDimitry Andric bool isLittle) {
7671d5a254SDimitry Andric std::string Ret;
773a0822f0SDimitry Andric MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions);
785a5ac124SDimitry Andric
795a5ac124SDimitry Andric // There are both little and big endian mips.
805a5ac124SDimitry Andric if (isLittle)
815a5ac124SDimitry Andric Ret += "e";
825a5ac124SDimitry Andric else
835a5ac124SDimitry Andric Ret += "E";
845a5ac124SDimitry Andric
85a7fe922bSDimitry Andric if (ABI.IsO32())
865a5ac124SDimitry Andric Ret += "-m:m";
87a7fe922bSDimitry Andric else
88a7fe922bSDimitry Andric Ret += "-m:e";
895a5ac124SDimitry Andric
905a5ac124SDimitry Andric // Pointers are 32 bit on some ABIs.
915a5ac124SDimitry Andric if (!ABI.IsN64())
925a5ac124SDimitry Andric Ret += "-p:32:32";
935a5ac124SDimitry Andric
94ee8648bdSDimitry Andric // 8 and 16 bit integers only need to have natural alignment, but try to
955a5ac124SDimitry Andric // align them to 32 bits. 64 bit integers have natural alignment.
965a5ac124SDimitry Andric Ret += "-i8:8:32-i16:16:32-i64:64";
975a5ac124SDimitry Andric
985a5ac124SDimitry Andric // 32 bit registers are always available and the stack is at least 64 bit
995a5ac124SDimitry Andric // aligned. On N64 64 bit registers are also available and the stack is
1005a5ac124SDimitry Andric // 128 bit aligned.
1015a5ac124SDimitry Andric if (ABI.IsN64() || ABI.IsN32())
1025a5ac124SDimitry Andric Ret += "-n32:64-S128";
1035a5ac124SDimitry Andric else
1045a5ac124SDimitry Andric Ret += "-n32-S64";
1055a5ac124SDimitry Andric
1065a5ac124SDimitry Andric return Ret;
1075a5ac124SDimitry Andric }
1085a5ac124SDimitry Andric
getEffectiveRelocModel(bool JIT,std::optional<Reloc::Model> RM)109044eb2f6SDimitry Andric static Reloc::Model getEffectiveRelocModel(bool JIT,
110e3b55780SDimitry Andric std::optional<Reloc::Model> RM) {
111145449b1SDimitry Andric if (!RM || JIT)
11201095a5dSDimitry Andric return Reloc::Static;
11301095a5dSDimitry Andric return *RM;
11401095a5dSDimitry Andric }
11501095a5dSDimitry Andric
116009b1c42SEd Schouten // On function prologue, the stack is created by decrementing
117009b1c42SEd Schouten // its pointer. Once decremented, all references are done with positive
118009b1c42SEd Schouten // offset from the stack/frame pointer, using StackGrowsUp enables
119009b1c42SEd Schouten // an easier handling.
120009b1c42SEd Schouten // Using CodeModel::Large enables different CALL behavior.
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)1213a0822f0SDimitry Andric MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT,
1225ca98fd9SDimitry Andric StringRef CPU, StringRef FS,
1235ca98fd9SDimitry Andric const TargetOptions &Options,
124e3b55780SDimitry Andric std::optional<Reloc::Model> RM,
125e3b55780SDimitry Andric std::optional<CodeModel::Model> CM,
126b1c73532SDimitry Andric CodeGenOptLevel OL, bool JIT,
12701095a5dSDimitry Andric bool isLittle)
1285a5ac124SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
129044eb2f6SDimitry Andric CPU, FS, Options, getEffectiveRelocModel(JIT, RM),
130d8e91e46SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), OL),
1311d5ae102SDimitry Andric isLittle(isLittle), TLOF(std::make_unique<MipsTargetObjectFile>()),
1323a0822f0SDimitry Andric ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)),
133e3b55780SDimitry Andric Subtarget(nullptr),
134e3b55780SDimitry Andric DefaultSubtarget(TT, CPU, FS, isLittle, *this, std::nullopt),
1355ca98fd9SDimitry Andric NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16",
136e3b55780SDimitry Andric isLittle, *this, std::nullopt),
1375ca98fd9SDimitry Andric Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16",
138e3b55780SDimitry Andric isLittle, *this, std::nullopt) {
1395ca98fd9SDimitry Andric Subtarget = &DefaultSubtarget;
140f8af5cf6SDimitry Andric initAsmInfo();
141cfca06d7SDimitry Andric
142cfca06d7SDimitry Andric // Mips supports the debug entry values.
143cfca06d7SDimitry Andric setSupportsDebugEntryValues(true);
144009b1c42SEd Schouten }
145009b1c42SEd Schouten
14671d5a254SDimitry Andric MipsTargetMachine::~MipsTargetMachine() = default;
14767c32a98SDimitry Andric
anchor()14863faed5bSDimitry Andric void MipsebTargetMachine::anchor() {}
14963faed5bSDimitry Andric
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)1503a0822f0SDimitry Andric MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT,
1513a0822f0SDimitry Andric StringRef CPU, StringRef FS,
1523a0822f0SDimitry Andric const TargetOptions &Options,
153e3b55780SDimitry Andric std::optional<Reloc::Model> RM,
154e3b55780SDimitry Andric std::optional<CodeModel::Model> CM,
155b1c73532SDimitry Andric CodeGenOptLevel OL, bool JIT)
156044eb2f6SDimitry Andric : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {}
15763faed5bSDimitry Andric
anchor()15863faed5bSDimitry Andric void MipselTargetMachine::anchor() {}
15930815c53SDimitry Andric
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)1603a0822f0SDimitry Andric MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT,
1613a0822f0SDimitry Andric StringRef CPU, StringRef FS,
1623a0822f0SDimitry Andric const TargetOptions &Options,
163e3b55780SDimitry Andric std::optional<Reloc::Model> RM,
164e3b55780SDimitry Andric std::optional<CodeModel::Model> CM,
165b1c73532SDimitry Andric CodeGenOptLevel OL, bool JIT)
166044eb2f6SDimitry Andric : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {}
16763faed5bSDimitry Andric
16867c32a98SDimitry Andric const MipsSubtarget *
getSubtargetImpl(const Function & F) const16967c32a98SDimitry Andric MipsTargetMachine::getSubtargetImpl(const Function &F) const {
1705a5ac124SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu");
1715a5ac124SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features");
17267c32a98SDimitry Andric
173b60736ecSDimitry Andric std::string CPU =
174b60736ecSDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
175b60736ecSDimitry Andric std::string FS =
176b60736ecSDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
177b60736ecSDimitry Andric bool hasMips16Attr = F.getFnAttribute("mips16").isValid();
178b60736ecSDimitry Andric bool hasNoMips16Attr = F.getFnAttribute("nomips16").isValid();
17967c32a98SDimitry Andric
180b60736ecSDimitry Andric bool HasMicroMipsAttr = F.getFnAttribute("micromips").isValid();
181b60736ecSDimitry Andric bool HasNoMicroMipsAttr = F.getFnAttribute("nomicromips").isValid();
182b5630dbaSDimitry Andric
18367c32a98SDimitry Andric // FIXME: This is related to the code below to reset the target options,
18467c32a98SDimitry Andric // we need to know whether or not the soft float flag is set on the
1855a5ac124SDimitry Andric // function, so we can enable it as a subtarget feature.
186344a3780SDimitry Andric bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
18767c32a98SDimitry Andric
18867c32a98SDimitry Andric if (hasMips16Attr)
18967c32a98SDimitry Andric FS += FS.empty() ? "+mips16" : ",+mips16";
19067c32a98SDimitry Andric else if (hasNoMips16Attr)
19167c32a98SDimitry Andric FS += FS.empty() ? "-mips16" : ",-mips16";
192b5630dbaSDimitry Andric if (HasMicroMipsAttr)
193b5630dbaSDimitry Andric FS += FS.empty() ? "+micromips" : ",+micromips";
194b5630dbaSDimitry Andric else if (HasNoMicroMipsAttr)
195b5630dbaSDimitry Andric FS += FS.empty() ? "-micromips" : ",-micromips";
1965a5ac124SDimitry Andric if (softFloat)
1975a5ac124SDimitry Andric FS += FS.empty() ? "+soft-float" : ",+soft-float";
19867c32a98SDimitry Andric
1995a5ac124SDimitry Andric auto &I = SubtargetMap[CPU + FS];
20067c32a98SDimitry Andric if (!I) {
20167c32a98SDimitry Andric // This needs to be done before we create a new subtarget since any
20267c32a98SDimitry Andric // creation will depend on the TM and the code generation flags on the
20367c32a98SDimitry Andric // function that reside in TargetOptions.
20467c32a98SDimitry Andric resetTargetOptions(F);
2051d5ae102SDimitry Andric I = std::make_unique<MipsSubtarget>(
2061d5ae102SDimitry Andric TargetTriple, CPU, FS, isLittle, *this,
207344a3780SDimitry Andric MaybeAlign(F.getParent()->getOverrideStackAlignment()));
20867c32a98SDimitry Andric }
20967c32a98SDimitry Andric return I.get();
21067c32a98SDimitry Andric }
21167c32a98SDimitry Andric
resetSubtarget(MachineFunction * MF)2125ca98fd9SDimitry Andric void MipsTargetMachine::resetSubtarget(MachineFunction *MF) {
213eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "resetSubtarget\n");
21467c32a98SDimitry Andric
215e6d15924SDimitry Andric Subtarget = &MF->getSubtarget<MipsSubtarget>();
2165ca98fd9SDimitry Andric }
2175ca98fd9SDimitry Andric
21863faed5bSDimitry Andric namespace {
21971d5a254SDimitry Andric
22063faed5bSDimitry Andric /// Mips Code Generator Pass Configuration Options.
22163faed5bSDimitry Andric class MipsPassConfig : public TargetPassConfig {
22263faed5bSDimitry Andric public:
MipsPassConfig(MipsTargetMachine & TM,PassManagerBase & PM)223f382538dSDimitry Andric MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM)
224f8af5cf6SDimitry Andric : TargetPassConfig(TM, PM) {
225f8af5cf6SDimitry Andric // The current implementation of long branch pass requires a scratch
226f8af5cf6SDimitry Andric // register ($at) to be available before branch instructions. Tail merging
227f8af5cf6SDimitry Andric // can break this requirement, so disable it when long branch pass is
228f8af5cf6SDimitry Andric // enabled.
229f8af5cf6SDimitry Andric EnableTailMerge = !getMipsSubtarget().enableLongBranchPass();
230f8af5cf6SDimitry Andric }
23163faed5bSDimitry Andric
getMipsTargetMachine() const23263faed5bSDimitry Andric MipsTargetMachine &getMipsTargetMachine() const {
23363faed5bSDimitry Andric return getTM<MipsTargetMachine>();
23463faed5bSDimitry Andric }
23563faed5bSDimitry Andric
getMipsSubtarget() const23663faed5bSDimitry Andric const MipsSubtarget &getMipsSubtarget() const {
23763faed5bSDimitry Andric return *getMipsTargetMachine().getSubtargetImpl();
23863faed5bSDimitry Andric }
23963faed5bSDimitry Andric
2405ca98fd9SDimitry Andric void addIRPasses() override;
2415ca98fd9SDimitry Andric bool addInstSelector() override;
24267c32a98SDimitry Andric void addPreEmitPass() override;
24367c32a98SDimitry Andric void addPreRegAlloc() override;
244eb11fae6SDimitry Andric bool addIRTranslator() override;
245d8e91e46SDimitry Andric void addPreLegalizeMachineIR() override;
246eb11fae6SDimitry Andric bool addLegalizeMachineIR() override;
247145449b1SDimitry Andric void addPreRegBankSelect() override;
248eb11fae6SDimitry Andric bool addRegBankSelect() override;
249eb11fae6SDimitry Andric bool addGlobalInstructionSelect() override;
250e6d15924SDimitry Andric
251e6d15924SDimitry Andric std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
25263faed5bSDimitry Andric };
25371d5a254SDimitry Andric
25471d5a254SDimitry Andric } // end anonymous namespace
25563faed5bSDimitry Andric
createPassConfig(PassManagerBase & PM)25663faed5bSDimitry Andric TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
257f382538dSDimitry Andric return new MipsPassConfig(*this, PM);
25863faed5bSDimitry Andric }
259009b1c42SEd Schouten
getCSEConfig() const260e6d15924SDimitry Andric std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const {
261e6d15924SDimitry Andric return getStandardCSEConfigForOpt(TM->getOptLevel());
262e6d15924SDimitry Andric }
263e6d15924SDimitry Andric
addIRPasses()26459d6cff9SDimitry Andric void MipsPassConfig::addIRPasses() {
26559d6cff9SDimitry Andric TargetPassConfig::addIRPasses();
266ac9a064cSDimitry Andric addPass(createAtomicExpandLegacyPass());
26759d6cff9SDimitry Andric if (getMipsSubtarget().os16())
268b5630dbaSDimitry Andric addPass(createMipsOs16Pass());
269f8af5cf6SDimitry Andric if (getMipsSubtarget().inMips16HardFloat())
270b5630dbaSDimitry Andric addPass(createMips16HardFloatPass());
27159d6cff9SDimitry Andric }
272009b1c42SEd Schouten // Install an instruction selector pass using
273009b1c42SEd Schouten // the ISelDag to gen Mips code.
addInstSelector()274b61ab53cSDimitry Andric bool MipsPassConfig::addInstSelector() {
275b5630dbaSDimitry Andric addPass(createMipsModuleISelDagPass());
27601095a5dSDimitry Andric addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel()));
27701095a5dSDimitry Andric addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel()));
2785ca98fd9SDimitry Andric return false;
27959d6cff9SDimitry Andric }
2805ca98fd9SDimitry Andric
addPreRegAlloc()28167c32a98SDimitry Andric void MipsPassConfig::addPreRegAlloc() {
282b5630dbaSDimitry Andric addPass(createMipsOptimizePICCallPass());
283009b1c42SEd Schouten }
284009b1c42SEd Schouten
285c7dac04cSDimitry Andric TargetTransformInfo
getTargetTransformInfo(const Function & F) const286145449b1SDimitry Andric MipsTargetMachine::getTargetTransformInfo(const Function &F) const {
2875ca98fd9SDimitry Andric if (Subtarget->allowMixed16_32()) {
288eb11fae6SDimitry Andric LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n");
2895a5ac124SDimitry Andric // FIXME: This is no longer necessary as the TTI returned is per-function.
290ac9a064cSDimitry Andric return TargetTransformInfo(F.getDataLayout());
2915a5ac124SDimitry Andric }
2925a5ac124SDimitry Andric
293eb11fae6SDimitry Andric LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n");
294145449b1SDimitry Andric return TargetTransformInfo(MipsTTIImpl(this, F));
29559d6cff9SDimitry Andric }
29659d6cff9SDimitry Andric
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const297e3b55780SDimitry Andric MachineFunctionInfo *MipsTargetMachine::createMachineFunctionInfo(
298e3b55780SDimitry Andric BumpPtrAllocator &Allocator, const Function &F,
299e3b55780SDimitry Andric const TargetSubtargetInfo *STI) const {
300e3b55780SDimitry Andric return MipsFunctionInfo::create<MipsFunctionInfo>(Allocator, F, STI);
301e3b55780SDimitry Andric }
302e3b55780SDimitry Andric
303009b1c42SEd Schouten // Implemented by targets that want to run passes immediately before
304b60736ecSDimitry Andric // machine code is emitted.
addPreEmitPass()30567c32a98SDimitry Andric void MipsPassConfig::addPreEmitPass() {
306eb11fae6SDimitry Andric // Expand pseudo instructions that are sensitive to register allocation.
307eb11fae6SDimitry Andric addPass(createMipsExpandPseudoPass());
30801095a5dSDimitry Andric
309eb11fae6SDimitry Andric // The microMIPS size reduction pass performs instruction reselection for
310eb11fae6SDimitry Andric // instructions which can be remapped to a 16 bit instruction.
311eb11fae6SDimitry Andric addPass(createMicroMipsSizeReducePass());
312eb11fae6SDimitry Andric
3136f8fc217SDimitry Andric // This pass inserts a nop instruction between two back-to-back multiplication
3146f8fc217SDimitry Andric // instructions when the "mfix4300" flag is passed.
3156f8fc217SDimitry Andric if (EnableMulMulFix)
3166f8fc217SDimitry Andric addPass(createMipsMulMulBugPass());
3176f8fc217SDimitry Andric
318eb11fae6SDimitry Andric // The delay slot filler pass can potientially create forbidden slot hazards
319eb11fae6SDimitry Andric // for MIPSR6 and therefore it should go before MipsBranchExpansion pass.
320b5630dbaSDimitry Andric addPass(createMipsDelaySlotFillerPass());
321eb11fae6SDimitry Andric
322eb11fae6SDimitry Andric // This pass expands branches and takes care about the forbidden slot hazards.
323eb11fae6SDimitry Andric // Expanding branches may potentially create forbidden slot hazards for
324eb11fae6SDimitry Andric // MIPSR6, and fixing such hazard may potentially break a branch by extending
325eb11fae6SDimitry Andric // its offset out of range. That's why this pass combine these two tasks, and
326eb11fae6SDimitry Andric // runs them alternately until one of them finishes without any changes. Only
327eb11fae6SDimitry Andric // then we can be sure that all branches are expanded properly and no hazards
328eb11fae6SDimitry Andric // exists.
329eb11fae6SDimitry Andric // Any new pass should go before this pass.
330eb11fae6SDimitry Andric addPass(createMipsBranchExpansion());
331eb11fae6SDimitry Andric
33201095a5dSDimitry Andric addPass(createMipsConstantIslandPass());
33330815c53SDimitry Andric }
334eb11fae6SDimitry Andric
addIRTranslator()335eb11fae6SDimitry Andric bool MipsPassConfig::addIRTranslator() {
336b60736ecSDimitry Andric addPass(new IRTranslator(getOptLevel()));
337eb11fae6SDimitry Andric return false;
338eb11fae6SDimitry Andric }
339eb11fae6SDimitry Andric
addPreLegalizeMachineIR()340d8e91e46SDimitry Andric void MipsPassConfig::addPreLegalizeMachineIR() {
341d8e91e46SDimitry Andric addPass(createMipsPreLegalizeCombiner());
342d8e91e46SDimitry Andric }
343d8e91e46SDimitry Andric
addLegalizeMachineIR()344eb11fae6SDimitry Andric bool MipsPassConfig::addLegalizeMachineIR() {
345eb11fae6SDimitry Andric addPass(new Legalizer());
346eb11fae6SDimitry Andric return false;
347eb11fae6SDimitry Andric }
348eb11fae6SDimitry Andric
addPreRegBankSelect()349145449b1SDimitry Andric void MipsPassConfig::addPreRegBankSelect() {
350b1c73532SDimitry Andric bool IsOptNone = getOptLevel() == CodeGenOptLevel::None;
351145449b1SDimitry Andric addPass(createMipsPostLegalizeCombiner(IsOptNone));
352145449b1SDimitry Andric }
353145449b1SDimitry Andric
addRegBankSelect()354eb11fae6SDimitry Andric bool MipsPassConfig::addRegBankSelect() {
355eb11fae6SDimitry Andric addPass(new RegBankSelect());
356eb11fae6SDimitry Andric return false;
357eb11fae6SDimitry Andric }
358eb11fae6SDimitry Andric
addGlobalInstructionSelect()359eb11fae6SDimitry Andric bool MipsPassConfig::addGlobalInstructionSelect() {
360344a3780SDimitry Andric addPass(new InstructionSelect(getOptLevel()));
361eb11fae6SDimitry Andric return false;
362eb11fae6SDimitry Andric }
363