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