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

Generated by: LCOV version 1.13