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 "ARMMachineFunctionInfo.h" 19 #include "ARMSelectionDAGInfo.h" 20 #include "ARMSubtarget.h" 21 #include "ARMTargetMachine.h" 22 #include "Thumb1FrameLowering.h" 23 #include "Thumb1InstrInfo.h" 24 #include "Thumb2InstrInfo.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/IR/Attributes.h" 27 #include "llvm/IR/Function.h" 28 #include "llvm/IR/GlobalValue.h" 29 #include "llvm/Support/CommandLine.h" 30 #include "llvm/Target/TargetInstrInfo.h" 31 #include "llvm/Target/TargetOptions.h" 32 #include "llvm/Target/TargetRegisterInfo.h" 33 34 using namespace llvm; 35 36 #define DEBUG_TYPE "arm-subtarget" 37 38 #define GET_SUBTARGETINFO_TARGET_DESC 39 #define GET_SUBTARGETINFO_CTOR 40 #include "ARMGenSubtargetInfo.inc" 41 42 static cl::opt<bool> 43 ReserveR9("arm-reserve-r9", cl::Hidden, 44 cl::desc("Reserve R9, making it unavailable as GPR")); 45 46 static cl::opt<bool> 47 ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden); 48 49 static cl::opt<bool> 50 UseFusedMulOps("arm-use-mulops", 51 cl::init(true), cl::Hidden); 52 53 namespace { 54 enum AlignMode { 55 DefaultAlign, 56 StrictAlign, 57 NoStrictAlign 58 }; 59 } 60 61 static cl::opt<AlignMode> 62 Align(cl::desc("Load/store alignment support"), 63 cl::Hidden, cl::init(DefaultAlign), 64 cl::values( 65 clEnumValN(DefaultAlign, "arm-default-align", 66 "Generate unaligned accesses only on hardware/OS " 67 "combinations that are known to support them"), 68 clEnumValN(StrictAlign, "arm-strict-align", 69 "Disallow all unaligned memory accesses"), 70 clEnumValN(NoStrictAlign, "arm-no-strict-align", 71 "Allow unaligned memory accesses"), 72 clEnumValEnd)); 73 74 enum ITMode { 75 DefaultIT, 76 RestrictedIT, 77 NoRestrictedIT 78 }; 79 80 static cl::opt<ITMode> 81 IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), 82 cl::ZeroOrMore, 83 cl::values(clEnumValN(DefaultIT, "arm-default-it", 84 "Generate IT block based on arch"), 85 clEnumValN(RestrictedIT, "arm-restrict-it", 86 "Disallow deprecated IT based on ARMv8"), 87 clEnumValN(NoRestrictedIT, "arm-no-restrict-it", 88 "Allow IT blocks based on ARMv7"), 89 clEnumValEnd)); 90 91 /// initializeSubtargetDependencies - Initializes using a CPU and feature string 92 /// so that we can use initializer lists for subtarget initialization. 93 ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU, 94 StringRef FS) { 95 initializeEnvironment(); 96 initSubtargetFeatures(CPU, FS); 97 return *this; 98 } 99 100 ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU, 101 StringRef FS) { 102 ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS); 103 if (STI.isThumb1Only()) 104 return (ARMFrameLowering *)new Thumb1FrameLowering(STI); 105 106 return new ARMFrameLowering(STI); 107 } 108 109 ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, 110 const std::string &FS, 111 const ARMBaseTargetMachine &TM, bool IsLittle) 112 : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), 113 ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle), 114 TargetTriple(TT), Options(TM.Options), TM(TM), 115 TSInfo(*TM.getDataLayout()), 116 FrameLowering(initializeFrameLowering(CPU, FS)), 117 // At this point initializeSubtargetDependencies has been called so 118 // we can query directly. 119 InstrInfo(isThumb1Only() 120 ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this) 121 : !isThumb() 122 ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this) 123 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)), 124 TLInfo(TM, *this) {} 125 126 void ARMSubtarget::initializeEnvironment() { 127 HasV4TOps = false; 128 HasV5TOps = false; 129 HasV5TEOps = false; 130 HasV6Ops = false; 131 HasV6MOps = false; 132 HasV6KOps = false; 133 HasV6T2Ops = false; 134 HasV7Ops = false; 135 HasV8Ops = false; 136 HasV8_1aOps = false; 137 HasVFPv2 = false; 138 HasVFPv3 = false; 139 HasVFPv4 = false; 140 HasFPARMv8 = false; 141 HasNEON = false; 142 UseNEONForSinglePrecisionFP = false; 143 UseMulOps = UseFusedMulOps; 144 SlowFPVMLx = false; 145 HasVMLxForwarding = false; 146 SlowFPBrcc = false; 147 InThumbMode = false; 148 HasThumb2 = false; 149 NoARM = false; 150 IsR9Reserved = ReserveR9; 151 UseMovt = false; 152 SupportsTailCall = false; 153 HasFP16 = false; 154 HasD16 = false; 155 HasHardwareDivide = false; 156 HasHardwareDivideInARM = false; 157 HasT2ExtractPack = false; 158 HasDataBarrier = false; 159 Pref32BitThumb = false; 160 AvoidCPSRPartialUpdate = false; 161 AvoidMOVsShifterOperand = false; 162 HasRAS = false; 163 HasMPExtension = false; 164 HasVirtualization = false; 165 FPOnlySP = false; 166 HasPerfMon = false; 167 HasTrustZone = false; 168 HasCrypto = false; 169 HasCRC = false; 170 HasZeroCycleZeroing = false; 171 AllowsUnalignedMem = false; 172 Thumb2DSP = false; 173 UseNaClTrap = false; 174 UnsafeFPMath = false; 175 UseLong64 = false; 176 } 177 178 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { 179 if (CPUString.empty()) { 180 if (isTargetDarwin() && TargetTriple.getArchName().endswith("v7s")) 181 // Default to the Swift CPU when targeting armv7s/thumbv7s. 182 CPUString = "swift"; 183 else 184 CPUString = "generic"; 185 } 186 187 // Insert the architecture feature derived from the target triple into the 188 // feature string. This is important for setting features that are implied 189 // based on the architecture version. 190 std::string ArchFS = 191 ARM_MC::ParseARMTriple(TargetTriple.getTriple(), CPUString); 192 if (!FS.empty()) { 193 if (!ArchFS.empty()) 194 ArchFS = (Twine(ArchFS) + "," + FS).str(); 195 else 196 ArchFS = FS; 197 } 198 ParseSubtargetFeatures(CPUString, ArchFS); 199 200 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 201 // Assert this for now to make the change obvious. 202 assert(hasV6T2Ops() || !hasThumb2()); 203 204 // Keep a pointer to static instruction cost data for the specified CPU. 205 SchedModel = getSchedModelForCPU(CPUString); 206 207 // Initialize scheduling itinerary for the specified CPU. 208 InstrItins = getInstrItineraryForCPU(CPUString); 209 210 // FIXME: this is invalid for WindowsCE 211 if (isTargetWindows()) 212 NoARM = true; 213 214 if (isAAPCS_ABI()) 215 stackAlignment = 8; 216 if (isTargetNaCl()) 217 stackAlignment = 16; 218 219 UseMovt = hasV6T2Ops() && ArmUseMOVT; 220 221 if (isTargetMachO()) { 222 IsR9Reserved = ReserveR9 || !HasV6Ops; 223 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 224 } else { 225 IsR9Reserved = ReserveR9; 226 SupportsTailCall = !isThumb1Only(); 227 } 228 229 if (Align == DefaultAlign) { 230 // Assume pre-ARMv6 doesn't support unaligned accesses. 231 // 232 // ARMv6 may or may not support unaligned accesses depending on the 233 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 234 // Darwin and NetBSD targets support unaligned accesses, and others don't. 235 // 236 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 237 // which raises an alignment fault on unaligned accesses. Linux 238 // defaults this bit to 0 and handles it as a system-wide (not 239 // per-process) setting. It is therefore safe to assume that ARMv7+ 240 // Linux targets support unaligned accesses. The same goes for NaCl. 241 // 242 // The above behavior is consistent with GCC. 243 AllowsUnalignedMem = 244 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() || 245 isTargetNetBSD())) || 246 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD())); 247 } else { 248 AllowsUnalignedMem = !(Align == StrictAlign); 249 } 250 251 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2) 252 if (isV6M()) 253 AllowsUnalignedMem = false; 254 255 switch (IT) { 256 case DefaultIT: 257 RestrictIT = hasV8Ops(); 258 break; 259 case RestrictedIT: 260 RestrictIT = true; 261 break; 262 case NoRestrictedIT: 263 RestrictIT = false; 264 break; 265 } 266 267 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 268 uint64_t Bits = getFeatureBits(); 269 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 270 (Options.UnsafeFPMath || isTargetDarwin())) 271 UseNEONForSinglePrecisionFP = true; 272 } 273 274 bool ARMSubtarget::isAPCS_ABI() const { 275 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 276 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS; 277 } 278 bool ARMSubtarget::isAAPCS_ABI() const { 279 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 280 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS; 281 } 282 283 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 284 bool 285 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 286 Reloc::Model RelocM) const { 287 if (RelocM == Reloc::Static) 288 return false; 289 290 bool isDecl = GV->isDeclarationForLinker(); 291 292 if (!isTargetMachO()) { 293 // Extra load is needed for all externally visible. 294 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 295 return false; 296 return true; 297 } else { 298 if (RelocM == Reloc::PIC_) { 299 // If this is a strong reference to a definition, it is definitely not 300 // through a stub. 301 if (!isDecl && !GV->isWeakForLinker()) 302 return false; 303 304 // Unless we have a symbol with hidden visibility, we have to go through a 305 // normal $non_lazy_ptr stub because this symbol might be resolved late. 306 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 307 return true; 308 309 // If symbol visibility is hidden, we have a stub for common symbol 310 // references and external declarations. 311 if (isDecl || GV->hasCommonLinkage()) 312 // Hidden $non_lazy_ptr reference. 313 return true; 314 315 return false; 316 } else { 317 // If this is a strong reference to a definition, it is definitely not 318 // through a stub. 319 if (!isDecl && !GV->isWeakForLinker()) 320 return false; 321 322 // Unless we have a symbol with hidden visibility, we have to go through a 323 // normal $non_lazy_ptr stub because this symbol might be resolved late. 324 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 325 return true; 326 } 327 } 328 329 return false; 330 } 331 332 unsigned ARMSubtarget::getMispredictionPenalty() const { 333 return SchedModel.MispredictPenalty; 334 } 335 336 bool ARMSubtarget::hasSinCos() const { 337 return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0); 338 } 339 340 // This overrides the PostRAScheduler bit in the SchedModel for any CPU. 341 bool ARMSubtarget::enablePostMachineScheduler() const { 342 return (!isThumb() || hasThumb2()); 343 } 344 345 bool ARMSubtarget::enableAtomicExpand() const { 346 return hasAnyDataBarrier() && !isThumb1Only(); 347 } 348 349 bool ARMSubtarget::useMovt(const MachineFunction &MF) const { 350 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit 351 // immediates as it is inherently position independent, and may be out of 352 // range otherwise. 353 return UseMovt && (isTargetWindows() || 354 !MF.getFunction()->hasFnAttribute(Attribute::MinSize)); 355 } 356