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