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 "ARMSubtarget.h" 15#include "ARMFrameLowering.h" 16#include "ARMISelLowering.h" 17#include "ARMInstrInfo.h" 18#include "ARMJITInfo.h" 19#include "ARMSelectionDAGInfo.h" 20#include "ARMSubtarget.h" 21#include "Thumb1FrameLowering.h" 22#include "Thumb1InstrInfo.h" 23#include "Thumb2InstrInfo.h" 24#include "llvm/IR/Attributes.h" 25#include "llvm/IR/Function.h" 26#include "llvm/IR/GlobalValue.h" 27#include "llvm/Support/CommandLine.h" 28#include "llvm/Target/TargetInstrInfo.h" 29#include "llvm/Target/TargetOptions.h" 30 31using namespace llvm; 32 33#define DEBUG_TYPE "arm-subtarget" 34 35#define GET_SUBTARGETINFO_TARGET_DESC 36#define GET_SUBTARGETINFO_CTOR 37#include "ARMGenSubtargetInfo.inc" 38 39static cl::opt<bool> 40ReserveR9("arm-reserve-r9", cl::Hidden, 41 cl::desc("Reserve R9, making it unavailable as GPR")); 42 43static cl::opt<bool> 44ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden); 45 46static cl::opt<bool> 47UseFusedMulOps("arm-use-mulops", 48 cl::init(true), cl::Hidden); 49 50enum AlignMode { 51 DefaultAlign, 52 StrictAlign, 53 NoStrictAlign 54}; 55 56static cl::opt<AlignMode> 57Align(cl::desc("Load/store alignment support"), 58 cl::Hidden, cl::init(DefaultAlign), 59 cl::values( 60 clEnumValN(DefaultAlign, "arm-default-align", 61 "Generate unaligned accesses only on hardware/OS " 62 "combinations that are known to support them"), 63 clEnumValN(StrictAlign, "arm-strict-align", 64 "Disallow all unaligned memory accesses"), 65 clEnumValN(NoStrictAlign, "arm-no-strict-align", 66 "Allow unaligned memory accesses"), 67 clEnumValEnd)); 68 69enum ITMode { 70 DefaultIT, 71 RestrictedIT, 72 NoRestrictedIT 73}; 74 75static cl::opt<ITMode> 76IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), 77 cl::ZeroOrMore, 78 cl::values(clEnumValN(DefaultIT, "arm-default-it", 79 "Generate IT block based on arch"), 80 clEnumValN(RestrictedIT, "arm-restrict-it", 81 "Disallow deprecated IT based on ARMv8"), 82 clEnumValN(NoRestrictedIT, "arm-no-restrict-it", 83 "Allow IT blocks based on ARMv7"), 84 clEnumValEnd)); 85 86static std::string computeDataLayout(ARMSubtarget &ST) { 87 std::string Ret = ""; 88 89 if (ST.isLittle()) 90 // Little endian. 91 Ret += "e"; 92 else 93 // Big endian. 94 Ret += "E"; 95 96 Ret += DataLayout::getManglingComponent(ST.getTargetTriple()); 97 98 // Pointers are 32 bits and aligned to 32 bits. 99 Ret += "-p:32:32"; 100 101 // On thumb, i16,i18 and i1 have natural aligment requirements, but we try to 102 // align to 32. 103 if (ST.isThumb()) 104 Ret += "-i1:8:32-i8:8:32-i16:16:32"; 105 106 // ABIs other than APCS have 64 bit integers with natural alignment. 107 if (!ST.isAPCS_ABI()) 108 Ret += "-i64:64"; 109 110 // We have 64 bits floats. The APCS ABI requires them to be aligned to 32 111 // bits, others to 64 bits. We always try to align to 64 bits. 112 if (ST.isAPCS_ABI()) 113 Ret += "-f64:32:64"; 114 115 // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others 116 // to 64. We always ty to give them natural alignment. 117 if (ST.isAPCS_ABI()) 118 Ret += "-v64:32:64-v128:32:128"; 119 else 120 Ret += "-v128:64:128"; 121 122 // On thumb and APCS, only try to align aggregates to 32 bits (the default is 123 // 64 bits). 124 if (ST.isThumb() || ST.isAPCS_ABI()) 125 Ret += "-a:0:32"; 126 127 // Integer registers are 32 bits. 128 Ret += "-n32"; 129 130 // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit 131 // aligned everywhere else. 132 if (ST.isTargetNaCl()) 133 Ret += "-S128"; 134 else if (ST.isAAPCS_ABI()) 135 Ret += "-S64"; 136 else 137 Ret += "-S32"; 138 139 return Ret; 140} 141 142/// initializeSubtargetDependencies - Initializes using a CPU and feature string 143/// so that we can use initializer lists for subtarget initialization. 144ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU, 145 StringRef FS) { 146 initializeEnvironment(); 147 resetSubtargetFeatures(CPU, FS); 148 return *this; 149} 150 151ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, 152 const std::string &FS, TargetMachine &TM, 153 bool IsLittle, const TargetOptions &Options) 154 : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), 155 ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle), 156 TargetTriple(TT), Options(Options), TargetABI(ARM_ABI_UNKNOWN), 157 DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS))), 158 TSInfo(DL), JITInfo(), 159 InstrInfo(isThumb1Only() 160 ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this) 161 : !isThumb() 162 ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this) 163 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)), 164 TLInfo(TM), 165 FrameLowering(!isThumb1Only() 166 ? new ARMFrameLowering(*this) 167 : (ARMFrameLowering *)new Thumb1FrameLowering(*this)) {} 168 169void ARMSubtarget::initializeEnvironment() { 170 HasV4TOps = false; 171 HasV5TOps = false; 172 HasV5TEOps = false; 173 HasV6Ops = false; 174 HasV6MOps = false; 175 HasV6T2Ops = false; 176 HasV7Ops = false; 177 HasV8Ops = false; 178 HasVFPv2 = false; 179 HasVFPv3 = false; 180 HasVFPv4 = false; 181 HasFPARMv8 = false; 182 HasNEON = false; 183 UseNEONForSinglePrecisionFP = false; 184 UseMulOps = UseFusedMulOps; 185 SlowFPVMLx = false; 186 HasVMLxForwarding = false; 187 SlowFPBrcc = false; 188 InThumbMode = false; 189 HasThumb2 = false; 190 NoARM = false; 191 PostRAScheduler = false; 192 IsR9Reserved = ReserveR9; 193 UseMovt = false; 194 SupportsTailCall = false; 195 HasFP16 = false; 196 HasD16 = false; 197 HasHardwareDivide = false; 198 HasHardwareDivideInARM = false; 199 HasT2ExtractPack = false; 200 HasDataBarrier = false; 201 Pref32BitThumb = false; 202 AvoidCPSRPartialUpdate = false; 203 AvoidMOVsShifterOperand = false; 204 HasRAS = false; 205 HasMPExtension = false; 206 HasVirtualization = false; 207 FPOnlySP = false; 208 HasPerfMon = false; 209 HasTrustZone = false; 210 HasCrypto = false; 211 HasCRC = false; 212 HasZeroCycleZeroing = false; 213 AllowsUnalignedMem = false; 214 Thumb2DSP = false; 215 UseNaClTrap = false; 216 UnsafeFPMath = false; 217 UseLong64 = false; 218} 219 220void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { 221 AttributeSet FnAttrs = MF->getFunction()->getAttributes(); 222 Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 223 "target-cpu"); 224 Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 225 "target-features"); 226 std::string CPU = 227 !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; 228 std::string FS = 229 !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; 230 if (!FS.empty()) { 231 initializeEnvironment(); 232 resetSubtargetFeatures(CPU, FS); 233 } 234} 235 236void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { 237 if (CPUString.empty()) { 238 if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s")) 239 // Default to the Swift CPU when targeting armv7s/thumbv7s. 240 CPUString = "swift"; 241 else 242 CPUString = "generic"; 243 } 244 245 // Insert the architecture feature derived from the target triple into the 246 // feature string. This is important for setting features that are implied 247 // based on the architecture version. 248 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 249 CPUString); 250 if (!FS.empty()) { 251 if (!ArchFS.empty()) 252 ArchFS = ArchFS + "," + FS.str(); 253 else 254 ArchFS = FS; 255 } 256 ParseSubtargetFeatures(CPUString, ArchFS); 257 258 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 259 // Assert this for now to make the change obvious. 260 assert(hasV6T2Ops() || !hasThumb2()); 261 262 // Keep a pointer to static instruction cost data for the specified CPU. 263 SchedModel = getSchedModelForCPU(CPUString); 264 265 // Initialize scheduling itinerary for the specified CPU. 266 InstrItins = getInstrItineraryForCPU(CPUString); 267 268 if (TargetABI == ARM_ABI_UNKNOWN) { 269 switch (TargetTriple.getEnvironment()) { 270 case Triple::Android: 271 case Triple::EABI: 272 case Triple::EABIHF: 273 case Triple::GNUEABI: 274 case Triple::GNUEABIHF: 275 TargetABI = ARM_ABI_AAPCS; 276 break; 277 default: 278 if ((isTargetIOS() && isMClass()) || 279 (TargetTriple.isOSBinFormatMachO() && 280 TargetTriple.getOS() == Triple::UnknownOS)) 281 TargetABI = ARM_ABI_AAPCS; 282 else 283 TargetABI = ARM_ABI_APCS; 284 break; 285 } 286 } 287 288 // FIXME: this is invalid for WindowsCE 289 if (isTargetWindows()) { 290 TargetABI = ARM_ABI_AAPCS; 291 NoARM = true; 292 } 293 294 if (isAAPCS_ABI()) 295 stackAlignment = 8; 296 if (isTargetNaCl()) 297 stackAlignment = 16; 298 299 UseMovt = hasV6T2Ops() && ArmUseMOVT; 300 301 if (isTargetMachO()) { 302 IsR9Reserved = ReserveR9 | !HasV6Ops; 303 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 304 } else { 305 IsR9Reserved = ReserveR9; 306 SupportsTailCall = !isThumb1Only(); 307 } 308 309 if (!isThumb() || hasThumb2()) 310 PostRAScheduler = true; 311 312 switch (Align) { 313 case DefaultAlign: 314 // Assume pre-ARMv6 doesn't support unaligned accesses. 315 // 316 // ARMv6 may or may not support unaligned accesses depending on the 317 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 318 // Darwin and NetBSD targets support unaligned accesses, and others don't. 319 // 320 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 321 // which raises an alignment fault on unaligned accesses. Linux 322 // defaults this bit to 0 and handles it as a system-wide (not 323 // per-process) setting. It is therefore safe to assume that ARMv7+ 324 // Linux targets support unaligned accesses. The same goes for NaCl. 325 // 326 // The above behavior is consistent with GCC. 327 AllowsUnalignedMem = 328 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() || 329 isTargetNetBSD())) || 330 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD())); 331 // The one exception is cortex-m0, which despite being v6, does not 332 // support unaligned accesses. Rather than make the above boolean 333 // expression even more obtuse, just override the value here. 334 if (isThumb1Only() && isMClass()) 335 AllowsUnalignedMem = false; 336 break; 337 case StrictAlign: 338 AllowsUnalignedMem = false; 339 break; 340 case NoStrictAlign: 341 AllowsUnalignedMem = true; 342 break; 343 } 344 345 switch (IT) { 346 case DefaultIT: 347 RestrictIT = hasV8Ops() ? true : false; 348 break; 349 case RestrictedIT: 350 RestrictIT = true; 351 break; 352 case NoRestrictedIT: 353 RestrictIT = false; 354 break; 355 } 356 357 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 358 uint64_t Bits = getFeatureBits(); 359 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 360 (Options.UnsafeFPMath || isTargetDarwin())) 361 UseNEONForSinglePrecisionFP = true; 362} 363 364/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 365bool 366ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 367 Reloc::Model RelocM) const { 368 if (RelocM == Reloc::Static) 369 return false; 370 371 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 372 // load from stub. 373 bool isDecl = GV->hasAvailableExternallyLinkage(); 374 if (GV->isDeclaration() && !GV->isMaterializable()) 375 isDecl = true; 376 377 if (!isTargetMachO()) { 378 // Extra load is needed for all externally visible. 379 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 380 return false; 381 return true; 382 } else { 383 if (RelocM == Reloc::PIC_) { 384 // If this is a strong reference to a definition, it is definitely not 385 // through a stub. 386 if (!isDecl && !GV->isWeakForLinker()) 387 return false; 388 389 // Unless we have a symbol with hidden visibility, we have to go through a 390 // normal $non_lazy_ptr stub because this symbol might be resolved late. 391 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 392 return true; 393 394 // If symbol visibility is hidden, we have a stub for common symbol 395 // references and external declarations. 396 if (isDecl || GV->hasCommonLinkage()) 397 // Hidden $non_lazy_ptr reference. 398 return true; 399 400 return false; 401 } else { 402 // If this is a strong reference to a definition, it is definitely not 403 // through a stub. 404 if (!isDecl && !GV->isWeakForLinker()) 405 return false; 406 407 // Unless we have a symbol with hidden visibility, we have to go through a 408 // normal $non_lazy_ptr stub because this symbol might be resolved late. 409 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 410 return true; 411 } 412 } 413 414 return false; 415} 416 417unsigned ARMSubtarget::getMispredictionPenalty() const { 418 return SchedModel->MispredictPenalty; 419} 420 421bool ARMSubtarget::hasSinCos() const { 422 return getTargetTriple().getOS() == Triple::IOS && 423 !getTargetTriple().isOSVersionLT(7, 0); 424} 425 426// Enable the PostMachineScheduler if the target selects it instead of 427// PostRAScheduler. Currently only available on the command line via 428// -misched-postra. 429bool ARMSubtarget::enablePostMachineScheduler() const { 430 return PostRAScheduler; 431} 432 433bool ARMSubtarget::enableAtomicExpandLoadLinked() const { 434 return hasAnyDataBarrier() && !isThumb1Only(); 435} 436 437bool ARMSubtarget::enablePostRAScheduler( 438 CodeGenOpt::Level OptLevel, 439 TargetSubtargetInfo::AntiDepBreakMode& Mode, 440 RegClassVector& CriticalPathRCs) const { 441 Mode = TargetSubtargetInfo::ANTIDEP_NONE; 442 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 443} 444 445bool ARMSubtarget::useMovt(const MachineFunction &MF) const { 446 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit 447 // immediates as it is inherently position independent, and may be out of 448 // range otherwise. 449 return UseMovt && (isTargetWindows() || 450 !MF.getFunction()->getAttributes().hasAttribute( 451 AttributeSet::FunctionIndex, Attribute::MinSize)); 452} 453