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 "Mips16ISelDAGToDAG.h" 18 #include "Mips16ISelLowering.h" 19 #include "Mips16InstrInfo.h" 20 #include "MipsFrameLowering.h" 21 #include "MipsInstrInfo.h" 22 #include "MipsSEFrameLowering.h" 23 #include "MipsSEISelDAGToDAG.h" 24 #include "MipsSEISelLowering.h" 25 #include "MipsSEInstrInfo.h" 26 #include "MipsTargetObjectFile.h" 27 #include "llvm/Analysis/TargetTransformInfo.h" 28 #include "llvm/CodeGen/Passes.h" 29 #include "llvm/CodeGen/TargetPassConfig.h" 30 #include "llvm/IR/LegacyPassManager.h" 31 #include "llvm/Support/Debug.h" 32 #include "llvm/Support/TargetRegistry.h" 33 #include "llvm/Support/raw_ostream.h" 34 #include "llvm/Transforms/Scalar.h" 35 36 using namespace llvm; 37 38 #define DEBUG_TYPE "mips" 39 40 extern "C" void LLVMInitializeMipsTarget() { 41 // Register the target. 42 RegisterTargetMachine<MipsebTargetMachine> X(getTheMipsTarget()); 43 RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget()); 44 RegisterTargetMachine<MipsebTargetMachine> A(getTheMips64Target()); 45 RegisterTargetMachine<MipselTargetMachine> B(getTheMips64elTarget()); 46 } 47 48 static std::string computeDataLayout(const Triple &TT, StringRef CPU, 49 const TargetOptions &Options, 50 bool isLittle) { 51 std::string Ret = ""; 52 MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); 53 54 // There are both little and big endian mips. 55 if (isLittle) 56 Ret += "e"; 57 else 58 Ret += "E"; 59 60 if (ABI.IsO32()) 61 Ret += "-m:m"; 62 else 63 Ret += "-m:e"; 64 65 // Pointers are 32 bit on some ABIs. 66 if (!ABI.IsN64()) 67 Ret += "-p:32:32"; 68 69 // 8 and 16 bit integers only need to have natural alignment, but try to 70 // align them to 32 bits. 64 bit integers have natural alignment. 71 Ret += "-i8:8:32-i16:16:32-i64:64"; 72 73 // 32 bit registers are always available and the stack is at least 64 bit 74 // aligned. On N64 64 bit registers are also available and the stack is 75 // 128 bit aligned. 76 if (ABI.IsN64() || ABI.IsN32()) 77 Ret += "-n32:64-S128"; 78 else 79 Ret += "-n32-S64"; 80 81 return Ret; 82 } 83 84 static Reloc::Model getEffectiveRelocModel(CodeModel::Model CM, 85 Optional<Reloc::Model> RM) { 86 if (!RM.hasValue() || CM == CodeModel::JITDefault) 87 return Reloc::Static; 88 return *RM; 89 } 90 91 // On function prologue, the stack is created by decrementing 92 // its pointer. Once decremented, all references are done with positive 93 // offset from the stack/frame pointer, using StackGrowsUp enables 94 // an easier handling. 95 // Using CodeModel::Large enables different CALL behavior. 96 MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, 97 StringRef CPU, StringRef FS, 98 const TargetOptions &Options, 99 Optional<Reloc::Model> RM, 100 CodeModel::Model CM, CodeGenOpt::Level OL, 101 bool isLittle) 102 : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, 103 CPU, FS, Options, getEffectiveRelocModel(CM, RM), CM, 104 OL), 105 isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()), 106 ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)), 107 Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this), 108 NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", 109 isLittle, *this), 110 Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", 111 isLittle, *this) { 112 Subtarget = &DefaultSubtarget; 113 initAsmInfo(); 114 } 115 116 MipsTargetMachine::~MipsTargetMachine() {} 117 118 void MipsebTargetMachine::anchor() { } 119 120 MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, 121 StringRef CPU, StringRef FS, 122 const TargetOptions &Options, 123 Optional<Reloc::Model> RM, 124 CodeModel::Model CM, 125 CodeGenOpt::Level OL) 126 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 127 128 void MipselTargetMachine::anchor() { } 129 130 MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, 131 StringRef CPU, StringRef FS, 132 const TargetOptions &Options, 133 Optional<Reloc::Model> RM, 134 CodeModel::Model CM, 135 CodeGenOpt::Level OL) 136 : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 137 138 const MipsSubtarget * 139 MipsTargetMachine::getSubtargetImpl(const Function &F) const { 140 Attribute CPUAttr = F.getFnAttribute("target-cpu"); 141 Attribute FSAttr = F.getFnAttribute("target-features"); 142 143 std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 144 ? CPUAttr.getValueAsString().str() 145 : TargetCPU; 146 std::string FS = !FSAttr.hasAttribute(Attribute::None) 147 ? FSAttr.getValueAsString().str() 148 : TargetFS; 149 bool hasMips16Attr = 150 !F.getFnAttribute("mips16").hasAttribute(Attribute::None); 151 bool hasNoMips16Attr = 152 !F.getFnAttribute("nomips16").hasAttribute(Attribute::None); 153 154 // FIXME: This is related to the code below to reset the target options, 155 // we need to know whether or not the soft float flag is set on the 156 // function, so we can enable it as a subtarget feature. 157 bool softFloat = 158 F.hasFnAttribute("use-soft-float") && 159 F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 160 161 if (hasMips16Attr) 162 FS += FS.empty() ? "+mips16" : ",+mips16"; 163 else if (hasNoMips16Attr) 164 FS += FS.empty() ? "-mips16" : ",-mips16"; 165 if (softFloat) 166 FS += FS.empty() ? "+soft-float" : ",+soft-float"; 167 168 auto &I = SubtargetMap[CPU + FS]; 169 if (!I) { 170 // This needs to be done before we create a new subtarget since any 171 // creation will depend on the TM and the code generation flags on the 172 // function that reside in TargetOptions. 173 resetTargetOptions(F); 174 I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, 175 *this); 176 } 177 return I.get(); 178 } 179 180 void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { 181 DEBUG(dbgs() << "resetSubtarget\n"); 182 183 Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction())); 184 MF->setSubtarget(Subtarget); 185 return; 186 } 187 188 namespace { 189 /// Mips Code Generator Pass Configuration Options. 190 class MipsPassConfig : public TargetPassConfig { 191 public: 192 MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM) 193 : TargetPassConfig(TM, PM) { 194 // The current implementation of long branch pass requires a scratch 195 // register ($at) to be available before branch instructions. Tail merging 196 // can break this requirement, so disable it when long branch pass is 197 // enabled. 198 EnableTailMerge = !getMipsSubtarget().enableLongBranchPass(); 199 } 200 201 MipsTargetMachine &getMipsTargetMachine() const { 202 return getTM<MipsTargetMachine>(); 203 } 204 205 const MipsSubtarget &getMipsSubtarget() const { 206 return *getMipsTargetMachine().getSubtargetImpl(); 207 } 208 209 void addIRPasses() override; 210 bool addInstSelector() override; 211 void addMachineSSAOptimization() override; 212 void addPreEmitPass() override; 213 214 void addPreRegAlloc() override; 215 216 }; 217 } // namespace 218 219 TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { 220 return new MipsPassConfig(this, PM); 221 } 222 223 void MipsPassConfig::addIRPasses() { 224 TargetPassConfig::addIRPasses(); 225 addPass(createAtomicExpandPass(&getMipsTargetMachine())); 226 if (getMipsSubtarget().os16()) 227 addPass(createMipsOs16Pass(getMipsTargetMachine())); 228 if (getMipsSubtarget().inMips16HardFloat()) 229 addPass(createMips16HardFloatPass(getMipsTargetMachine())); 230 } 231 // Install an instruction selector pass using 232 // the ISelDag to gen Mips code. 233 bool MipsPassConfig::addInstSelector() { 234 addPass(createMipsModuleISelDagPass(getMipsTargetMachine())); 235 addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel())); 236 addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel())); 237 return false; 238 } 239 240 void MipsPassConfig::addMachineSSAOptimization() { 241 addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); 242 TargetPassConfig::addMachineSSAOptimization(); 243 } 244 245 void MipsPassConfig::addPreRegAlloc() { 246 if (getOptLevel() == CodeGenOpt::None) 247 addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); 248 } 249 250 TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() { 251 return TargetIRAnalysis([this](const Function &F) { 252 if (Subtarget->allowMixed16_32()) { 253 DEBUG(errs() << "No Target Transform Info Pass Added\n"); 254 // FIXME: This is no longer necessary as the TTI returned is per-function. 255 return TargetTransformInfo(F.getParent()->getDataLayout()); 256 } 257 258 DEBUG(errs() << "Target Transform Info Pass Added\n"); 259 return TargetTransformInfo(BasicTTIImpl(this, F)); 260 }); 261 } 262 263 // Implemented by targets that want to run passes immediately before 264 // machine code is emitted. return true if -print-machineinstrs should 265 // print out the code after the passes. 266 void MipsPassConfig::addPreEmitPass() { 267 MipsTargetMachine &TM = getMipsTargetMachine(); 268 269 // The delay slot filler pass can potientially create forbidden slot (FS) 270 // hazards for MIPSR6 which the hazard schedule pass (HSP) will fix. Any 271 // (new) pass that creates compact branches after the HSP must handle FS 272 // hazards itself or be pipelined before the HSP. 273 addPass(createMipsDelaySlotFillerPass(TM)); 274 addPass(createMipsHazardSchedule()); 275 addPass(createMipsLongBranchPass(TM)); 276 addPass(createMipsConstantIslandPass()); 277 } 278