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 ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, 80 const std::string &FS, bool IsLittle, 81 const TargetOptions &Options) 82 : ARMGenSubtargetInfo(TT, CPU, FS) 83 , ARMProcFamily(Others) 84 , ARMProcClass(None) 85 , stackAlignment(4) 86 , CPUString(CPU) 87 , IsLittle(IsLittle) 88 , TargetTriple(TT) 89 , Options(Options) 90 , TargetABI(ARM_ABI_UNKNOWN) { 91 initializeEnvironment(); 92 resetSubtargetFeatures(CPU, FS); 93 } 94 95 void ARMSubtarget::initializeEnvironment() { 96 HasV4TOps = false; 97 HasV5TOps = false; 98 HasV5TEOps = false; 99 HasV6Ops = false; 100 HasV6MOps = false; 101 HasV6T2Ops = false; 102 HasV7Ops = false; 103 HasV8Ops = false; 104 HasVFPv2 = false; 105 HasVFPv3 = false; 106 HasVFPv4 = false; 107 HasFPARMv8 = false; 108 HasNEON = false; 109 MinSize = false; 110 UseNEONForSinglePrecisionFP = false; 111 UseMulOps = UseFusedMulOps; 112 SlowFPVMLx = false; 113 HasVMLxForwarding = false; 114 SlowFPBrcc = false; 115 InThumbMode = false; 116 HasThumb2 = false; 117 NoARM = false; 118 PostRAScheduler = false; 119 IsR9Reserved = ReserveR9; 120 UseMovt = false; 121 SupportsTailCall = false; 122 HasFP16 = false; 123 HasD16 = false; 124 HasHardwareDivide = false; 125 HasHardwareDivideInARM = false; 126 HasT2ExtractPack = false; 127 HasDataBarrier = false; 128 Pref32BitThumb = false; 129 AvoidCPSRPartialUpdate = false; 130 AvoidMOVsShifterOperand = false; 131 HasRAS = false; 132 HasMPExtension = false; 133 HasVirtualization = false; 134 FPOnlySP = false; 135 HasPerfMon = false; 136 HasTrustZone = false; 137 HasCrypto = false; 138 HasCRC = false; 139 HasZeroCycleZeroing = false; 140 AllowsUnalignedMem = false; 141 Thumb2DSP = false; 142 UseNaClTrap = false; 143 UnsafeFPMath = false; 144 } 145 146 void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { 147 AttributeSet FnAttrs = MF->getFunction()->getAttributes(); 148 Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 149 "target-cpu"); 150 Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 151 "target-features"); 152 std::string CPU = 153 !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; 154 std::string FS = 155 !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; 156 if (!FS.empty()) { 157 initializeEnvironment(); 158 resetSubtargetFeatures(CPU, FS); 159 } 160 161 MinSize = 162 FnAttrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize); 163 } 164 165 void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { 166 if (CPUString.empty()) { 167 if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s")) 168 // Default to the Swift CPU when targeting armv7s/thumbv7s. 169 CPUString = "swift"; 170 else 171 CPUString = "generic"; 172 } 173 174 // Insert the architecture feature derived from the target triple into the 175 // feature string. This is important for setting features that are implied 176 // based on the architecture version. 177 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 178 CPUString); 179 if (!FS.empty()) { 180 if (!ArchFS.empty()) 181 ArchFS = ArchFS + "," + FS.str(); 182 else 183 ArchFS = FS; 184 } 185 ParseSubtargetFeatures(CPUString, ArchFS); 186 187 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 188 // Assert this for now to make the change obvious. 189 assert(hasV6T2Ops() || !hasThumb2()); 190 191 // Keep a pointer to static instruction cost data for the specified CPU. 192 SchedModel = getSchedModelForCPU(CPUString); 193 194 // Initialize scheduling itinerary for the specified CPU. 195 InstrItins = getInstrItineraryForCPU(CPUString); 196 197 if (TargetABI == ARM_ABI_UNKNOWN) { 198 switch (TargetTriple.getEnvironment()) { 199 case Triple::Android: 200 case Triple::EABI: 201 case Triple::EABIHF: 202 case Triple::GNUEABI: 203 case Triple::GNUEABIHF: 204 TargetABI = ARM_ABI_AAPCS; 205 break; 206 default: 207 if ((isTargetIOS() && isMClass()) || 208 (TargetTriple.isOSBinFormatMachO() && 209 TargetTriple.getOS() == Triple::UnknownOS)) 210 TargetABI = ARM_ABI_AAPCS; 211 else 212 TargetABI = ARM_ABI_APCS; 213 break; 214 } 215 } 216 217 // FIXME: this is invalid for WindowsCE 218 if (isTargetWindows()) { 219 TargetABI = ARM_ABI_AAPCS; 220 NoARM = true; 221 } 222 223 if (isAAPCS_ABI()) 224 stackAlignment = 8; 225 if (isTargetNaCl()) 226 stackAlignment = 16; 227 228 UseMovt = hasV6T2Ops() && ArmUseMOVT; 229 230 if (isTargetMachO()) { 231 IsR9Reserved = ReserveR9 | !HasV6Ops; 232 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 233 } else { 234 IsR9Reserved = ReserveR9; 235 SupportsTailCall = !isThumb1Only(); 236 } 237 238 if (!isThumb() || hasThumb2()) 239 PostRAScheduler = true; 240 241 switch (Align) { 242 case DefaultAlign: 243 // Assume pre-ARMv6 doesn't support unaligned accesses. 244 // 245 // ARMv6 may or may not support unaligned accesses depending on the 246 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 247 // Darwin and NetBSD targets support unaligned accesses, and others don't. 248 // 249 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 250 // which raises an alignment fault on unaligned accesses. Linux 251 // defaults this bit to 0 and handles it as a system-wide (not 252 // per-process) setting. It is therefore safe to assume that ARMv7+ 253 // Linux targets support unaligned accesses. The same goes for NaCl. 254 // 255 // The above behavior is consistent with GCC. 256 AllowsUnalignedMem = 257 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() || 258 isTargetNetBSD())) || 259 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD())); 260 // The one exception is cortex-m0, which despite being v6, does not 261 // support unaligned accesses. Rather than make the above boolean 262 // expression even more obtuse, just override the value here. 263 if (isThumb1Only() && isMClass()) 264 AllowsUnalignedMem = false; 265 break; 266 case StrictAlign: 267 AllowsUnalignedMem = false; 268 break; 269 case NoStrictAlign: 270 AllowsUnalignedMem = true; 271 break; 272 } 273 274 switch (IT) { 275 case DefaultIT: 276 RestrictIT = hasV8Ops() ? true : false; 277 break; 278 case RestrictedIT: 279 RestrictIT = true; 280 break; 281 case NoRestrictedIT: 282 RestrictIT = false; 283 break; 284 } 285 286 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 287 uint64_t Bits = getFeatureBits(); 288 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 289 (Options.UnsafeFPMath || isTargetDarwin())) 290 UseNEONForSinglePrecisionFP = true; 291 } 292 293 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 294 bool 295 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 296 Reloc::Model RelocM) const { 297 if (RelocM == Reloc::Static) 298 return false; 299 300 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 301 // load from stub. 302 bool isDecl = GV->hasAvailableExternallyLinkage(); 303 if (GV->isDeclaration() && !GV->isMaterializable()) 304 isDecl = true; 305 306 if (!isTargetMachO()) { 307 // Extra load is needed for all externally visible. 308 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 309 return false; 310 return true; 311 } else { 312 if (RelocM == Reloc::PIC_) { 313 // If this is a strong reference to a definition, it is definitely not 314 // through a stub. 315 if (!isDecl && !GV->isWeakForLinker()) 316 return false; 317 318 // Unless we have a symbol with hidden visibility, we have to go through a 319 // normal $non_lazy_ptr stub because this symbol might be resolved late. 320 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 321 return true; 322 323 // If symbol visibility is hidden, we have a stub for common symbol 324 // references and external declarations. 325 if (isDecl || GV->hasCommonLinkage()) 326 // Hidden $non_lazy_ptr reference. 327 return true; 328 329 return false; 330 } else { 331 // If this is a strong reference to a definition, it is definitely not 332 // through a stub. 333 if (!isDecl && !GV->isWeakForLinker()) 334 return false; 335 336 // Unless we have a symbol with hidden visibility, we have to go through a 337 // normal $non_lazy_ptr stub because this symbol might be resolved late. 338 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 339 return true; 340 } 341 } 342 343 return false; 344 } 345 346 unsigned ARMSubtarget::getMispredictionPenalty() const { 347 return SchedModel->MispredictPenalty; 348 } 349 350 bool ARMSubtarget::hasSinCos() const { 351 return getTargetTriple().getOS() == Triple::IOS && 352 !getTargetTriple().isOSVersionLT(7, 0); 353 } 354 355 bool ARMSubtarget::enablePostRAScheduler( 356 CodeGenOpt::Level OptLevel, 357 TargetSubtargetInfo::AntiDepBreakMode& Mode, 358 RegClassVector& CriticalPathRCs) const { 359 Mode = TargetSubtargetInfo::ANTIDEP_NONE; 360 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 361 } 362