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