10b57cec5SDimitry Andric //===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Implements the info about Mips target spec. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "MipsTargetMachine.h" 140b57cec5SDimitry Andric #include "MCTargetDesc/MipsABIInfo.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h" 160b57cec5SDimitry Andric #include "Mips.h" 170b57cec5SDimitry Andric #include "Mips16ISelDAGToDAG.h" 180b57cec5SDimitry Andric #include "MipsSEISelDAGToDAG.h" 190b57cec5SDimitry Andric #include "MipsSubtarget.h" 200b57cec5SDimitry Andric #include "MipsTargetObjectFile.h" 210b57cec5SDimitry Andric #include "TargetInfo/MipsTargetInfo.h" 220b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 230b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 240b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 26480093f4SDimitry Andric #include "llvm/CodeGen/BasicTTIImpl.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 28480093f4SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h" 300b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 320b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 330b57cec5SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 340b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 350b57cec5SDimitry Andric #include "llvm/IR/Function.h" 36480093f4SDimitry Andric #include "llvm/InitializePasses.h" 370b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 380b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 390b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h" 400b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 410b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 420b57cec5SDimitry Andric #include <string> 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric using namespace llvm; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric #define DEBUG_TYPE "mips" 470b57cec5SDimitry Andric 48480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeMipsTarget() { 490b57cec5SDimitry Andric // Register the target. 500b57cec5SDimitry Andric RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget()); 510b57cec5SDimitry Andric RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget()); 520b57cec5SDimitry Andric RegisterTargetMachine<MipsebTargetMachine> A(getTheMips64Target()); 530b57cec5SDimitry Andric RegisterTargetMachine<MipselTargetMachine> B(getTheMips64elTarget()); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric PassRegistry *PR = PassRegistry::getPassRegistry(); 560b57cec5SDimitry Andric initializeGlobalISel(*PR); 570b57cec5SDimitry Andric initializeMipsDelaySlotFillerPass(*PR); 580b57cec5SDimitry Andric initializeMipsBranchExpansionPass(*PR); 590b57cec5SDimitry Andric initializeMicroMipsSizeReducePass(*PR); 600b57cec5SDimitry Andric initializeMipsPreLegalizerCombinerPass(*PR); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric static std::string computeDataLayout(const Triple &TT, StringRef CPU, 640b57cec5SDimitry Andric const TargetOptions &Options, 650b57cec5SDimitry Andric bool isLittle) { 660b57cec5SDimitry Andric std::string Ret; 670b57cec5SDimitry Andric MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // There are both little and big endian mips. 700b57cec5SDimitry Andric if (isLittle) 710b57cec5SDimitry Andric Ret += "e"; 720b57cec5SDimitry Andric else 730b57cec5SDimitry Andric Ret += "E"; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric if (ABI.IsO32()) 760b57cec5SDimitry Andric Ret += "-m:m"; 770b57cec5SDimitry Andric else 780b57cec5SDimitry Andric Ret += "-m:e"; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // Pointers are 32 bit on some ABIs. 810b57cec5SDimitry Andric if (!ABI.IsN64()) 820b57cec5SDimitry Andric Ret += "-p:32:32"; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric // 8 and 16 bit integers only need to have natural alignment, but try to 850b57cec5SDimitry Andric // align them to 32 bits. 64 bit integers have natural alignment. 860b57cec5SDimitry Andric Ret += "-i8:8:32-i16:16:32-i64:64"; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric // 32 bit registers are always available and the stack is at least 64 bit 890b57cec5SDimitry Andric // aligned. On N64 64 bit registers are also available and the stack is 900b57cec5SDimitry Andric // 128 bit aligned. 910b57cec5SDimitry Andric if (ABI.IsN64() || ABI.IsN32()) 920b57cec5SDimitry Andric Ret += "-n32:64-S128"; 930b57cec5SDimitry Andric else 940b57cec5SDimitry Andric Ret += "-n32-S64"; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric return Ret; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric static Reloc::Model getEffectiveRelocModel(bool JIT, 1000b57cec5SDimitry Andric Optional<Reloc::Model> RM) { 1010b57cec5SDimitry Andric if (!RM.hasValue() || JIT) 1020b57cec5SDimitry Andric return Reloc::Static; 1030b57cec5SDimitry Andric return *RM; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric // On function prologue, the stack is created by decrementing 1070b57cec5SDimitry Andric // its pointer. Once decremented, all references are done with positive 1080b57cec5SDimitry Andric // offset from the stack/frame pointer, using StackGrowsUp enables 1090b57cec5SDimitry Andric // an easier handling. 1100b57cec5SDimitry Andric // Using CodeModel::Large enables different CALL behavior. 1110b57cec5SDimitry Andric MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, 1120b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1130b57cec5SDimitry Andric const TargetOptions &Options, 1140b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1150b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1160b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT, 1170b57cec5SDimitry Andric bool isLittle) 1180b57cec5SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, 1190b57cec5SDimitry Andric CPU, FS, Options, getEffectiveRelocModel(JIT, RM), 1200b57cec5SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), OL), 1218bcb0991SDimitry Andric isLittle(isLittle), TLOF(std::make_unique<MipsTargetObjectFile>()), 1220b57cec5SDimitry Andric ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)), 1238bcb0991SDimitry Andric Subtarget(nullptr), 1248bcb0991SDimitry Andric DefaultSubtarget(TT, CPU, FS, isLittle, *this, 1258bcb0991SDimitry Andric MaybeAlign(Options.StackAlignmentOverride)), 1260b57cec5SDimitry Andric NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", 1278bcb0991SDimitry Andric isLittle, *this, 1288bcb0991SDimitry Andric MaybeAlign(Options.StackAlignmentOverride)), 1290b57cec5SDimitry Andric Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", 1308bcb0991SDimitry Andric isLittle, *this, 1318bcb0991SDimitry Andric MaybeAlign(Options.StackAlignmentOverride)) { 1320b57cec5SDimitry Andric Subtarget = &DefaultSubtarget; 1330b57cec5SDimitry Andric initAsmInfo(); 1345ffd83dbSDimitry Andric 1355ffd83dbSDimitry Andric // Mips supports the debug entry values. 1365ffd83dbSDimitry Andric setSupportsDebugEntryValues(true); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric MipsTargetMachine::~MipsTargetMachine() = default; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric void MipsebTargetMachine::anchor() {} 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, 1440b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1450b57cec5SDimitry Andric const TargetOptions &Options, 1460b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1470b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1480b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 1490b57cec5SDimitry Andric : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric void MipselTargetMachine::anchor() {} 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, 1540b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1550b57cec5SDimitry Andric const TargetOptions &Options, 1560b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1570b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1580b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 1590b57cec5SDimitry Andric : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric const MipsSubtarget * 1620b57cec5SDimitry Andric MipsTargetMachine::getSubtargetImpl(const Function &F) const { 1630b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 1640b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 1650b57cec5SDimitry Andric 166*e8d8bef9SDimitry Andric std::string CPU = 167*e8d8bef9SDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 168*e8d8bef9SDimitry Andric std::string FS = 169*e8d8bef9SDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 170*e8d8bef9SDimitry Andric bool hasMips16Attr = F.getFnAttribute("mips16").isValid(); 171*e8d8bef9SDimitry Andric bool hasNoMips16Attr = F.getFnAttribute("nomips16").isValid(); 1720b57cec5SDimitry Andric 173*e8d8bef9SDimitry Andric bool HasMicroMipsAttr = F.getFnAttribute("micromips").isValid(); 174*e8d8bef9SDimitry Andric bool HasNoMicroMipsAttr = F.getFnAttribute("nomicromips").isValid(); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 1770b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 1780b57cec5SDimitry Andric // function, so we can enable it as a subtarget feature. 1790b57cec5SDimitry Andric bool softFloat = 1800b57cec5SDimitry Andric F.hasFnAttribute("use-soft-float") && 1810b57cec5SDimitry Andric F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric if (hasMips16Attr) 1840b57cec5SDimitry Andric FS += FS.empty() ? "+mips16" : ",+mips16"; 1850b57cec5SDimitry Andric else if (hasNoMips16Attr) 1860b57cec5SDimitry Andric FS += FS.empty() ? "-mips16" : ",-mips16"; 1870b57cec5SDimitry Andric if (HasMicroMipsAttr) 1880b57cec5SDimitry Andric FS += FS.empty() ? "+micromips" : ",+micromips"; 1890b57cec5SDimitry Andric else if (HasNoMicroMipsAttr) 1900b57cec5SDimitry Andric FS += FS.empty() ? "-micromips" : ",-micromips"; 1910b57cec5SDimitry Andric if (softFloat) 1920b57cec5SDimitry Andric FS += FS.empty() ? "+soft-float" : ",+soft-float"; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 1950b57cec5SDimitry Andric if (!I) { 1960b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 1970b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 1980b57cec5SDimitry Andric // function that reside in TargetOptions. 1990b57cec5SDimitry Andric resetTargetOptions(F); 2008bcb0991SDimitry Andric I = std::make_unique<MipsSubtarget>( 2018bcb0991SDimitry Andric TargetTriple, CPU, FS, isLittle, *this, 2028bcb0991SDimitry Andric MaybeAlign(Options.StackAlignmentOverride)); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric return I.get(); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { 2080b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "resetSubtarget\n"); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric Subtarget = &MF->getSubtarget<MipsSubtarget>(); 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric namespace { 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric /// Mips Code Generator Pass Configuration Options. 2160b57cec5SDimitry Andric class MipsPassConfig : public TargetPassConfig { 2170b57cec5SDimitry Andric public: 2180b57cec5SDimitry Andric MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM) 2190b57cec5SDimitry Andric : TargetPassConfig(TM, PM) { 2200b57cec5SDimitry Andric // The current implementation of long branch pass requires a scratch 2210b57cec5SDimitry Andric // register ($at) to be available before branch instructions. Tail merging 2220b57cec5SDimitry Andric // can break this requirement, so disable it when long branch pass is 2230b57cec5SDimitry Andric // enabled. 2240b57cec5SDimitry Andric EnableTailMerge = !getMipsSubtarget().enableLongBranchPass(); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric MipsTargetMachine &getMipsTargetMachine() const { 2280b57cec5SDimitry Andric return getTM<MipsTargetMachine>(); 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric const MipsSubtarget &getMipsSubtarget() const { 2320b57cec5SDimitry Andric return *getMipsTargetMachine().getSubtargetImpl(); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric void addIRPasses() override; 2360b57cec5SDimitry Andric bool addInstSelector() override; 2370b57cec5SDimitry Andric void addPreEmitPass() override; 2380b57cec5SDimitry Andric void addPreRegAlloc() override; 2390b57cec5SDimitry Andric bool addIRTranslator() override; 2400b57cec5SDimitry Andric void addPreLegalizeMachineIR() override; 2410b57cec5SDimitry Andric bool addLegalizeMachineIR() override; 2420b57cec5SDimitry Andric bool addRegBankSelect() override; 2430b57cec5SDimitry Andric bool addGlobalInstructionSelect() override; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase> getCSEConfig() const override; 2460b57cec5SDimitry Andric }; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric } // end anonymous namespace 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { 2510b57cec5SDimitry Andric return new MipsPassConfig(*this, PM); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const { 2550b57cec5SDimitry Andric return getStandardCSEConfigForOpt(TM->getOptLevel()); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric void MipsPassConfig::addIRPasses() { 2590b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 2600b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 2610b57cec5SDimitry Andric if (getMipsSubtarget().os16()) 2620b57cec5SDimitry Andric addPass(createMipsOs16Pass()); 2630b57cec5SDimitry Andric if (getMipsSubtarget().inMips16HardFloat()) 2640b57cec5SDimitry Andric addPass(createMips16HardFloatPass()); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric // Install an instruction selector pass using 2670b57cec5SDimitry Andric // the ISelDag to gen Mips code. 2680b57cec5SDimitry Andric bool MipsPassConfig::addInstSelector() { 2690b57cec5SDimitry Andric addPass(createMipsModuleISelDagPass()); 2700b57cec5SDimitry Andric addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel())); 2710b57cec5SDimitry Andric addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel())); 2720b57cec5SDimitry Andric return false; 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric void MipsPassConfig::addPreRegAlloc() { 2760b57cec5SDimitry Andric addPass(createMipsOptimizePICCallPass()); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric TargetTransformInfo 2800b57cec5SDimitry Andric MipsTargetMachine::getTargetTransformInfo(const Function &F) { 2810b57cec5SDimitry Andric if (Subtarget->allowMixed16_32()) { 2820b57cec5SDimitry Andric LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n"); 2830b57cec5SDimitry Andric // FIXME: This is no longer necessary as the TTI returned is per-function. 2840b57cec5SDimitry Andric return TargetTransformInfo(F.getParent()->getDataLayout()); 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n"); 2880b57cec5SDimitry Andric return TargetTransformInfo(BasicTTIImpl(this, F)); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // Implemented by targets that want to run passes immediately before 292*e8d8bef9SDimitry Andric // machine code is emitted. 2930b57cec5SDimitry Andric void MipsPassConfig::addPreEmitPass() { 2940b57cec5SDimitry Andric // Expand pseudo instructions that are sensitive to register allocation. 2950b57cec5SDimitry Andric addPass(createMipsExpandPseudoPass()); 2960b57cec5SDimitry Andric 2970b57cec5SDimitry Andric // The microMIPS size reduction pass performs instruction reselection for 2980b57cec5SDimitry Andric // instructions which can be remapped to a 16 bit instruction. 2990b57cec5SDimitry Andric addPass(createMicroMipsSizeReducePass()); 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // The delay slot filler pass can potientially create forbidden slot hazards 3020b57cec5SDimitry Andric // for MIPSR6 and therefore it should go before MipsBranchExpansion pass. 3030b57cec5SDimitry Andric addPass(createMipsDelaySlotFillerPass()); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // This pass expands branches and takes care about the forbidden slot hazards. 3060b57cec5SDimitry Andric // Expanding branches may potentially create forbidden slot hazards for 3070b57cec5SDimitry Andric // MIPSR6, and fixing such hazard may potentially break a branch by extending 3080b57cec5SDimitry Andric // its offset out of range. That's why this pass combine these two tasks, and 3090b57cec5SDimitry Andric // runs them alternately until one of them finishes without any changes. Only 3100b57cec5SDimitry Andric // then we can be sure that all branches are expanded properly and no hazards 3110b57cec5SDimitry Andric // exists. 3120b57cec5SDimitry Andric // Any new pass should go before this pass. 3130b57cec5SDimitry Andric addPass(createMipsBranchExpansion()); 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric addPass(createMipsConstantIslandPass()); 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric bool MipsPassConfig::addIRTranslator() { 319*e8d8bef9SDimitry Andric addPass(new IRTranslator(getOptLevel())); 3200b57cec5SDimitry Andric return false; 3210b57cec5SDimitry Andric } 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric void MipsPassConfig::addPreLegalizeMachineIR() { 3240b57cec5SDimitry Andric addPass(createMipsPreLegalizeCombiner()); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric bool MipsPassConfig::addLegalizeMachineIR() { 3280b57cec5SDimitry Andric addPass(new Legalizer()); 3290b57cec5SDimitry Andric return false; 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric bool MipsPassConfig::addRegBankSelect() { 3330b57cec5SDimitry Andric addPass(new RegBankSelect()); 3340b57cec5SDimitry Andric return false; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric bool MipsPassConfig::addGlobalInstructionSelect() { 3380b57cec5SDimitry Andric addPass(new InstructionSelect()); 3390b57cec5SDimitry Andric return false; 3400b57cec5SDimitry Andric } 341