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