LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMSubtarget.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 148 148 100.0 %
Date: 2018-07-13 00:08:38 Functions: 26 26 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       99743 : UseFusedMulOps("arm-use-mulops",
      52       99743 :                cl::init(true), cl::Hidden);
      53             : 
      54             : enum ITMode {
      55             :   DefaultIT,
      56             :   RestrictedIT,
      57             :   NoRestrictedIT
      58             : };
      59             : 
      60             : static cl::opt<ITMode>
      61      398972 : IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
      62             :    cl::ZeroOrMore,
      63      498715 :    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      498715 :                          "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       99743 : ForceFastISel("arm-force-fast-isel",
      74       99743 :                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        4835 : ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
      79             :                                                             StringRef FS) {
      80        4835 :   initializeEnvironment();
      81        4835 :   initSubtargetFeatures(CPU, FS);
      82        4835 :   return *this;
      83             : }
      84             : 
      85        4835 : ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
      86             :                                                         StringRef FS) {
      87        4835 :   ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
      88        4835 :   if (STI.isThumb1Only())
      89         473 :     return (ARMFrameLowering *)new Thumb1FrameLowering(STI);
      90             : 
      91        4362 :   return new ARMFrameLowering(STI);
      92             : }
      93             : 
      94        4835 : ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU,
      95             :                            const std::string &FS,
      96        4835 :                            const ARMBaseTargetMachine &TM, bool IsLittle)
      97             :     : ARMGenSubtargetInfo(TT, CPU, FS), UseMulOps(UseFusedMulOps),
      98             :       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        4835 :       InstrInfo(isThumb1Only()
     103         473 :                     ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
     104             :                     : !isThumb()
     105        4362 :                           ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
     106        1453 :                           : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
     107       38680 :       TLInfo(TM, *this) {
     108             : 
     109        4835 :   CallLoweringInfo.reset(new ARMCallLowering(*getTargetLowering()));
     110        4835 :   Legalizer.reset(new ARMLegalizerInfo(*this));
     111             : 
     112        4835 :   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        4835 :   InstSelector.reset(createARMInstructionSelector(
     118             :       *static_cast<const ARMBaseTargetMachine *>(&TM), *this, *RBI));
     119             : 
     120             :   RegBankInfo.reset(RBI);
     121        4835 : }
     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         312 : const RegisterBankInfo *ARMSubtarget::getRegBankInfo() const {
     136         312 :   return RegBankInfo.get();
     137             : }
     138             : 
     139           8 : bool ARMSubtarget::isXRaySupported() const {
     140             :   // We don't currently suppport Thumb, but Windows requires Thumb.
     141          16 :   return hasV6Ops() && hasARMOps() && !isTargetWindows();
     142             : }
     143             : 
     144        4835 : 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        6362 :   UseSjLjEH = (isTargetDarwin() && !isTargetWatchABI() &&
     149        4836 :                Options.ExceptionModel == ExceptionHandling::None) ||
     150        4085 :               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        4835 : }
     156             : 
     157        4835 : void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
     158        4835 :   if (CPUString.empty()) {
     159        3484 :     CPUString = "generic";
     160             : 
     161             :     if (isTargetDarwin()) {
     162         569 :       StringRef ArchName = TargetTriple.getArchName();
     163         569 :       ARM::ArchKind AK = ARM::parseArch(ArchName);
     164         569 :       if (AK == ARM::ArchKind::ARMV7S)
     165             :         // Default to the Swift CPU when targeting armv7s/thumbv7s.
     166             :         CPUString = "swift";
     167         533 :       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        4835 :   std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString);
     178        4835 :   if (!FS.empty()) {
     179        2213 :     if (!ArchFS.empty())
     180        2950 :       ArchFS = (Twine(ArchFS) + "," + FS).str();
     181             :     else
     182        1476 :       ArchFS = FS;
     183             :   }
     184        4835 :   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             :   if (genExecuteOnly())
     192             :     assert(hasV8MBaselineOps() && !NoMovt && "Cannot generate execute-only code for this target");
     193             : 
     194             :   // Keep a pointer to static instruction cost data for the specified CPU.
     195        9670 :   SchedModel = getSchedModelForCPU(CPUString);
     196             : 
     197             :   // Initialize scheduling itinerary for the specified CPU.
     198        4835 :   InstrItins = getInstrItineraryForCPU(CPUString);
     199             : 
     200             :   // FIXME: this is invalid for WindowsCE
     201        4835 :   if (isTargetWindows())
     202          81 :     NoARM = true;
     203             : 
     204        4835 :   if (isAAPCS_ABI())
     205        4087 :     stackAlignment = 8;
     206        4835 :   if (isTargetNaCl() || isAAPCS16_ABI())
     207          33 :     stackAlignment = 16;
     208             : 
     209             :   // FIXME: Completely disable sibcall for Thumb1 since ThumbRegisterInfo::
     210             :   // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as
     211             :   // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation
     212             :   // support in the assembler and linker to be used. This would need to be
     213             :   // fixed to fully support tail calls in Thumb1.
     214             :   //
     215             :   // For ARMv8-M, we /do/ implement tail calls.  Doing this is tricky for v8-M
     216             :   // baseline, since the LDM/POP instruction on Thumb doesn't take LR.  This
     217             :   // means if we need to reload LR, it takes extra instructions, which outweighs
     218             :   // the value of the tail call; but here we don't know yet whether LR is going
     219             :   // to be used. We take the optimistic approach of generating the tail call and
     220             :   // perhaps taking a hit if we need to restore the LR.
     221             : 
     222             :   // Thumb1 PIC calls to external symbols use BX, so they can be tail calls,
     223             :   // but we need to make sure there are enough registers; the only valid
     224             :   // registers are the 4 used for parameters.  We don't currently do this
     225             :   // case.
     226             : 
     227        4835 :   SupportsTailCall = !isThumb() || hasV8MBaselineOps();
     228             : 
     229        5217 :   if (isTargetMachO() && isTargetIOS() && getTargetTriple().isOSVersionLT(5, 0))
     230         289 :     SupportsTailCall = false;
     231             : 
     232        4835 :   switch (IT) {
     233        4811 :   case DefaultIT:
     234        4811 :     RestrictIT = hasV8Ops();
     235        4811 :     break;
     236          18 :   case RestrictedIT:
     237          18 :     RestrictIT = true;
     238          18 :     break;
     239           6 :   case NoRestrictedIT:
     240           6 :     RestrictIT = false;
     241           6 :     break;
     242             :   }
     243             : 
     244             :   // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
     245             :   const FeatureBitset &Bits = getFeatureBits();
     246        9992 :   if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
     247         341 :       (Options.UnsafeFPMath || isTargetDarwin()))
     248         150 :     UseNEONForSinglePrecisionFP = true;
     249             : 
     250        4835 :   if (isRWPI())
     251          59 :     ReserveR9 = true;
     252             : 
     253             :   // FIXME: Teach TableGen to deal with these instead of doing it manually here.
     254        4835 :   switch (ARMProcFamily) {
     255             :   case Others:
     256             :   case CortexA5:
     257             :     break;
     258         111 :   case CortexA7:
     259         111 :     LdStMultipleTiming = DoubleIssue;
     260         111 :     break;
     261         322 :   case CortexA8:
     262         322 :     LdStMultipleTiming = DoubleIssue;
     263         322 :     break;
     264         108 :   case CortexA9:
     265         108 :     LdStMultipleTiming = DoubleIssueCheckUnalignedAccess;
     266         108 :     PreISelOperandLatencyAdjustment = 1;
     267         108 :     break;
     268             :   case CortexA12:
     269             :     break;
     270          52 :   case CortexA15:
     271          52 :     MaxInterleaveFactor = 2;
     272          52 :     PreISelOperandLatencyAdjustment = 1;
     273          52 :     PartialUpdateClearance = 12;
     274          52 :     break;
     275             :   case CortexA17:
     276             :   case CortexA32:
     277             :   case CortexA35:
     278             :   case CortexA53:
     279             :   case CortexA55:
     280             :   case CortexA57:
     281             :   case CortexA72:
     282             :   case CortexA73:
     283             :   case CortexA75:
     284             :   case CortexR4:
     285             :   case CortexR4F:
     286             :   case CortexR5:
     287             :   case CortexR7:
     288             :   case CortexM3:
     289             :   case CortexR52:
     290             :   case ExynosM1:
     291             :   case Kryo:
     292             :     break;
     293          12 :   case Krait:
     294          12 :     PreISelOperandLatencyAdjustment = 1;
     295          12 :     break;
     296         102 :   case Swift:
     297         102 :     MaxInterleaveFactor = 2;
     298         102 :     LdStMultipleTiming = SingleIssuePlusExtras;
     299         102 :     PreISelOperandLatencyAdjustment = 1;
     300         102 :     PartialUpdateClearance = 12;
     301         102 :     break;
     302             :   }
     303        4835 : }
     304             : 
     305           5 : bool ARMSubtarget::isAPCS_ABI() const {
     306             :   assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
     307           5 :   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS;
     308             : }
     309       96373 : bool ARMSubtarget::isAAPCS_ABI() const {
     310             :   assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
     311       96373 :   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS ||
     312       96373 :          TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
     313             : }
     314        4964 : bool ARMSubtarget::isAAPCS16_ABI() const {
     315             :   assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
     316        4964 :   return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16;
     317             : }
     318             : 
     319       17423 : bool ARMSubtarget::isROPI() const {
     320       34521 :   return TM.getRelocationModel() == Reloc::ROPI ||
     321       34521 :          TM.getRelocationModel() == Reloc::ROPI_RWPI;
     322             : }
     323       10200 : bool ARMSubtarget::isRWPI() const {
     324       20240 :   return TM.getRelocationModel() == Reloc::RWPI ||
     325       20240 :          TM.getRelocationModel() == Reloc::ROPI_RWPI;
     326             : }
     327             : 
     328        2690 : bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
     329        2690 :   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
     330             :     return true;
     331             : 
     332             :   // 32 bit macho has no relocation for a-b if a is undefined, even if b is in
     333             :   // the section that is being relocated. This means we have to use o load even
     334             :   // for GVs that are known to be local to the dso.
     335        2246 :   if (isTargetMachO() && TM.isPositionIndependent() &&
     336         899 :       (GV->isDeclarationForLinker() || GV->hasCommonLinkage()))
     337             :     return true;
     338             : 
     339             :   return false;
     340             : }
     341             : 
     342          32 : bool ARMSubtarget::isGVInGOT(const GlobalValue *GV) const {
     343          48 :   return isTargetELF() && TM.isPositionIndependent() &&
     344          48 :          !TM.shouldAssumeDSOLocal(*GV->getParent(), GV);
     345             : }
     346             : 
     347        1473 : unsigned ARMSubtarget::getMispredictionPenalty() const {
     348        1473 :   return SchedModel.MispredictPenalty;
     349             : }
     350             : 
     351       41501 : bool ARMSubtarget::enableMachineScheduler() const {
     352             :   // Enable the MachineScheduler before register allocation for subtargets
     353             :   // with the use-misched feature.
     354       41501 :   return useMachineScheduler();
     355             : }
     356             : 
     357             : // This overrides the PostRAScheduler bit in the SchedModel for any CPU.
     358       12304 : bool ARMSubtarget::enablePostRAScheduler() const {
     359       12304 :   if (disablePostRAScheduler())
     360             :     return false;
     361             :   // Don't reschedule potential IT blocks.
     362       24072 :   return !isThumb1Only();
     363             : }
     364             : 
     365       27762 : bool ARMSubtarget::enableAtomicExpand() const { return hasAnyDataBarrier(); }
     366             : 
     367        1096 : bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const {
     368             :   // For general targets, the prologue can grow when VFPs are allocated with
     369             :   // stride 4 (more vpush instructions). But WatchOS uses a compact unwind
     370             :   // format which it's more important to get right.
     371        1193 :   return isTargetWatchABI() || (isSwift() && !MF.getFunction().optForMinSize());
     372             : }
     373             : 
     374       12450 : bool ARMSubtarget::useMovt(const MachineFunction &MF) const {
     375             :   // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit
     376             :   // immediates as it is inherently position independent, and may be out of
     377             :   // range otherwise.
     378       20361 :   return !NoMovt && hasV8MBaselineOps() &&
     379       15524 :          (isTargetWindows() || !MF.getFunction().optForMinSize() || genExecuteOnly());
     380             : }
     381             : 
     382      309367 : bool ARMSubtarget::useFastISel() const {
     383             :   // Enable fast-isel for any target, for testing only.
     384      309367 :   if (ForceFastISel)
     385             :     return true;
     386             : 
     387             :   // Limit fast-isel to the targets that are or have been tested.
     388      309285 :   if (!hasV6Ops())
     389             :     return false;
     390             : 
     391             :   // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl.
     392      543029 :   return TM.Options.EnableFastISel &&
     393       36062 :          ((isTargetMachO() && !isThumb1Only()) ||
     394      258447 :           (isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb()));
     395      299229 : }

Generated by: LCOV version 1.13