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 } 176 177 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { 178 if (CPUString.empty()) { 179 if (isTargetDarwin() && TargetTriple.getArchName().endswith("v7s")) 180 // Default to the Swift CPU when targeting armv7s/thumbv7s. 181 CPUString = "swift"; 182 else 183 CPUString = "generic"; 184 } 185 186 // Insert the architecture feature derived from the target triple into the 187 // feature string. This is important for setting features that are implied 188 // based on the architecture version. 189 std::string ArchFS = 190 ARM_MC::ParseARMTriple(TargetTriple.getTriple(), CPUString); 191 if (!FS.empty()) { 192 if (!ArchFS.empty()) 193 ArchFS = (Twine(ArchFS) + "," + FS).str(); 194 else 195 ArchFS = FS; 196 } 197 ParseSubtargetFeatures(CPUString, ArchFS); 198 199 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 200 // Assert this for now to make the change obvious. 201 assert(hasV6T2Ops() || !hasThumb2()); 202 203 // Keep a pointer to static instruction cost data for the specified CPU. 204 SchedModel = getSchedModelForCPU(CPUString); 205 206 // Initialize scheduling itinerary for the specified CPU. 207 InstrItins = getInstrItineraryForCPU(CPUString); 208 209 // FIXME: this is invalid for WindowsCE 210 if (isTargetWindows()) 211 NoARM = true; 212 213 if (isAAPCS_ABI()) 214 stackAlignment = 8; 215 if (isTargetNaCl()) 216 stackAlignment = 16; 217 218 UseMovt = hasV6T2Ops() && ArmUseMOVT; 219 220 if (isTargetMachO()) { 221 IsR9Reserved = ReserveR9 || !HasV6Ops; 222 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 223 } else { 224 IsR9Reserved = ReserveR9; 225 SupportsTailCall = !isThumb1Only(); 226 } 227 228 if (Align == DefaultAlign) { 229 // Assume pre-ARMv6 doesn't support unaligned accesses. 230 // 231 // ARMv6 may or may not support unaligned accesses depending on the 232 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 233 // Darwin and NetBSD targets support unaligned accesses, and others don't. 234 // 235 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 236 // which raises an alignment fault on unaligned accesses. Linux 237 // defaults this bit to 0 and handles it as a system-wide (not 238 // per-process) setting. It is therefore safe to assume that ARMv7+ 239 // Linux targets support unaligned accesses. The same goes for NaCl. 240 // 241 // The above behavior is consistent with GCC. 242 AllowsUnalignedMem = 243 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() || 244 isTargetNetBSD())) || 245 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD())); 246 } else { 247 AllowsUnalignedMem = !(Align == StrictAlign); 248 } 249 250 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2) 251 if (isV6M()) 252 AllowsUnalignedMem = false; 253 254 switch (IT) { 255 case DefaultIT: 256 RestrictIT = hasV8Ops(); 257 break; 258 case RestrictedIT: 259 RestrictIT = true; 260 break; 261 case NoRestrictedIT: 262 RestrictIT = false; 263 break; 264 } 265 266 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 267 uint64_t Bits = getFeatureBits(); 268 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 269 (Options.UnsafeFPMath || isTargetDarwin())) 270 UseNEONForSinglePrecisionFP = true; 271 } 272 273 bool ARMSubtarget::isAPCS_ABI() const { 274 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 275 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS; 276 } 277 bool ARMSubtarget::isAAPCS_ABI() const { 278 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 279 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS; 280 } 281 282 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 283 bool 284 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 285 Reloc::Model RelocM) const { 286 if (RelocM == Reloc::Static) 287 return false; 288 289 bool isDecl = GV->isDeclarationForLinker(); 290 291 if (!isTargetMachO()) { 292 // Extra load is needed for all externally visible. 293 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 294 return false; 295 return true; 296 } else { 297 if (RelocM == Reloc::PIC_) { 298 // If this is a strong reference to a definition, it is definitely not 299 // through a stub. 300 if (!isDecl && !GV->isWeakForLinker()) 301 return false; 302 303 // Unless we have a symbol with hidden visibility, we have to go through a 304 // normal $non_lazy_ptr stub because this symbol might be resolved late. 305 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 306 return true; 307 308 // If symbol visibility is hidden, we have a stub for common symbol 309 // references and external declarations. 310 if (isDecl || GV->hasCommonLinkage()) 311 // Hidden $non_lazy_ptr reference. 312 return true; 313 314 return false; 315 } else { 316 // If this is a strong reference to a definition, it is definitely not 317 // through a stub. 318 if (!isDecl && !GV->isWeakForLinker()) 319 return false; 320 321 // Unless we have a symbol with hidden visibility, we have to go through a 322 // normal $non_lazy_ptr stub because this symbol might be resolved late. 323 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 324 return true; 325 } 326 } 327 328 return false; 329 } 330 331 unsigned ARMSubtarget::getMispredictionPenalty() const { 332 return SchedModel.MispredictPenalty; 333 } 334 335 bool ARMSubtarget::hasSinCos() const { 336 return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0); 337 } 338 339 // This overrides the PostRAScheduler bit in the SchedModel for any CPU. 340 bool ARMSubtarget::enablePostMachineScheduler() const { 341 return (!isThumb() || hasThumb2()); 342 } 343 344 bool ARMSubtarget::enableAtomicExpand() const { 345 return hasAnyDataBarrier() && !isThumb1Only(); 346 } 347 348 bool ARMSubtarget::useMovt(const MachineFunction &MF) const { 349 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit 350 // immediates as it is inherently position independent, and may be out of 351 // range otherwise. 352 return UseMovt && (isTargetWindows() || 353 !MF.getFunction()->hasFnAttribute(Attribute::MinSize)); 354 } 355