1 //===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Implements the info about Mips target spec. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MipsTargetMachine.h" 15 #include "Mips.h" 16 #include "Mips16FrameLowering.h" 17 #include "Mips16HardFloat.h" 18 #include "Mips16ISelDAGToDAG.h" 19 #include "Mips16ISelLowering.h" 20 #include "Mips16InstrInfo.h" 21 #include "MipsFrameLowering.h" 22 #include "MipsInstrInfo.h" 23 #include "MipsModuleISelDAGToDAG.h" 24 #include "MipsOs16.h" 25 #include "MipsSEFrameLowering.h" 26 #include "MipsSEISelDAGToDAG.h" 27 #include "MipsSEISelLowering.h" 28 #include "MipsSEInstrInfo.h" 29 #include "MipsTargetObjectFile.h" 30 #include "llvm/Analysis/TargetTransformInfo.h" 31 #include "llvm/CodeGen/Passes.h" 32 #include "llvm/PassManager.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/TargetRegistry.h" 35 #include "llvm/Support/raw_ostream.h" 36 #include "llvm/Transforms/Scalar.h" 37 using namespace llvm; 38 39 #define DEBUG_TYPE "mips" 40 41 extern "C" void LLVMInitializeMipsTarget() { 42 // Register the target. 43 RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget); 44 RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget); 45 RegisterTargetMachine<MipsebTargetMachine> A(TheMips64Target); 46 RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget); 47 } 48 49 // On function prologue, the stack is created by decrementing 50 // its pointer. Once decremented, all references are done with positive 51 // offset from the stack/frame pointer, using StackGrowsUp enables 52 // an easier handling. 53 // Using CodeModel::Large enables different CALL behavior. 54 MipsTargetMachine::MipsTargetMachine(const Target &T, StringRef TT, 55 StringRef CPU, StringRef FS, 56 const TargetOptions &Options, 57 Reloc::Model RM, CodeModel::Model CM, 58 CodeGenOpt::Level OL, bool isLittle) 59 : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 60 isLittle(isLittle), 61 TLOF(make_unique<MipsTargetObjectFile>()), 62 Subtarget(nullptr), 63 DefaultSubtarget(TT, CPU, FS, isLittle, *this), 64 NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", 65 isLittle, *this), 66 Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", 67 isLittle, *this) { 68 Subtarget = &DefaultSubtarget; 69 initAsmInfo(); 70 } 71 72 MipsTargetMachine::~MipsTargetMachine() {} 73 74 void MipsebTargetMachine::anchor() { } 75 76 MipsebTargetMachine:: 77 MipsebTargetMachine(const Target &T, StringRef TT, 78 StringRef CPU, StringRef FS, const TargetOptions &Options, 79 Reloc::Model RM, CodeModel::Model CM, 80 CodeGenOpt::Level OL) 81 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 82 83 void MipselTargetMachine::anchor() { } 84 85 MipselTargetMachine:: 86 MipselTargetMachine(const Target &T, StringRef TT, 87 StringRef CPU, StringRef FS, const TargetOptions &Options, 88 Reloc::Model RM, CodeModel::Model CM, 89 CodeGenOpt::Level OL) 90 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 91 92 const MipsSubtarget * 93 MipsTargetMachine::getSubtargetImpl(const Function &F) const { 94 AttributeSet FnAttrs = F.getAttributes(); 95 Attribute CPUAttr = 96 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu"); 97 Attribute FSAttr = 98 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features"); 99 100 std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 101 ? CPUAttr.getValueAsString().str() 102 : TargetCPU; 103 std::string FS = !FSAttr.hasAttribute(Attribute::None) 104 ? FSAttr.getValueAsString().str() 105 : TargetFS; 106 bool hasMips16Attr = 107 !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "mips16") 108 .hasAttribute(Attribute::None); 109 bool hasNoMips16Attr = 110 !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "nomips16") 111 .hasAttribute(Attribute::None); 112 113 // FIXME: This is related to the code below to reset the target options, 114 // we need to know whether or not the soft float flag is set on the 115 // function before we can generate a subtarget. We also need to use 116 // it as a key for the subtarget since that can be the only difference 117 // between two functions. 118 Attribute SFAttr = 119 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "use-soft-float"); 120 bool softFloat = !SFAttr.hasAttribute(Attribute::None) 121 ? SFAttr.getValueAsString() == "true" 122 : Options.UseSoftFloat; 123 124 if (hasMips16Attr) 125 FS += FS.empty() ? "+mips16" : ",+mips16"; 126 else if (hasNoMips16Attr) 127 FS += FS.empty() ? "-mips16" : ",-mips16"; 128 129 auto &I = SubtargetMap[CPU + FS + (softFloat ? "use-soft-float=true" 130 : "use-soft-float=false")]; 131 if (!I) { 132 // This needs to be done before we create a new subtarget since any 133 // creation will depend on the TM and the code generation flags on the 134 // function that reside in TargetOptions. 135 resetTargetOptions(F); 136 I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, *this); 137 } 138 return I.get(); 139 } 140 141 void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { 142 DEBUG(dbgs() << "resetSubtarget\n"); 143 144 Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction())); 145 MF->setSubtarget(Subtarget); 146 return; 147 } 148 149 namespace { 150 /// Mips Code Generator Pass Configuration Options. 151 class MipsPassConfig : public TargetPassConfig { 152 public: 153 MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM) 154 : TargetPassConfig(TM, PM) { 155 // The current implementation of long branch pass requires a scratch 156 // register ($at) to be available before branch instructions. Tail merging 157 // can break this requirement, so disable it when long branch pass is 158 // enabled. 159 EnableTailMerge = !getMipsSubtarget().enableLongBranchPass(); 160 } 161 162 MipsTargetMachine &getMipsTargetMachine() const { 163 return getTM<MipsTargetMachine>(); 164 } 165 166 const MipsSubtarget &getMipsSubtarget() const { 167 return *getMipsTargetMachine().getSubtargetImpl(); 168 } 169 170 void addIRPasses() override; 171 bool addInstSelector() override; 172 void addMachineSSAOptimization() override; 173 void addPreEmitPass() override; 174 175 void addPreRegAlloc() override; 176 177 }; 178 } // namespace 179 180 TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { 181 return new MipsPassConfig(this, PM); 182 } 183 184 void MipsPassConfig::addIRPasses() { 185 TargetPassConfig::addIRPasses(); 186 addPass(createAtomicExpandPass(&getMipsTargetMachine())); 187 if (getMipsSubtarget().os16()) 188 addPass(createMipsOs16(getMipsTargetMachine())); 189 if (getMipsSubtarget().inMips16HardFloat()) 190 addPass(createMips16HardFloat(getMipsTargetMachine())); 191 } 192 // Install an instruction selector pass using 193 // the ISelDag to gen Mips code. 194 bool MipsPassConfig::addInstSelector() { 195 addPass(createMipsModuleISelDag(getMipsTargetMachine())); 196 addPass(createMips16ISelDag(getMipsTargetMachine())); 197 addPass(createMipsSEISelDag(getMipsTargetMachine())); 198 return false; 199 } 200 201 void MipsPassConfig::addMachineSSAOptimization() { 202 addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); 203 TargetPassConfig::addMachineSSAOptimization(); 204 } 205 206 void MipsPassConfig::addPreRegAlloc() { 207 if (getOptLevel() == CodeGenOpt::None) 208 addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); 209 } 210 211 void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) { 212 if (Subtarget->allowMixed16_32()) { 213 DEBUG(errs() << "No "); 214 //FIXME: The Basic Target Transform Info 215 // pass needs to become a function pass instead of 216 // being an immutable pass and then this method as it exists now 217 // would be unnecessary. 218 PM.add(createNoTargetTransformInfoPass()); 219 } else 220 LLVMTargetMachine::addAnalysisPasses(PM); 221 DEBUG(errs() << "Target Transform Info Pass Added\n"); 222 } 223 224 // Implemented by targets that want to run passes immediately before 225 // machine code is emitted. return true if -print-machineinstrs should 226 // print out the code after the passes. 227 void MipsPassConfig::addPreEmitPass() { 228 MipsTargetMachine &TM = getMipsTargetMachine(); 229 addPass(createMipsDelaySlotFillerPass(TM)); 230 addPass(createMipsLongBranchPass(TM)); 231 addPass(createMipsConstantIslandPass(TM)); 232 } 233