560 lines · cpp
1//===-- ARMSubtarget.cpp - ARM 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 ARM specific subclass of TargetSubtargetInfo.10//11//===----------------------------------------------------------------------===//12 13#include "ARM.h"14 15#include "ARMCallLowering.h"16#include "ARMFrameLowering.h"17#include "ARMInstrInfo.h"18#include "ARMLegalizerInfo.h"19#include "ARMRegisterBankInfo.h"20#include "ARMSubtarget.h"21#include "ARMTargetMachine.h"22#include "MCTargetDesc/ARMMCTargetDesc.h"23#include "Thumb1FrameLowering.h"24#include "Thumb1InstrInfo.h"25#include "Thumb2InstrInfo.h"26#include "llvm/ADT/StringRef.h"27#include "llvm/ADT/Twine.h"28#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"29#include "llvm/CodeGen/MachineFrameInfo.h"30#include "llvm/CodeGen/MachineFunction.h"31#include "llvm/IR/Function.h"32#include "llvm/IR/GlobalValue.h"33#include "llvm/MC/MCAsmInfo.h"34#include "llvm/MC/MCTargetOptions.h"35#include "llvm/Support/CodeGen.h"36#include "llvm/Support/CommandLine.h"37#include "llvm/Target/TargetOptions.h"38#include "llvm/TargetParser/ARMTargetParser.h"39#include "llvm/TargetParser/Triple.h"40 41using namespace llvm;42 43#define DEBUG_TYPE "arm-subtarget"44 45#define GET_SUBTARGETINFO_TARGET_DESC46#define GET_SUBTARGETINFO_CTOR47#include "ARMGenSubtargetInfo.inc"48 49static cl::opt<bool>50UseFusedMulOps("arm-use-mulops",51 cl::init(true), cl::Hidden);52 53enum ITMode {54 DefaultIT,55 RestrictedIT56};57 58static cl::opt<ITMode>59 IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),60 cl::values(clEnumValN(DefaultIT, "arm-default-it",61 "Generate any type of IT block"),62 clEnumValN(RestrictedIT, "arm-restrict-it",63 "Disallow complex IT blocks")));64 65/// ForceFastISel - Use the fast-isel, even for subtargets where it is not66/// currently supported (for testing only).67static cl::opt<bool>68ForceFastISel("arm-force-fast-isel",69 cl::init(false), cl::Hidden);70 71/// initializeSubtargetDependencies - Initializes using a CPU and feature string72/// so that we can use initializer lists for subtarget initialization.73ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,74 StringRef FS) {75 initSubtargetFeatures(CPU, FS);76 return *this;77}78 79ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,80 StringRef FS) {81 ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);82 if (STI.isThumb1Only())83 return (ARMFrameLowering *)new Thumb1FrameLowering(STI);84 85 return new ARMFrameLowering(STI);86}87 88ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU,89 const std::string &FS,90 const ARMBaseTargetMachine &TM, bool IsLittle,91 bool MinSize, DenormalMode DM)92 : ARMGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),93 UseMulOps(UseFusedMulOps), CPUString(CPU), OptMinSize(MinSize),94 IsLittle(IsLittle), DM(DM), TargetTriple(TT), Options(TM.Options), TM(TM),95 FrameLowering(initializeFrameLowering(CPU, FS)),96 // At this point initializeSubtargetDependencies has been called so97 // we can query directly.98 InstrInfo(isThumb1Only() ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)99 : !isThumb() ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)100 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),101 TLInfo(TM, *this) {102 103 CallLoweringInfo.reset(new ARMCallLowering(*getTargetLowering()));104 Legalizer.reset(new ARMLegalizerInfo(*this));105 106 auto *RBI = new ARMRegisterBankInfo(*getRegisterInfo());107 108 // FIXME: At this point, we can't rely on Subtarget having RBI.109 // It's awkward to mix passing RBI and the Subtarget; should we pass110 // TII/TRI as well?111 InstSelector.reset(createARMInstructionSelector(TM, *this, *RBI));112 113 RegBankInfo.reset(RBI);114}115 116const CallLowering *ARMSubtarget::getCallLowering() const {117 return CallLoweringInfo.get();118}119 120InstructionSelector *ARMSubtarget::getInstructionSelector() const {121 return InstSelector.get();122}123 124const LegalizerInfo *ARMSubtarget::getLegalizerInfo() const {125 return Legalizer.get();126}127 128const RegisterBankInfo *ARMSubtarget::getRegBankInfo() const {129 return RegBankInfo.get();130}131 132void ARMSubtarget::initLibcallLoweringInfo(LibcallLoweringInfo &Info) const {133 const Triple &TT = getTargetTriple();134 if (TT.isOSBinFormatMachO()) {135 // Uses VFP for Thumb libfuncs if available.136 if (isThumb() && hasVFP2Base() && hasARMOps() && !useSoftFloat()) {137 // clang-format off138 static const struct {139 const RTLIB::Libcall Op;140 const RTLIB::LibcallImpl Impl;141 } LibraryCalls[] = {142 // Single-precision floating-point arithmetic.143 { RTLIB::ADD_F32, RTLIB::impl___addsf3vfp },144 { RTLIB::SUB_F32, RTLIB::impl___subsf3vfp },145 { RTLIB::MUL_F32, RTLIB::impl___mulsf3vfp },146 { RTLIB::DIV_F32, RTLIB::impl___divsf3vfp },147 148 // Double-precision floating-point arithmetic.149 { RTLIB::ADD_F64, RTLIB::impl___adddf3vfp },150 { RTLIB::SUB_F64, RTLIB::impl___subdf3vfp },151 { RTLIB::MUL_F64, RTLIB::impl___muldf3vfp },152 { RTLIB::DIV_F64, RTLIB::impl___divdf3vfp },153 154 // Single-precision comparisons.155 { RTLIB::OEQ_F32, RTLIB::impl___eqsf2vfp },156 { RTLIB::UNE_F32, RTLIB::impl___nesf2vfp },157 { RTLIB::OLT_F32, RTLIB::impl___ltsf2vfp },158 { RTLIB::OLE_F32, RTLIB::impl___lesf2vfp },159 { RTLIB::OGE_F32, RTLIB::impl___gesf2vfp },160 { RTLIB::OGT_F32, RTLIB::impl___gtsf2vfp },161 { RTLIB::UO_F32, RTLIB::impl___unordsf2vfp },162 163 // Double-precision comparisons.164 { RTLIB::OEQ_F64, RTLIB::impl___eqdf2vfp },165 { RTLIB::UNE_F64, RTLIB::impl___nedf2vfp },166 { RTLIB::OLT_F64, RTLIB::impl___ltdf2vfp },167 { RTLIB::OLE_F64, RTLIB::impl___ledf2vfp },168 { RTLIB::OGE_F64, RTLIB::impl___gedf2vfp },169 { RTLIB::OGT_F64, RTLIB::impl___gtdf2vfp },170 { RTLIB::UO_F64, RTLIB::impl___unorddf2vfp },171 172 // Floating-point to integer conversions.173 // i64 conversions are done via library routines even when generating VFP174 // instructions, so use the same ones.175 { RTLIB::FPTOSINT_F64_I32, RTLIB::impl___fixdfsivfp },176 { RTLIB::FPTOUINT_F64_I32, RTLIB::impl___fixunsdfsivfp },177 { RTLIB::FPTOSINT_F32_I32, RTLIB::impl___fixsfsivfp },178 { RTLIB::FPTOUINT_F32_I32, RTLIB::impl___fixunssfsivfp },179 180 // Conversions between floating types.181 { RTLIB::FPROUND_F64_F32, RTLIB::impl___truncdfsf2vfp },182 { RTLIB::FPEXT_F32_F64, RTLIB::impl___extendsfdf2vfp },183 184 // Integer to floating-point conversions.185 // i64 conversions are done via library routines even when generating VFP186 // instructions, so use the same ones.187 // FIXME: There appears to be some naming inconsistency in ARM libgcc:188 // e.g., __floatunsidf vs. __floatunssidfvfp.189 { RTLIB::SINTTOFP_I32_F64, RTLIB::impl___floatsidfvfp },190 { RTLIB::UINTTOFP_I32_F64, RTLIB::impl___floatunssidfvfp },191 { RTLIB::SINTTOFP_I32_F32, RTLIB::impl___floatsisfvfp },192 { RTLIB::UINTTOFP_I32_F32, RTLIB::impl___floatunssisfvfp },193 };194 // clang-format on195 196 for (const auto &LC : LibraryCalls)197 Info.setLibcallImpl(LC.Op, LC.Impl);198 }199 }200}201 202bool ARMSubtarget::isXRaySupported() const {203 // We don't currently suppport Thumb, but Windows requires Thumb.204 return hasV6Ops() && hasARMOps() && !isTargetWindows();205}206 207void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {208 if (CPUString.empty()) {209 CPUString = "generic";210 211 if (isTargetDarwin()) {212 StringRef ArchName = TargetTriple.getArchName();213 ARM::ArchKind AK = ARM::parseArch(ArchName);214 if (AK == ARM::ArchKind::ARMV7S)215 // Default to the Swift CPU when targeting armv7s/thumbv7s.216 CPUString = "swift";217 else if (AK == ARM::ArchKind::ARMV7K)218 // Default to the Cortex-a7 CPU when targeting armv7k/thumbv7k.219 // ARMv7k does not use SjLj exception handling.220 CPUString = "cortex-a7";221 }222 }223 224 // Insert the architecture feature derived from the target triple into the225 // feature string. This is important for setting features that are implied226 // based on the architecture version.227 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString);228 if (!FS.empty()) {229 if (!ArchFS.empty())230 ArchFS = (Twine(ArchFS) + "," + FS).str();231 else232 ArchFS = std::string(FS);233 }234 ParseSubtargetFeatures(CPUString, /*TuneCPU*/ CPUString, ArchFS);235 236 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.237 // Assert this for now to make the change obvious.238 assert(hasV6T2Ops() || !hasThumb2());239 240 if (genExecuteOnly()) {241 // Execute only support for >= v8-M Baseline requires movt support242 if (hasV8MBaselineOps())243 NoMovt = false;244 if (!hasV6MOps())245 report_fatal_error("Cannot generate execute-only code for this target");246 }247 248 // Keep a pointer to static instruction cost data for the specified CPU.249 SchedModel = getSchedModelForCPU(CPUString);250 251 // Initialize scheduling itinerary for the specified CPU.252 InstrItins = getInstrItineraryForCPU(CPUString);253 254 // FIXME: this is invalid for WindowsCE255 if (isTargetWindows())256 NoARM = true;257 258 if (TM.isAAPCS_ABI())259 stackAlignment = Align(8);260 if (TM.isAAPCS16_ABI())261 stackAlignment = Align(16);262 263 // FIXME: Completely disable sibcall for Thumb1 since ThumbRegisterInfo::264 // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as265 // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation266 // support in the assembler and linker to be used. This would need to be267 // fixed to fully support tail calls in Thumb1.268 //269 // For ARMv8-M, we /do/ implement tail calls. Doing this is tricky for v8-M270 // baseline, since the LDM/POP instruction on Thumb doesn't take LR. This271 // means if we need to reload LR, it takes extra instructions, which outweighs272 // the value of the tail call; but here we don't know yet whether LR is going273 // to be used. We take the optimistic approach of generating the tail call and274 // perhaps taking a hit if we need to restore the LR.275 276 // Thumb1 PIC calls to external symbols use BX, so they can be tail calls,277 // but we need to make sure there are enough registers; the only valid278 // registers are the 4 used for parameters. We don't currently do this279 // case.280 281 SupportsTailCall = !isThumb1Only() || hasV8MBaselineOps();282 283 switch (IT) {284 case DefaultIT:285 RestrictIT = false;286 break;287 case RestrictedIT:288 RestrictIT = true;289 break;290 }291 292 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.293 const FeatureBitset &Bits = getFeatureBits();294 if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters295 (isTargetDarwin() || DM == DenormalMode::getPreserveSign()))296 HasNEONForFP = true;297 298 const ARM::ArchKind Arch = ARM::parseArch(TargetTriple.getArchName());299 if (isRWPI() ||300 (isTargetIOS() &&301 (Arch == ARM::ArchKind::ARMV6K || Arch == ARM::ArchKind::ARMV6) &&302 TargetTriple.isOSVersionLT(3, 0)))303 ReserveR9 = true;304 305 // If MVEVectorCostFactor is still 0 (has not been set to anything else), default it to 2306 if (MVEVectorCostFactor == 0)307 MVEVectorCostFactor = 2;308 309 // FIXME: Teach TableGen to deal with these instead of doing it manually here.310 switch (ARMProcFamily) {311 case Others:312 case CortexA5:313 break;314 case CortexA7:315 LdStMultipleTiming = DoubleIssue;316 break;317 case CortexA8:318 LdStMultipleTiming = DoubleIssue;319 break;320 case CortexA9:321 LdStMultipleTiming = DoubleIssueCheckUnalignedAccess;322 PreISelOperandLatencyAdjustment = 1;323 break;324 case CortexA12:325 break;326 case CortexA15:327 MaxInterleaveFactor = 2;328 PreISelOperandLatencyAdjustment = 1;329 PartialUpdateClearance = 12;330 break;331 case CortexA17:332 case CortexA32:333 case CortexA35:334 case CortexA53:335 case CortexA55:336 case CortexA57:337 case CortexA72:338 case CortexA73:339 case CortexA75:340 case CortexA76:341 case CortexA77:342 case CortexA78:343 case CortexA78AE:344 case CortexA78C:345 case CortexA510:346 case CortexA710:347 case CortexR4:348 case CortexR5:349 case CortexR7:350 case CortexM3:351 case CortexM55:352 case CortexM7:353 case CortexM85:354 case CortexR52:355 case CortexR52plus:356 case CortexX1:357 case CortexX1C:358 break;359 case Exynos:360 LdStMultipleTiming = SingleIssuePlusExtras;361 MaxInterleaveFactor = 4;362 if (!isThumb())363 PreferBranchLogAlignment = 3;364 break;365 case Kryo:366 break;367 case Krait:368 PreISelOperandLatencyAdjustment = 1;369 break;370 case NeoverseV1:371 break;372 case Swift:373 MaxInterleaveFactor = 2;374 LdStMultipleTiming = SingleIssuePlusExtras;375 PreISelOperandLatencyAdjustment = 1;376 PartialUpdateClearance = 12;377 break;378 }379}380 381bool ARMSubtarget::isROPI() const {382 // FIXME: This should ideally come from a function attribute, to work383 // correctly with LTO.384 return TM.getRelocationModel() == Reloc::ROPI ||385 TM.getRelocationModel() == Reloc::ROPI_RWPI;386}387 388bool ARMSubtarget::isRWPI() const {389 // FIXME: This should ideally come from a function attribute, to work390 // correctly with LTO.391 return TM.getRelocationModel() == Reloc::RWPI ||392 TM.getRelocationModel() == Reloc::ROPI_RWPI;393}394 395bool ARMSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {396 return TM.isGVIndirectSymbol(GV);397}398 399bool ARMSubtarget::isGVInGOT(const GlobalValue *GV) const {400 return isTargetELF() && TM.isPositionIndependent() && !GV->isDSOLocal();401}402 403unsigned ARMSubtarget::getMispredictionPenalty() const {404 return SchedModel.MispredictPenalty;405}406 407bool ARMSubtarget::enableMachineScheduler() const {408 // The MachineScheduler can increase register usage, so we use more high409 // registers and end up with more T2 instructions that cannot be converted to410 // T1 instructions. At least until we do better at converting to thumb1411 // instructions, on cortex-m at Oz where we are size-paranoid, don't use the412 // Machine scheduler, relying on the DAG register pressure scheduler instead.413 if (isMClass() && hasMinSize())414 return false;415 // Enable the MachineScheduler before register allocation for subtargets416 // with the use-misched feature.417 return useMachineScheduler();418}419 420bool ARMSubtarget::enableSubRegLiveness() const {421 // Enable SubRegLiveness for MVE to better optimize s subregs for mqpr regs422 // and q subregs for qqqqpr regs.423 return hasMVEIntegerOps();424}425 426bool ARMSubtarget::enableMachinePipeliner() const {427 // Enable the MachinePipeliner before register allocation for subtargets428 // with the use-mipipeliner feature.429 return getSchedModel().hasInstrSchedModel() && useMachinePipeliner();430}431 432bool ARMSubtarget::useDFAforSMS() const { return false; }433 434// This overrides the PostRAScheduler bit in the SchedModel for any CPU.435bool ARMSubtarget::enablePostRAScheduler() const {436 if (enableMachineScheduler())437 return false;438 if (disablePostRAScheduler())439 return false;440 // Thumb1 cores will generally not benefit from post-ra scheduling441 return !isThumb1Only();442}443 444bool ARMSubtarget::enablePostRAMachineScheduler() const {445 if (!enableMachineScheduler())446 return false;447 if (disablePostRAScheduler())448 return false;449 return !isThumb1Only();450}451 452bool ARMSubtarget::useStride4VFPs() const {453 // For general targets, the prologue can grow when VFPs are allocated with454 // stride 4 (more vpush instructions). But WatchOS uses a compact unwind455 // format which it's more important to get right.456 return isTargetWatchABI() ||457 (useWideStrideVFP() && !OptMinSize);458}459 460bool ARMSubtarget::useMovt() const {461 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit462 // immediates as it is inherently position independent, and may be out of463 // range otherwise.464 return !NoMovt && hasV8MBaselineOps() &&465 (isTargetWindows() || !OptMinSize || genExecuteOnly());466}467 468bool ARMSubtarget::useFastISel() const {469 // Enable fast-isel for any target, for testing only.470 if (ForceFastISel)471 return true;472 473 // Limit fast-isel to the targets that are or have been tested.474 if (!hasV6Ops())475 return false;476 477 // Thumb2 support on iOS; ARM support on iOS and Linux.478 return TM.Options.EnableFastISel && ((isTargetMachO() && !isThumb1Only()) ||479 (isTargetLinux() && !isThumb()));480}481 482unsigned ARMSubtarget::getGPRAllocationOrder(const MachineFunction &MF) const {483 // The GPR register class has multiple possible allocation orders, with484 // tradeoffs preferred by different sub-architectures and optimisation goals.485 // The allocation orders are:486 // 0: (the default tablegen order, not used)487 // 1: r14, r0-r13488 // 2: r0-r7489 // 3: r0-r7, r12, lr, r8-r11490 // Note that the register allocator will change this order so that491 // callee-saved registers are used later, as they require extra work in the492 // prologue/epilogue (though we sometimes override that).493 494 // For thumb1-only targets, only the low registers are allocatable.495 if (isThumb1Only())496 return 2;497 498 // Allocate low registers first, so we can select more 16-bit instructions.499 // We also (in ignoreCSRForAllocationOrder) override the default behaviour500 // with regards to callee-saved registers, because pushing extra registers is501 // much cheaper (in terms of code size) than using high registers. After502 // that, we allocate r12 (doesn't need to be saved), lr (saving it means we503 // can return with the pop, don't need an extra "bx lr") and then the rest of504 // the high registers.505 if (isThumb2() && MF.getFunction().hasMinSize())506 return 3;507 508 // Otherwise, allocate in the default order, using LR first because saving it509 // allows a shorter epilogue sequence.510 return 1;511}512 513bool ARMSubtarget::ignoreCSRForAllocationOrder(const MachineFunction &MF,514 MCRegister PhysReg) const {515 // To minimize code size in Thumb2, we prefer the usage of low regs (lower516 // cost per use) so we can use narrow encoding. By default, caller-saved517 // registers (e.g. lr, r12) are always allocated first, regardless of518 // their cost per use. When optForMinSize, we prefer the low regs even if519 // they are CSR because usually push/pop can be folded into existing ones.520 return isThumb2() && MF.getFunction().hasMinSize() &&521 ARM::GPRRegClass.contains(PhysReg);522}523 524ARMSubtarget::PushPopSplitVariation525ARMSubtarget::getPushPopSplitVariation(const MachineFunction &MF) const {526 const Function &F = MF.getFunction();527 const MachineFrameInfo &MFI = MF.getFrameInfo();528 529 // Thumb1 always splits the pushes at R7, because the Thumb1 push instruction530 // cannot use high registers except for lr.531 if (isThumb1Only())532 return SplitR7;533 534 // If R7 is the frame pointer, we must split at R7 to ensure that the535 // previous frame pointer (R7) and return address (LR) are adjacent on the536 // stack, to form a valid frame record.537 if (getFramePointerReg() == ARM::R7 &&538 MF.getTarget().Options.FramePointerIsReserved(MF))539 return SplitR7;540 541 // Returns SplitR11WindowsSEH when the stack pointer needs to be542 // restored from the frame pointer r11 + an offset and Windows CFI is enabled.543 // This stack unwinding cannot be expressed with SEH unwind opcodes when done544 // with a single push, making it necessary to split the push into r4-r10, and545 // another containing r11+lr.546 if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&547 F.needsUnwindTableEntry() &&548 (MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF)))549 return SplitR11WindowsSEH;550 551 // Returns SplitR11AAPCSSignRA when the frame pointer is R11, requiring R11552 // and LR to be adjacent on the stack, and branch signing is enabled,553 // requiring R12 to be on the stack.554 if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress() &&555 getFramePointerReg() == ARM::R11 &&556 MF.getTarget().Options.FramePointerIsReserved(MF))557 return SplitR11AAPCSSignRA;558 return NoSplit;559}560