LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMSubtarget.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 151 151 100.0 %
Date: 2018-10-20 13:21:21 Functions: 25 25 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===//
       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             : // This file implements the ARM specific subclass of TargetSubtargetInfo.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "ARM.h"
      15             : 
      16             : #include "ARMCallLowering.h"
      17             : #include "ARMLegalizerInfo.h"
      18             : #include "ARMRegisterBankInfo.h"
      19             : #include "ARMSubtarget.h"
      20             : #include "ARMFrameLowering.h"
      21             : #include "ARMInstrInfo.h"
      22             : #include "ARMSubtarget.h"
      23             : #include "ARMTargetMachine.h"
      24             : #include "MCTargetDesc/ARMMCTargetDesc.h"
      25             : #include "Thumb1FrameLowering.h"
      26             : #include "Thumb1InstrInfo.h"
      27             : #include "Thumb2InstrInfo.h"
      28             : #include "llvm/ADT/StringRef.h"
      29             : #include "llvm/ADT/Triple.h"
      30             : #include "llvm/ADT/Twine.h"
      31             : #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
      32             : #include "llvm/CodeGen/MachineFunction.h"
      33             : #include "llvm/IR/Function.h"
      34             : #include "llvm/IR/GlobalValue.h"
      35             : #include "llvm/MC/MCAsmInfo.h"
      36             : #include "llvm/MC/MCTargetOptions.h"
      37             : #include "llvm/Support/CodeGen.h"
      38             : #include "llvm/Support/CommandLine.h"
      39             : #include "llvm/Support/TargetParser.h"
      40             : #include "llvm/Target/TargetOptions.h"
      41             : 
      42             : using namespace llvm;
      43             : 
      44             : #define DEBUG_TYPE "arm-subtarget"
      45             : 
      46             : #define GET_SUBTARGETINFO_TARGET_DESC
      47             : #define GET_SUBTARGETINFO_CTOR
      48             : #include "ARMGenSubtargetInfo.inc"
      49             : 
      50             : static cl::opt<bool>
      51             : UseFusedMulOps("arm-use-mulops",
      52             :                cl::init(true), cl::Hidden);
      53             : 
      54             : enum ITMode {
      55             :   DefaultIT,
      56             :   RestrictedIT,
      57             :   NoRestrictedIT
      58             : };
      59             : 
      60             : static cl::opt<ITMode>
      61             : IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
      62             :    cl::ZeroOrMore,
      63             :    cl::values(clEnumValN(DefaultIT, "arm-default-it",
      64             :                          "Generate IT block based on arch"),
      65             :               clEnumValN(RestrictedIT, "arm-restrict-it",
      66             :                          "Disallow deprecated IT based on ARMv8"),
      67             :               clEnumValN(NoRestrictedIT, "arm-no-restrict-it",
      68             :                          "Allow IT blocks based on ARMv7")));
      69             : 
      70             : /// ForceFastISel - Use the fast-isel, even for subtargets where it is not
      71             : /// currently supported (for testing only).
      72             : static cl::opt<bool>
      73             : ForceFastISel("arm-force-fast-isel",
      74             :                cl::init(false), cl::Hidden);
      75             : 
      76             : /// initializeSubtargetDependencies - Initializes using a CPU and feature string
      77             : /// so that we can use initializer lists for subtarget initialization.
      78        5050 : ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
      79             :                                                             StringRef FS) {
      80        5050 :   initializeEnvironment();
      81        5050 :   initSubtargetFeatures(CPU, FS);
      82        5050 :   return *this;
      83             : }
      84             : 
      85        5050 : ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
      86             :                                                         StringRef FS) {
      87        5050 :   ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
      88        5050 :   if (STI.isThumb1Only())
      89         506 :     return (ARMFrameLowering *)new Thumb1FrameLowering(STI);
      90             : 
      91        4544 :   return new ARMFrameLowering(STI);
      92             : }
      93             : 
      94        5050 : ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU,
      95             :                            const std::string &FS,
      96        5050 :                            const ARMBaseTargetMachine &TM, bool IsLittle)
      97             :     : ARMGenSubtargetInfo(TT, CPU, FS), UseMulOps(UseFusedMulOps),
      98        5050 :       CPUString(CPU), IsLittle(IsLittle), TargetTriple(TT), Options(TM.Options),
      99             :       TM(TM), FrameLowering(initializeFrameLowering(CPU, FS)),
     100             :       // At this point initializeSubtargetDependencies has been called so
     101             :       // we can query directly.
     102        5050 :       InstrInfo(isThumb1Only()
     103         506 :                     ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
     104             :                     : !isThumb()
     105        4544 :                           ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
     106        1557 :                           : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
     107       15150 :       TLInfo(TM, *this) {
     108             : 
     109        5050 :   CallLoweringInfo.reset(new ARMCallLowering(*getTargetLowering()));
     110        5050 :   Legalizer.reset(new ARMLegalizerInfo(*this));
     111             : 
     112        5050 :   auto *RBI = new ARMRegisterBankInfo(*getRegisterInfo());
     113             : 
     114             :   // FIXME: At this point, we can't rely on Subtarget having RBI.
     115             :   // It's awkward to mix passing RBI and the Subtarget; should we pass
     116             :   // TII/TRI as well?
     117        5050 :   InstSelector.reset(createARMInstructionSelector(
     118             :       *static_cast<const ARMBaseTargetMachine *>(&TM), *this, *RBI));
     119             : 
     120             :   RegBankInfo.reset(RBI);
     121        5050 : }
     122             : 
     123         537 : const CallLowering *ARMSubtarget::getCallLowering() const {
     124         537 :   return CallLoweringInfo.get();
     125             : }
     126             : 
     127         358 : const InstructionSelector *ARMSubtarget::getInstructionSelector() const {
     128         358 :   return InstSelector.get();
     129             : }
     130             : 
     131         447 : const LegalizerInfo *ARMSubtarget::getLegalizerInfo() const {
     132         447 :   return Legalizer.get();
     133             : }
     134             : 
     135         315 : const RegisterBankInfo *ARMSubtarget::getRegBankInfo() const {
     136         315 :   return RegBankInfo.get();
     137             : }
     138             : 
     139           8 : bool ARMSubtarget::isXRaySupported() const {
     140             :   // We don't currently suppport Thumb, but Windows requires Thumb.
     141           8 :   return hasV6Ops() && hasARMOps() && !isTargetWindows();
     142             : }
     143             : 
     144        5050 : void ARMSubtarget::initializeEnvironment() {
     145             :   // MCAsmInfo isn't always present (e.g. in opt) so we can't initialize this
     146             :   // directly from it, but we can try to make sure they're consistent when both
     147             :   // available.
     148         777 :   UseSjLjEH = (isTargetDarwin() && !isTargetWatchABI() &&
     149         752 :                Options.ExceptionModel == ExceptionHandling::None) ||
     150        4299 :               Options.ExceptionModel == ExceptionHandling::SjLj;
     151             :   assert((!TM.getMCAsmInfo() ||
     152             :           (TM.getMCAsmInfo()->getExceptionHandlingType() ==
     153             :            ExceptionHandling::SjLj) == UseSjLjEH) &&
     154             :          "inconsistent sjlj choice between CodeGen and MC");
     155        5050 : }
     156             : 
     157        5050 : void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
     158        5050 :   if (CPUString.empty()) {
     159        3637 :     CPUString = "generic";
     160             : 
     161             :     if (isTargetDarwin()) {
     162         570 :       StringRef ArchName = TargetTriple.getArchName();
     163         570 :       ARM::ArchKind AK = ARM::parseArch(ArchName);
     164         570 :       if (AK == ARM::ArchKind::ARMV7S)
     165             :         // Default to the Swift CPU when targeting armv7s/thumbv7s.
     166             :         CPUString = "swift";
     167         534 :       else if (AK == ARM::ArchKind::ARMV7K)
     168             :         // Default to the Cortex-a7 CPU when targeting armv7k/thumbv7k.
     169             :         // ARMv7k does not use SjLj exception handling.
     170             :         CPUString = "cortex-a7";
     171             :     }
     172             :   }
     173             : 
     174             :   // Insert the architecture feature derived from the target triple into the
     175             :   // feature string. This is important for setting features that are implied
     176             :   // based on the architecture version.
     177        5050 :   std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString);
     178        5050 :   if (!FS.empty()) {
     179        2316 :     if (!ArchFS.empty())
     180        3132 :       ArchFS = (Twine(ArchFS) + "," + FS).str();
     181             :     else
     182        1500 :       ArchFS = FS;
     183             :   }
     184        5050 :   ParseSubtargetFeatures(CPUString, ArchFS);
     185             : 
     186             :   // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
     187             :   // Assert this for now to make the change obvious.
     188             :   assert(hasV6T2Ops() || !hasThumb2());
     189             : 
     190             :   // Execute only support requires movt support
     191        5050 :   if (genExecuteOnly()) {
     192          46 :     NoMovt = false;
     193             :     assert(hasV8MBaselineOps() && "Cannot generate execute-only code for this target");
     194             :   }
     195             : 
     196             :   // Keep a pointer to static instruction cost data for the specified CPU.
     197       10100 :   SchedModel = getSchedModelForCPU(CPUString);
     198             : 
     199             :   // Initialize scheduling itinerary for the specified CPU.
     200        5050 :   InstrItins = getInstrItineraryForCPU(CPUString);
     201             : 
     202             :   // FIXME: this is invalid for WindowsCE
     203        5050 :   if (isTargetWindows())
     204          84 :     NoARM = true;
     205             : 
     206        5050 :   if (isAAPCS_ABI())
     207        4301 :     stackAlignment = 8;
     208        5050 :   if (isTargetNaCl() || isAAPCS16_ABI())
     209          33 :     stackAlignment = 16;
     210             : 
     211             :   // FIXME: Completely disable sibcall for Thumb1 since ThumbRegisterInfo::
     212             :   // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as
     213             :   // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation
     214             :   // support in the assembler and linker to be used. This would need to be
     215             :   // fixed to fully support tail calls in Thumb1.
     216             :   //
     217             :   // For ARMv8-M, we /do/ implement tail calls.  Doing this is tricky for v8-M
     218             :   // baseline, since the LDM/POP instruction on Thumb doesn't take LR.  This
     219             :   // means if we need to reload LR, it takes extra instructions, which outweighs
     220             :   // the value of the tail call; but here we don't know yet whether LR is going
     221             :   // to be used. We take the optimistic approach of generating the tail call and
     222             :   // perhaps taking a hit if we need to restore the LR.
     223             : 
     224             :   // Thumb1 PIC calls to external symbols use BX, so they can be tail calls,
     225             :   // but we need to make sure there are enough registers; the only valid
     226             :   // registers are the 4 used for parameters.  We don't currently do this
     227             :   // case.
     228             : 
     229        6657 :   SupportsTailCall = !isThumb() || hasV8MBaselineOps();
     230             : 
     231        5432 :   if (isTargetMachO() && isTargetIOS() && getTargetTriple().isOSVersionLT(5, 0))
     232         289 :     SupportsTailCall = false;
     233             : 
     234        5050 :   switch (IT) {
     235        5026 :   case DefaultIT:
     236        5026 :     RestrictIT = hasV8Ops();
     237        5026 :     break;
     238          18 :   case RestrictedIT:
     239          18 :     RestrictIT = true;
     240          18 :     break;
     241           6 :   case NoRestrictedIT:
     242           6 :     RestrictIT = false;
     243           6 :     break;
     244             :   }
     245             : 
     246             :   // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
     247             :   const FeatureBitset &Bits = getFeatureBits();
     248        5050 :   if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
     249         346 :       (Options.UnsafeFPMath || isTargetDarwin()))
     250         150 :     UseNEONForSinglePrecisionFP = true;
     251             : 
     252        5050 :   if (isRWPI())
     253          61 :     ReserveR9 = true;
     254             : 
     255             :   // FIXME: Teach TableGen to deal with these instead of doing it manually here.
     256        5050 :   switch (ARMProcFamily) {
     257             :   case Others:
     258             :   case CortexA5:
     259             :     break;
     260         114 :   case CortexA7:
     261         114 :     LdStMultipleTiming = DoubleIssue;
     262         114 :     break;
     263         327 :   case CortexA8:
     264         327 :     LdStMultipleTiming = DoubleIssue;
     265         327 :     break;
     266         109 :   case CortexA9:
     267         109 :     LdStMultipleTiming = DoubleIssueCheckUnalignedAccess;
     268         109 :     PreISelOperandLatencyAdjustment = 1;
     269         109 :     break;
     270             :   case CortexA12:
     271             :     break;
     272          48 :   case CortexA15:
     273          48 :     MaxInterleaveFactor = 2;
     274          48 :     PreISelOperandLatencyAdjustment = 1;
     275          48 :     PartialUpdateClearance = 12;
     276          48 :     break;
     277             :   case CortexA17:
     278             :   case CortexA32:
     279             :   case CortexA35:
     280             :   case CortexA53:
     281             :   case CortexA55:
     282             :   case CortexA57:
     283             :   case CortexA72:
     284             :   case CortexA73:
     285             :   case CortexA75:
     286             :   case CortexR4:
     287             :   case CortexR4F:
     288             :   case CortexR5:
     289             :   case CortexR7:
     290             :   case CortexM3:
     291             :   case CortexR52:
     292             :     break;
     293          40 :   case Exynos:
     294          40 :     LdStMultipleTiming = SingleIssuePlusExtras;
     295          40 :     MaxInterleaveFactor = 4;
     296          40 :     if (!isThumb())
     297          40 :       PrefLoopAlignment = 3;
     298             :     break;
     299             :   case Kryo:
     300             :     break;
     301          12 :   case Krait:
     302          12 :     PreISelOperandLatencyAdjustment = 1;
     303          12 :     break;
     304         102 :   case Swift:
     305         102 :     MaxInterleaveFactor = 2;
     306         102 :     LdStMultipleTiming = SingleIssuePlusExtras;
     307         102 :     PreISelOperandLatencyAdjustment = 1;
     308         102 :     PartialUpdateClearance = 12;
     309         102 :     break;
     310             :   }
     311        5050 : }
     312             : 
     313         463 : bool ARMSubtarget::isTargetHardFloat() const { return TM.isTargetHardFloat(); }
     314             : 
     315           5 : bool ARMSubtarget::isAPCS_ABI() const {
     316             :   assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
     317           5 :   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS;
     318             : }
     319      101168 : bool ARMSubtarget::isAAPCS_ABI() const {
     320             :   assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
     321      101168 :   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS ||
     322      101168 :          TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
     323             : }
     324        5042 : bool ARMSubtarget::isAAPCS16_ABI() const {
     325             :   assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
     326        5042 :   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
     327             : }
     328             : 
     329       18614 : bool ARMSubtarget::isROPI() const {
     330       36823 :   return TM.getRelocationModel() == Reloc::ROPI ||
     331       18209 :          TM.getRelocationModel() == Reloc::ROPI_RWPI;
     332             : }
     333       10663 : bool ARMSubtarget::isRWPI() const {
     334       21156 :   return TM.getRelocationModel() == Reloc::RWPI ||
     335       10493 :          TM.getRelocationModel() == Reloc::ROPI_RWPI;
     336             : }
     337             : 
     338        2698 : bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
     339        2698 :   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
     340             :     return true;
     341             : 
     342             :   // 32 bit macho has no relocation for a-b if a is undefined, even if b is in
     343             :   // the section that is being relocated. This means we have to use o load even
     344             :   // for GVs that are known to be local to the dso.
     345        2262 :   if (isTargetMachO() && TM.isPositionIndependent() &&
     346         907 :       (GV->isDeclarationForLinker() || GV->hasCommonLinkage()))
     347          56 :     return true;
     348             : 
     349             :   return false;
     350             : }
     351             : 
     352          32 : bool ARMSubtarget::isGVInGOT(const GlobalValue *GV) const {
     353          48 :   return isTargetELF() && TM.isPositionIndependent() &&
     354          16 :          !TM.shouldAssumeDSOLocal(*GV->getParent(), GV);
     355             : }
     356             : 
     357        1550 : unsigned ARMSubtarget::getMispredictionPenalty() const {
     358        1550 :   return SchedModel.MispredictPenalty;
     359             : }
     360             : 
     361       44313 : bool ARMSubtarget::enableMachineScheduler() const {
     362             :   // Enable the MachineScheduler before register allocation for subtargets
     363             :   // with the use-misched feature.
     364       44313 :   return useMachineScheduler();
     365             : }
     366             : 
     367             : // This overrides the PostRAScheduler bit in the SchedModel for any CPU.
     368       13155 : bool ARMSubtarget::enablePostRAScheduler() const {
     369       13155 :   if (disablePostRAScheduler())
     370             :     return false;
     371             :   // Don't reschedule potential IT blocks.
     372       25774 :   return !isThumb1Only();
     373             : }
     374             : 
     375       14736 : bool ARMSubtarget::enableAtomicExpand() const { return hasAnyDataBarrier(); }
     376             : 
     377        1144 : bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const {
     378             :   // For general targets, the prologue can grow when VFPs are allocated with
     379             :   // stride 4 (more vpush instructions). But WatchOS uses a compact unwind
     380             :   // format which it's more important to get right.
     381        1144 :   return isTargetWatchABI() ||
     382        1131 :          (useWideStrideVFP() && !MF.getFunction().optForMinSize());
     383             : }
     384             : 
     385       12798 : bool ARMSubtarget::useMovt(const MachineFunction &MF) const {
     386             :   // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit
     387             :   // immediates as it is inherently position independent, and may be out of
     388             :   // range otherwise.
     389       12798 :   return !NoMovt && hasV8MBaselineOps() &&
     390        8001 :          (isTargetWindows() || !MF.getFunction().optForMinSize() || genExecuteOnly());
     391             : }
     392             : 
     393      328961 : bool ARMSubtarget::useFastISel() const {
     394             :   // Enable fast-isel for any target, for testing only.
     395      328961 :   if (ForceFastISel)
     396             :     return true;
     397             : 
     398             :   // Limit fast-isel to the targets that are or have been tested.
     399      328879 :   if (!hasV6Ops())
     400             :     return false;
     401             : 
     402             :   // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl.
     403       36153 :   return TM.Options.EnableFastISel &&
     404       36238 :          ((isTargetMachO() && !isThumb1Only()) ||
     405      281829 :           (isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb()));
     406             : }

Generated by: LCOV version 1.13