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" 37*349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 380b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 390b57cec5SDimitry Andric #include "llvm/Support/Debug.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)), 123fe6060f1SDimitry Andric Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this, None), 1240b57cec5SDimitry Andric NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", 125fe6060f1SDimitry Andric isLittle, *this, None), 1260b57cec5SDimitry Andric Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", 127fe6060f1SDimitry Andric isLittle, *this, None) { 1280b57cec5SDimitry Andric Subtarget = &DefaultSubtarget; 1290b57cec5SDimitry Andric initAsmInfo(); 1305ffd83dbSDimitry Andric 1315ffd83dbSDimitry Andric // Mips supports the debug entry values. 1325ffd83dbSDimitry Andric setSupportsDebugEntryValues(true); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric MipsTargetMachine::~MipsTargetMachine() = default; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric void MipsebTargetMachine::anchor() {} 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, 1400b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1410b57cec5SDimitry Andric const TargetOptions &Options, 1420b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1430b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1440b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 1450b57cec5SDimitry Andric : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, false) {} 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void MipselTargetMachine::anchor() {} 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, 1500b57cec5SDimitry Andric StringRef CPU, StringRef FS, 1510b57cec5SDimitry Andric const TargetOptions &Options, 1520b57cec5SDimitry Andric Optional<Reloc::Model> RM, 1530b57cec5SDimitry Andric Optional<CodeModel::Model> CM, 1540b57cec5SDimitry Andric CodeGenOpt::Level OL, bool JIT) 1550b57cec5SDimitry Andric : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, JIT, true) {} 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric const MipsSubtarget * 1580b57cec5SDimitry Andric MipsTargetMachine::getSubtargetImpl(const Function &F) const { 1590b57cec5SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu"); 1600b57cec5SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features"); 1610b57cec5SDimitry Andric 162e8d8bef9SDimitry Andric std::string CPU = 163e8d8bef9SDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU; 164e8d8bef9SDimitry Andric std::string FS = 165e8d8bef9SDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS; 166e8d8bef9SDimitry Andric bool hasMips16Attr = F.getFnAttribute("mips16").isValid(); 167e8d8bef9SDimitry Andric bool hasNoMips16Attr = F.getFnAttribute("nomips16").isValid(); 1680b57cec5SDimitry Andric 169e8d8bef9SDimitry Andric bool HasMicroMipsAttr = F.getFnAttribute("micromips").isValid(); 170e8d8bef9SDimitry Andric bool HasNoMicroMipsAttr = F.getFnAttribute("nomicromips").isValid(); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // FIXME: This is related to the code below to reset the target options, 1730b57cec5SDimitry Andric // we need to know whether or not the soft float flag is set on the 1740b57cec5SDimitry Andric // function, so we can enable it as a subtarget feature. 175fe6060f1SDimitry Andric bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool(); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (hasMips16Attr) 1780b57cec5SDimitry Andric FS += FS.empty() ? "+mips16" : ",+mips16"; 1790b57cec5SDimitry Andric else if (hasNoMips16Attr) 1800b57cec5SDimitry Andric FS += FS.empty() ? "-mips16" : ",-mips16"; 1810b57cec5SDimitry Andric if (HasMicroMipsAttr) 1820b57cec5SDimitry Andric FS += FS.empty() ? "+micromips" : ",+micromips"; 1830b57cec5SDimitry Andric else if (HasNoMicroMipsAttr) 1840b57cec5SDimitry Andric FS += FS.empty() ? "-micromips" : ",-micromips"; 1850b57cec5SDimitry Andric if (softFloat) 1860b57cec5SDimitry Andric FS += FS.empty() ? "+soft-float" : ",+soft-float"; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric auto &I = SubtargetMap[CPU + FS]; 1890b57cec5SDimitry Andric if (!I) { 1900b57cec5SDimitry Andric // This needs to be done before we create a new subtarget since any 1910b57cec5SDimitry Andric // creation will depend on the TM and the code generation flags on the 1920b57cec5SDimitry Andric // function that reside in TargetOptions. 1930b57cec5SDimitry Andric resetTargetOptions(F); 1948bcb0991SDimitry Andric I = std::make_unique<MipsSubtarget>( 1958bcb0991SDimitry Andric TargetTriple, CPU, FS, isLittle, *this, 196fe6060f1SDimitry Andric MaybeAlign(F.getParent()->getOverrideStackAlignment())); 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric return I.get(); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { 2020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "resetSubtarget\n"); 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric Subtarget = &MF->getSubtarget<MipsSubtarget>(); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric namespace { 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric /// Mips Code Generator Pass Configuration Options. 2100b57cec5SDimitry Andric class MipsPassConfig : public TargetPassConfig { 2110b57cec5SDimitry Andric public: 2120b57cec5SDimitry Andric MipsPassConfig(MipsTargetMachine &TM, PassManagerBase &PM) 2130b57cec5SDimitry Andric : TargetPassConfig(TM, PM) { 2140b57cec5SDimitry Andric // The current implementation of long branch pass requires a scratch 2150b57cec5SDimitry Andric // register ($at) to be available before branch instructions. Tail merging 2160b57cec5SDimitry Andric // can break this requirement, so disable it when long branch pass is 2170b57cec5SDimitry Andric // enabled. 2180b57cec5SDimitry Andric EnableTailMerge = !getMipsSubtarget().enableLongBranchPass(); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric MipsTargetMachine &getMipsTargetMachine() const { 2220b57cec5SDimitry Andric return getTM<MipsTargetMachine>(); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric const MipsSubtarget &getMipsSubtarget() const { 2260b57cec5SDimitry Andric return *getMipsTargetMachine().getSubtargetImpl(); 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric void addIRPasses() override; 2300b57cec5SDimitry Andric bool addInstSelector() override; 2310b57cec5SDimitry Andric void addPreEmitPass() override; 2320b57cec5SDimitry Andric void addPreRegAlloc() override; 2330b57cec5SDimitry Andric bool addIRTranslator() override; 2340b57cec5SDimitry Andric void addPreLegalizeMachineIR() override; 2350b57cec5SDimitry Andric bool addLegalizeMachineIR() override; 2360b57cec5SDimitry Andric bool addRegBankSelect() override; 2370b57cec5SDimitry Andric bool addGlobalInstructionSelect() override; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase> getCSEConfig() const override; 2400b57cec5SDimitry Andric }; 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric } // end anonymous namespace 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { 2450b57cec5SDimitry Andric return new MipsPassConfig(*this, PM); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric std::unique_ptr<CSEConfigBase> MipsPassConfig::getCSEConfig() const { 2490b57cec5SDimitry Andric return getStandardCSEConfigForOpt(TM->getOptLevel()); 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric void MipsPassConfig::addIRPasses() { 2530b57cec5SDimitry Andric TargetPassConfig::addIRPasses(); 2540b57cec5SDimitry Andric addPass(createAtomicExpandPass()); 2550b57cec5SDimitry Andric if (getMipsSubtarget().os16()) 2560b57cec5SDimitry Andric addPass(createMipsOs16Pass()); 2570b57cec5SDimitry Andric if (getMipsSubtarget().inMips16HardFloat()) 2580b57cec5SDimitry Andric addPass(createMips16HardFloatPass()); 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric // Install an instruction selector pass using 2610b57cec5SDimitry Andric // the ISelDag to gen Mips code. 2620b57cec5SDimitry Andric bool MipsPassConfig::addInstSelector() { 2630b57cec5SDimitry Andric addPass(createMipsModuleISelDagPass()); 2640b57cec5SDimitry Andric addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel())); 2650b57cec5SDimitry Andric addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel())); 2660b57cec5SDimitry Andric return false; 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric void MipsPassConfig::addPreRegAlloc() { 2700b57cec5SDimitry Andric addPass(createMipsOptimizePICCallPass()); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric TargetTransformInfo 2740b57cec5SDimitry Andric MipsTargetMachine::getTargetTransformInfo(const Function &F) { 2750b57cec5SDimitry Andric if (Subtarget->allowMixed16_32()) { 2760b57cec5SDimitry Andric LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n"); 2770b57cec5SDimitry Andric // FIXME: This is no longer necessary as the TTI returned is per-function. 2780b57cec5SDimitry Andric return TargetTransformInfo(F.getParent()->getDataLayout()); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n"); 2820b57cec5SDimitry Andric return TargetTransformInfo(BasicTTIImpl(this, F)); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric // Implemented by targets that want to run passes immediately before 286e8d8bef9SDimitry Andric // machine code is emitted. 2870b57cec5SDimitry Andric void MipsPassConfig::addPreEmitPass() { 2880b57cec5SDimitry Andric // Expand pseudo instructions that are sensitive to register allocation. 2890b57cec5SDimitry Andric addPass(createMipsExpandPseudoPass()); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // The microMIPS size reduction pass performs instruction reselection for 2920b57cec5SDimitry Andric // instructions which can be remapped to a 16 bit instruction. 2930b57cec5SDimitry Andric addPass(createMicroMipsSizeReducePass()); 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // The delay slot filler pass can potientially create forbidden slot hazards 2960b57cec5SDimitry Andric // for MIPSR6 and therefore it should go before MipsBranchExpansion pass. 2970b57cec5SDimitry Andric addPass(createMipsDelaySlotFillerPass()); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric // This pass expands branches and takes care about the forbidden slot hazards. 3000b57cec5SDimitry Andric // Expanding branches may potentially create forbidden slot hazards for 3010b57cec5SDimitry Andric // MIPSR6, and fixing such hazard may potentially break a branch by extending 3020b57cec5SDimitry Andric // its offset out of range. That's why this pass combine these two tasks, and 3030b57cec5SDimitry Andric // runs them alternately until one of them finishes without any changes. Only 3040b57cec5SDimitry Andric // then we can be sure that all branches are expanded properly and no hazards 3050b57cec5SDimitry Andric // exists. 3060b57cec5SDimitry Andric // Any new pass should go before this pass. 3070b57cec5SDimitry Andric addPass(createMipsBranchExpansion()); 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric addPass(createMipsConstantIslandPass()); 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric bool MipsPassConfig::addIRTranslator() { 313e8d8bef9SDimitry Andric addPass(new IRTranslator(getOptLevel())); 3140b57cec5SDimitry Andric return false; 3150b57cec5SDimitry Andric } 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric void MipsPassConfig::addPreLegalizeMachineIR() { 3180b57cec5SDimitry Andric addPass(createMipsPreLegalizeCombiner()); 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric bool MipsPassConfig::addLegalizeMachineIR() { 3220b57cec5SDimitry Andric addPass(new Legalizer()); 3230b57cec5SDimitry Andric return false; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric bool MipsPassConfig::addRegBankSelect() { 3270b57cec5SDimitry Andric addPass(new RegBankSelect()); 3280b57cec5SDimitry Andric return false; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric bool MipsPassConfig::addGlobalInstructionSelect() { 332fe6060f1SDimitry Andric addPass(new InstructionSelect(getOptLevel())); 3330b57cec5SDimitry Andric return false; 3340b57cec5SDimitry Andric } 335