1193323Sed//===-- MipsTargetMachine.cpp - Define TargetMachine for Mips -------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// Implements the info about Mips target spec. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14234353Sdim#include "MipsTargetMachine.h" 15193323Sed#include "Mips.h" 16276479Sdim#include "Mips16FrameLowering.h" 17276479Sdim#include "Mips16ISelDAGToDAG.h" 18276479Sdim#include "Mips16ISelLowering.h" 19276479Sdim#include "Mips16InstrInfo.h" 20239462Sdim#include "MipsFrameLowering.h" 21239462Sdim#include "MipsInstrInfo.h" 22251662Sdim#include "MipsSEFrameLowering.h" 23276479Sdim#include "MipsSEISelDAGToDAG.h" 24276479Sdim#include "MipsSEISelLowering.h" 25251662Sdim#include "MipsSEInstrInfo.h" 26280031Sdim#include "MipsTargetObjectFile.h" 27251662Sdim#include "llvm/Analysis/TargetTransformInfo.h" 28249423Sdim#include "llvm/CodeGen/Passes.h" 29288943Sdim#include "llvm/IR/LegacyPassManager.h" 30251662Sdim#include "llvm/Support/Debug.h" 31276479Sdim#include "llvm/Support/TargetRegistry.h" 32251662Sdim#include "llvm/Support/raw_ostream.h" 33261991Sdim#include "llvm/Transforms/Scalar.h" 34288943Sdim 35193323Sedusing namespace llvm; 36193323Sed 37276479Sdim#define DEBUG_TYPE "mips" 38251662Sdim 39198090Srdivackyextern "C" void LLVMInitializeMipsTarget() { 40198090Srdivacky // Register the target. 41226633Sdim RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget); 42198090Srdivacky RegisterTargetMachine<MipselTargetMachine> Y(TheMipselTarget); 43239462Sdim RegisterTargetMachine<MipsebTargetMachine> A(TheMips64Target); 44239462Sdim RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget); 45193323Sed} 46193323Sed 47288943Sdimstatic std::string computeDataLayout(const Triple &TT, StringRef CPU, 48288943Sdim const TargetOptions &Options, 49288943Sdim bool isLittle) { 50288943Sdim std::string Ret = ""; 51288943Sdim MipsABIInfo ABI = MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions); 52288943Sdim 53288943Sdim // There are both little and big endian mips. 54288943Sdim if (isLittle) 55288943Sdim Ret += "e"; 56288943Sdim else 57288943Sdim Ret += "E"; 58288943Sdim 59288943Sdim Ret += "-m:m"; 60288943Sdim 61288943Sdim // Pointers are 32 bit on some ABIs. 62288943Sdim if (!ABI.IsN64()) 63288943Sdim Ret += "-p:32:32"; 64288943Sdim 65288943Sdim // 8 and 16 bit integers only need to have natural alignment, but try to 66288943Sdim // align them to 32 bits. 64 bit integers have natural alignment. 67288943Sdim Ret += "-i8:8:32-i16:16:32-i64:64"; 68288943Sdim 69288943Sdim // 32 bit registers are always available and the stack is at least 64 bit 70288943Sdim // aligned. On N64 64 bit registers are also available and the stack is 71288943Sdim // 128 bit aligned. 72288943Sdim if (ABI.IsN64() || ABI.IsN32()) 73288943Sdim Ret += "-n32:64-S128"; 74288943Sdim else 75288943Sdim Ret += "-n32-S64"; 76288943Sdim 77288943Sdim return Ret; 78288943Sdim} 79288943Sdim 80193323Sed// On function prologue, the stack is created by decrementing 81193323Sed// its pointer. Once decremented, all references are done with positive 82218893Sdim// offset from the stack/frame pointer, using StackGrowsUp enables 83193323Sed// an easier handling. 84193323Sed// Using CodeModel::Large enables different CALL behavior. 85288943SdimMipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, 86276479Sdim StringRef CPU, StringRef FS, 87276479Sdim const TargetOptions &Options, 88276479Sdim Reloc::Model RM, CodeModel::Model CM, 89276479Sdim CodeGenOpt::Level OL, bool isLittle) 90288943Sdim : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, 91288943Sdim CPU, FS, Options, RM, CM, OL), 92288943Sdim isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()), 93288943Sdim ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)), 94288943Sdim Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this), 95276479Sdim NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", 96280031Sdim isLittle, *this), 97276479Sdim Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", 98280031Sdim isLittle, *this) { 99276479Sdim Subtarget = &DefaultSubtarget; 100261991Sdim initAsmInfo(); 101193323Sed} 102193323Sed 103280031SdimMipsTargetMachine::~MipsTargetMachine() {} 104280031Sdim 105234353Sdimvoid MipsebTargetMachine::anchor() { } 106234353Sdim 107288943SdimMipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, 108288943Sdim StringRef CPU, StringRef FS, 109288943Sdim const TargetOptions &Options, 110288943Sdim Reloc::Model RM, CodeModel::Model CM, 111288943Sdim CodeGenOpt::Level OL) 112288943Sdim : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 113226633Sdim 114234353Sdimvoid MipselTargetMachine::anchor() { } 115234353Sdim 116288943SdimMipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, 117288943Sdim StringRef CPU, StringRef FS, 118288943Sdim const TargetOptions &Options, 119288943Sdim Reloc::Model RM, CodeModel::Model CM, 120288943Sdim CodeGenOpt::Level OL) 121288943Sdim : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 122193323Sed 123280031Sdimconst MipsSubtarget * 124280031SdimMipsTargetMachine::getSubtargetImpl(const Function &F) const { 125288943Sdim Attribute CPUAttr = F.getFnAttribute("target-cpu"); 126288943Sdim Attribute FSAttr = F.getFnAttribute("target-features"); 127280031Sdim 128280031Sdim std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 129280031Sdim ? CPUAttr.getValueAsString().str() 130280031Sdim : TargetCPU; 131280031Sdim std::string FS = !FSAttr.hasAttribute(Attribute::None) 132280031Sdim ? FSAttr.getValueAsString().str() 133280031Sdim : TargetFS; 134280031Sdim bool hasMips16Attr = 135288943Sdim !F.getFnAttribute("mips16").hasAttribute(Attribute::None); 136280031Sdim bool hasNoMips16Attr = 137288943Sdim !F.getFnAttribute("nomips16").hasAttribute(Attribute::None); 138280031Sdim 139280031Sdim // FIXME: This is related to the code below to reset the target options, 140280031Sdim // we need to know whether or not the soft float flag is set on the 141288943Sdim // function, so we can enable it as a subtarget feature. 142288943Sdim bool softFloat = 143288943Sdim F.hasFnAttribute("use-soft-float") && 144288943Sdim F.getFnAttribute("use-soft-float").getValueAsString() == "true"; 145280031Sdim 146280031Sdim if (hasMips16Attr) 147280031Sdim FS += FS.empty() ? "+mips16" : ",+mips16"; 148280031Sdim else if (hasNoMips16Attr) 149280031Sdim FS += FS.empty() ? "-mips16" : ",-mips16"; 150288943Sdim if (softFloat) 151288943Sdim FS += FS.empty() ? "+soft-float" : ",+soft-float"; 152280031Sdim 153288943Sdim auto &I = SubtargetMap[CPU + FS]; 154280031Sdim if (!I) { 155280031Sdim // This needs to be done before we create a new subtarget since any 156280031Sdim // creation will depend on the TM and the code generation flags on the 157280031Sdim // function that reside in TargetOptions. 158280031Sdim resetTargetOptions(F); 159288943Sdim I = llvm::make_unique<MipsSubtarget>(TargetTriple, CPU, FS, isLittle, 160288943Sdim *this); 161280031Sdim } 162280031Sdim return I.get(); 163280031Sdim} 164280031Sdim 165276479Sdimvoid MipsTargetMachine::resetSubtarget(MachineFunction *MF) { 166276479Sdim DEBUG(dbgs() << "resetSubtarget\n"); 167280031Sdim 168280031Sdim Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(*MF->getFunction())); 169280031Sdim MF->setSubtarget(Subtarget); 170276479Sdim return; 171276479Sdim} 172276479Sdim 173234353Sdimnamespace { 174234353Sdim/// Mips Code Generator Pass Configuration Options. 175234353Sdimclass MipsPassConfig : public TargetPassConfig { 176234353Sdimpublic: 177234353Sdim MipsPassConfig(MipsTargetMachine *TM, PassManagerBase &PM) 178261991Sdim : TargetPassConfig(TM, PM) { 179261991Sdim // The current implementation of long branch pass requires a scratch 180261991Sdim // register ($at) to be available before branch instructions. Tail merging 181261991Sdim // can break this requirement, so disable it when long branch pass is 182261991Sdim // enabled. 183261991Sdim EnableTailMerge = !getMipsSubtarget().enableLongBranchPass(); 184261991Sdim } 185234353Sdim 186234353Sdim MipsTargetMachine &getMipsTargetMachine() const { 187234353Sdim return getTM<MipsTargetMachine>(); 188234353Sdim } 189234353Sdim 190234353Sdim const MipsSubtarget &getMipsSubtarget() const { 191234353Sdim return *getMipsTargetMachine().getSubtargetImpl(); 192234353Sdim } 193234353Sdim 194276479Sdim void addIRPasses() override; 195276479Sdim bool addInstSelector() override; 196276479Sdim void addMachineSSAOptimization() override; 197280031Sdim void addPreEmitPass() override; 198276479Sdim 199280031Sdim void addPreRegAlloc() override; 200276479Sdim 201234353Sdim}; 202234353Sdim} // namespace 203234353Sdim 204234353SdimTargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) { 205234353Sdim return new MipsPassConfig(this, PM); 206234353Sdim} 207234353Sdim 208251662Sdimvoid MipsPassConfig::addIRPasses() { 209251662Sdim TargetPassConfig::addIRPasses(); 210280031Sdim addPass(createAtomicExpandPass(&getMipsTargetMachine())); 211251662Sdim if (getMipsSubtarget().os16()) 212288943Sdim addPass(createMipsOs16Pass(getMipsTargetMachine())); 213261991Sdim if (getMipsSubtarget().inMips16HardFloat()) 214288943Sdim addPass(createMips16HardFloatPass(getMipsTargetMachine())); 215251662Sdim} 216218893Sdim// Install an instruction selector pass using 217193323Sed// the ISelDag to gen Mips code. 218234982Sdimbool MipsPassConfig::addInstSelector() { 219288943Sdim addPass(createMipsModuleISelDagPass(getMipsTargetMachine())); 220276479Sdim addPass(createMips16ISelDag(getMipsTargetMachine())); 221276479Sdim addPass(createMipsSEISelDag(getMipsTargetMachine())); 222193323Sed return false; 223193323Sed} 224193323Sed 225276479Sdimvoid MipsPassConfig::addMachineSSAOptimization() { 226276479Sdim addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); 227276479Sdim TargetPassConfig::addMachineSSAOptimization(); 228276479Sdim} 229276479Sdim 230280031Sdimvoid MipsPassConfig::addPreRegAlloc() { 231280031Sdim if (getOptLevel() == CodeGenOpt::None) 232276479Sdim addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); 233276479Sdim} 234276479Sdim 235288943SdimTargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() { 236296417Sdim return TargetIRAnalysis([this](const Function &F) { 237288943Sdim if (Subtarget->allowMixed16_32()) { 238288943Sdim DEBUG(errs() << "No Target Transform Info Pass Added\n"); 239288943Sdim // FIXME: This is no longer necessary as the TTI returned is per-function. 240288943Sdim return TargetTransformInfo(F.getParent()->getDataLayout()); 241288943Sdim } 242288943Sdim 243288943Sdim DEBUG(errs() << "Target Transform Info Pass Added\n"); 244288943Sdim return TargetTransformInfo(BasicTTIImpl(this, F)); 245288943Sdim }); 246251662Sdim} 247251662Sdim 248218893Sdim// Implemented by targets that want to run passes immediately before 249218893Sdim// machine code is emitted. return true if -print-machineinstrs should 250193323Sed// print out the code after the passes. 251280031Sdimvoid MipsPassConfig::addPreEmitPass() { 252239462Sdim MipsTargetMachine &TM = getMipsTargetMachine(); 253239462Sdim addPass(createMipsDelaySlotFillerPass(TM)); 254276479Sdim addPass(createMipsLongBranchPass(TM)); 255276479Sdim addPass(createMipsConstantIslandPass(TM)); 256221345Sdim} 257