340 lines · cpp
1//===-- MipsSubtarget.cpp - Mips Subtarget Information --------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the Mips specific subclass of TargetSubtargetInfo.10//11//===----------------------------------------------------------------------===//12 13#include "MipsSubtarget.h"14#include "Mips.h"15#include "MipsCallLowering.h"16#include "MipsLegalizerInfo.h"17#include "MipsRegisterBankInfo.h"18#include "MipsRegisterInfo.h"19#include "MipsSelectionDAGInfo.h"20#include "MipsTargetMachine.h"21#include "llvm/IR/Attributes.h"22#include "llvm/IR/Function.h"23#include "llvm/MC/TargetRegistry.h"24#include "llvm/Support/CommandLine.h"25#include "llvm/Support/Debug.h"26#include "llvm/Support/raw_ostream.h"27 28using namespace llvm;29 30#define DEBUG_TYPE "mips-subtarget"31 32#define GET_SUBTARGETINFO_TARGET_DESC33#define GET_SUBTARGETINFO_CTOR34#include "MipsGenSubtargetInfo.inc"35 36// FIXME: Maybe this should be on by default when Mips16 is specified37//38static cl::opt<bool>39 Mixed16_32("mips-mixed-16-32", cl::init(false),40 cl::desc("Allow for a mixture of Mips16 "41 "and Mips32 code in a single output file"),42 cl::Hidden);43 44static cl::opt<bool> Mips_Os16("mips-os16", cl::init(false),45 cl::desc("Compile all functions that don't use "46 "floating point as Mips 16"),47 cl::Hidden);48 49static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden,50 cl::desc("Enable mips16 hard float."),51 cl::init(false));52 53static cl::opt<bool>54 Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden,55 cl::desc("Enable mips16 constant islands."),56 cl::init(true));57 58static cl::opt<bool>59 GPOpt("mgpopt", cl::Hidden,60 cl::desc("Enable gp-relative addressing of mips small data items"));61 62bool MipsSubtarget::DspWarningPrinted = false;63bool MipsSubtarget::MSAWarningPrinted = false;64bool MipsSubtarget::VirtWarningPrinted = false;65bool MipsSubtarget::CRCWarningPrinted = false;66bool MipsSubtarget::GINVWarningPrinted = false;67bool MipsSubtarget::MIPS1WarningPrinted = false;68 69void MipsSubtarget::anchor() {}70 71MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS,72 bool little, const MipsTargetMachine &TM,73 MaybeAlign StackAlignOverride)74 : MipsGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),75 MipsArchVersion(MipsDefault), IsLittle(little), IsSoftFloat(false),76 IsSingleFloat(false), IsFPXX(false), NoABICalls(false), Abs2008(false),77 IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false),78 IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasCnMipsP(false),79 HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false),80 HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false),81 InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false),82 HasDSPR2(false), HasDSPR3(false),83 AllowMixed16_32(Mixed16_32 || Mips_Os16), Os16(Mips_Os16), HasMSA(false),84 UseTCCInDIV(false), HasSym32(false), HasEVA(false), DisableMadd4(false),85 HasMT(false), HasCRC(false), HasVirt(false), HasGINV(false),86 UseIndirectJumpsHazard(false), StrictAlign(false),87 StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT),88 InstrInfo(89 MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))),90 FrameLowering(MipsFrameLowering::create(*this)),91 TLInfo(MipsTargetLowering::create(TM, *this)) {92 93 if (MipsArchVersion == MipsDefault)94 MipsArchVersion = Mips32;95 96 // MIPS-I has not been tested.97 if (MipsArchVersion == Mips1 && !MIPS1WarningPrinted) {98 errs() << "warning: MIPS-I support is experimental\n";99 MIPS1WarningPrinted = true;100 }101 102 // Don't even attempt to generate code for MIPS-V. It has not103 // been tested and currently exists for the integrated assembler only.104 if (MipsArchVersion == Mips5)105 report_fatal_error("Code generation for MIPS-V is not implemented", false);106 107 // Check if Architecture and ABI are compatible.108 assert(((!isGP64bit() && isABI_O32()) || isGP64bit()) &&109 "Invalid Arch & ABI pair.");110 111 if (hasMSA() && !isFP64bit())112 report_fatal_error("MSA requires a 64-bit FPU register file (FR=1 mode). "113 "See -mattr=+fp64.",114 false);115 116 if (isFP64bit() && !hasMips64() && hasMips32() && !hasMips32r2())117 report_fatal_error(118 "FPU with 64-bit registers is not available on MIPS32 pre revision 2. "119 "Use -mcpu=mips32r2 or greater.", false);120 121 if (!isABI_O32() && !useOddSPReg())122 report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false);123 124 if (IsFPXX && (isABI_N32() || isABI_N64()))125 report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false);126 127 if (hasMips64r6() && InMicroMipsMode)128 report_fatal_error("microMIPS64R6 is not supported", false);129 130 if (!isABI_O32() && InMicroMipsMode)131 report_fatal_error("microMIPS64 is not supported.", false);132 133 if (UseIndirectJumpsHazard) {134 if (InMicroMipsMode)135 report_fatal_error(136 "cannot combine indirect jumps with hazard barriers and microMIPS");137 if (!hasMips32r2())138 report_fatal_error(139 "indirect jumps with hazard barriers requires MIPS32R2 or later");140 }141 if (inAbs2008Mode() && hasMips32() && !hasMips32r2()) {142 report_fatal_error("IEEE 754-2008 abs.fmt is not supported for the given "143 "architecture.",144 false);145 }146 147 if (hasMips32r6()) {148 StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";149 150 assert(isFP64bit());151 assert(isNaN2008());152 assert(inAbs2008Mode());153 if (hasDSP())154 report_fatal_error(ISA + " is not compatible with the DSP ASE", false);155 }156 157 if (NoABICalls && TM.isPositionIndependent())158 report_fatal_error("position-independent code requires '-mabicalls'");159 160 if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32())161 NoABICalls = true;162 163 // Set UseSmallSection.164 UseSmallSection = GPOpt;165 if (!NoABICalls && GPOpt) {166 errs() << "warning: cannot use small-data accesses for '-mabicalls'"167 << "\n";168 UseSmallSection = false;169 }170 171 if (hasDSPR2() && !DspWarningPrinted) {172 if (hasMips64() && !hasMips64r2()) {173 errs() << "warning: the 'dspr2' ASE requires MIPS64 revision 2 or "174 << "greater\n";175 DspWarningPrinted = true;176 } else if (hasMips32() && !hasMips32r2()) {177 errs() << "warning: the 'dspr2' ASE requires MIPS32 revision 2 or "178 << "greater\n";179 DspWarningPrinted = true;180 }181 } else if (hasDSP() && !DspWarningPrinted) {182 if (hasMips64() && !hasMips64r2()) {183 errs() << "warning: the 'dsp' ASE requires MIPS64 revision 2 or "184 << "greater\n";185 DspWarningPrinted = true;186 } else if (hasMips32() && !hasMips32r2()) {187 errs() << "warning: the 'dsp' ASE requires MIPS32 revision 2 or "188 << "greater\n";189 DspWarningPrinted = true;190 }191 }192 193 StringRef ArchName = hasMips64() ? "MIPS64" : "MIPS32";194 195 if (!hasMips32r5() && hasMSA() && !MSAWarningPrinted) {196 errs() << "warning: the 'msa' ASE requires " << ArchName197 << " revision 5 or greater\n";198 MSAWarningPrinted = true;199 }200 if (!hasMips32r5() && hasVirt() && !VirtWarningPrinted) {201 errs() << "warning: the 'virt' ASE requires " << ArchName202 << " revision 5 or greater\n";203 VirtWarningPrinted = true;204 }205 if (!hasMips32r6() && hasCRC() && !CRCWarningPrinted) {206 errs() << "warning: the 'crc' ASE requires " << ArchName207 << " revision 6 or greater\n";208 CRCWarningPrinted = true;209 }210 if (!hasMips32r6() && hasGINV() && !GINVWarningPrinted) {211 errs() << "warning: the 'ginv' ASE requires " << ArchName212 << " revision 6 or greater\n";213 GINVWarningPrinted = true;214 }215 216 TSInfo = std::make_unique<MipsSelectionDAGInfo>();217 218 CallLoweringInfo.reset(new MipsCallLowering(*getTargetLowering()));219 Legalizer.reset(new MipsLegalizerInfo(*this));220 221 auto *RBI = new MipsRegisterBankInfo(*getRegisterInfo());222 RegBankInfo.reset(RBI);223 InstSelector.reset(createMipsInstructionSelector(TM, *this, *RBI));224}225 226MipsSubtarget::~MipsSubtarget() = default;227 228bool MipsSubtarget::isPositionIndependent() const {229 return TM.isPositionIndependent();230}231 232/// This overrides the PostRAScheduler bit in the SchedModel for any CPU.233bool MipsSubtarget::enablePostRAScheduler() const { return true; }234 235void MipsSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {236 CriticalPathRCs.clear();237 CriticalPathRCs.push_back(isGP64bit() ? &Mips::GPR64RegClass238 : &Mips::GPR32RegClass);239}240 241CodeGenOptLevel MipsSubtarget::getOptLevelToEnablePostRAScheduler() const {242 return CodeGenOptLevel::Aggressive;243}244 245MipsSubtarget &246MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS,247 const TargetMachine &TM) {248 StringRef CPUName = MIPS_MC::selectMipsCPU(TM.getTargetTriple(), CPU);249 250 // Parse features string.251 ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);252 // Initialize scheduling itinerary for the specified CPU.253 InstrItins = getInstrItineraryForCPU(CPUName);254 255 if (InMips16Mode && !IsSoftFloat)256 InMips16HardFloat = true;257 258 if (StackAlignOverride)259 stackAlignment = *StackAlignOverride;260 else if (isABI_N32() || isABI_N64())261 stackAlignment = Align(16);262 else {263 assert(isABI_O32() && "Unknown ABI for stack alignment!");264 stackAlignment = Align(8);265 }266 267 if ((isABI_N32() || isABI_N64()) && !isGP64bit())268 reportFatalUsageError("64-bit code requested on a subtarget that doesn't "269 "support it!");270 271 return *this;272}273 274bool MipsSubtarget::useConstantIslands() {275 LLVM_DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands276 << "\n");277 return Mips16ConstantIslands;278}279 280Reloc::Model MipsSubtarget::getRelocationModel() const {281 return TM.getRelocationModel();282}283 284bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); }285bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); }286bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); }287const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); }288 289const SelectionDAGTargetInfo *MipsSubtarget::getSelectionDAGInfo() const {290 return TSInfo.get();291}292 293const CallLowering *MipsSubtarget::getCallLowering() const {294 return CallLoweringInfo.get();295}296 297const LegalizerInfo *MipsSubtarget::getLegalizerInfo() const {298 return Legalizer.get();299}300 301const RegisterBankInfo *MipsSubtarget::getRegBankInfo() const {302 return RegBankInfo.get();303}304 305InstructionSelector *MipsSubtarget::getInstructionSelector() const {306 return InstSelector.get();307}308 309// Libcalls for which no helper is generated. Sorted by name for binary search.310const RTLIB::LibcallImpl MipsSubtarget::HardFloatLibCalls[34] = {311 RTLIB::impl___mips16_adddf3, RTLIB::impl___mips16_addsf3,312 RTLIB::impl___mips16_divdf3, RTLIB::impl___mips16_divsf3,313 RTLIB::impl___mips16_eqdf2, RTLIB::impl___mips16_eqsf2,314 RTLIB::impl___mips16_extendsfdf2, RTLIB::impl___mips16_fix_truncdfsi,315 RTLIB::impl___mips16_fix_truncsfsi, RTLIB::impl___mips16_floatsidf,316 RTLIB::impl___mips16_floatsisf, RTLIB::impl___mips16_floatunsidf,317 RTLIB::impl___mips16_floatunsisf, RTLIB::impl___mips16_gedf2,318 RTLIB::impl___mips16_gesf2, RTLIB::impl___mips16_gtdf2,319 RTLIB::impl___mips16_gtsf2, RTLIB::impl___mips16_ledf2,320 RTLIB::impl___mips16_lesf2, RTLIB::impl___mips16_ltdf2,321 RTLIB::impl___mips16_ltsf2, RTLIB::impl___mips16_muldf3,322 RTLIB::impl___mips16_mulsf3, RTLIB::impl___mips16_nedf2,323 RTLIB::impl___mips16_nesf2, RTLIB::impl___mips16_ret_dc,324 RTLIB::impl___mips16_ret_df, RTLIB::impl___mips16_ret_sc,325 RTLIB::impl___mips16_ret_sf, RTLIB::impl___mips16_subdf3,326 RTLIB::impl___mips16_subsf3, RTLIB::impl___mips16_truncdfsf2,327 RTLIB::impl___mips16_unorddf2, RTLIB::impl___mips16_unordsf2};328 329void MipsSubtarget::initLibcallLoweringInfo(LibcallLoweringInfo &Info) const {330 if (inMips16Mode() && !useSoftFloat()) {331 for (unsigned I = 0; I != std::size(HardFloatLibCalls); ++I) {332 assert((I == 0 || HardFloatLibCalls[I - 1] < HardFloatLibCalls[I]) &&333 "Array not sorted!");334 RTLIB::Libcall LC =335 RTLIB::RuntimeLibcallsInfo::getLibcallFromImpl(HardFloatLibCalls[I]);336 Info.setLibcallImpl(LC, HardFloatLibCalls[I]);337 }338 }339}340