brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.8 KiB · b22647a Raw
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