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, const TargetOptions &Options) 79 : ARMGenSubtargetInfo(TT, CPU, FS) 80 , ARMProcFamily(Others) 81 , ARMProcClass(None) 82 , stackAlignment(4) 83 , CPUString(CPU) 84 , TargetTriple(TT) 85 , Options(Options) 86 , TargetABI(ARM_ABI_UNKNOWN) { 87 initializeEnvironment(); 88 resetSubtargetFeatures(CPU, FS); 89 } 90 91 void ARMSubtarget::initializeEnvironment() { 92 HasV4TOps = false; 93 HasV5TOps = false; 94 HasV5TEOps = false; 95 HasV6Ops = false; 96 HasV6MOps = false; 97 HasV6T2Ops = false; 98 HasV7Ops = false; 99 HasV8Ops = false; 100 HasVFPv2 = false; 101 HasVFPv3 = false; 102 HasVFPv4 = false; 103 HasFPARMv8 = false; 104 HasNEON = false; 105 MinSize = false; 106 UseNEONForSinglePrecisionFP = false; 107 UseMulOps = UseFusedMulOps; 108 SlowFPVMLx = false; 109 HasVMLxForwarding = false; 110 SlowFPBrcc = false; 111 InThumbMode = false; 112 HasThumb2 = false; 113 NoARM = false; 114 PostRAScheduler = false; 115 IsR9Reserved = ReserveR9; 116 UseMovt = false; 117 SupportsTailCall = false; 118 HasFP16 = false; 119 HasD16 = false; 120 HasHardwareDivide = false; 121 HasHardwareDivideInARM = false; 122 HasT2ExtractPack = false; 123 HasDataBarrier = false; 124 Pref32BitThumb = false; 125 AvoidCPSRPartialUpdate = false; 126 AvoidMOVsShifterOperand = false; 127 HasRAS = false; 128 HasMPExtension = false; 129 HasVirtualization = false; 130 FPOnlySP = false; 131 HasPerfMon = false; 132 HasTrustZone = false; 133 HasCrypto = false; 134 HasCRC = false; 135 AllowsUnalignedMem = false; 136 Thumb2DSP = false; 137 UseNaClTrap = false; 138 UnsafeFPMath = false; 139 } 140 141 void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { 142 AttributeSet FnAttrs = MF->getFunction()->getAttributes(); 143 Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 144 "target-cpu"); 145 Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 146 "target-features"); 147 std::string CPU = 148 !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; 149 std::string FS = 150 !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; 151 if (!FS.empty()) { 152 initializeEnvironment(); 153 resetSubtargetFeatures(CPU, FS); 154 } 155 156 MinSize = 157 FnAttrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize); 158 } 159 160 void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { 161 if (CPUString.empty()) { 162 if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s")) 163 // Default to the Swift CPU when targeting armv7s/thumbv7s. 164 CPUString = "swift"; 165 else 166 CPUString = "generic"; 167 } 168 169 // Insert the architecture feature derived from the target triple into the 170 // feature string. This is important for setting features that are implied 171 // based on the architecture version. 172 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 173 CPUString); 174 if (!FS.empty()) { 175 if (!ArchFS.empty()) 176 ArchFS = ArchFS + "," + FS.str(); 177 else 178 ArchFS = FS; 179 } 180 ParseSubtargetFeatures(CPUString, ArchFS); 181 182 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 183 // Assert this for now to make the change obvious. 184 assert(hasV6T2Ops() || !hasThumb2()); 185 186 // Keep a pointer to static instruction cost data for the specified CPU. 187 SchedModel = getSchedModelForCPU(CPUString); 188 189 // Initialize scheduling itinerary for the specified CPU. 190 InstrItins = getInstrItineraryForCPU(CPUString); 191 192 if (TargetABI == ARM_ABI_UNKNOWN) { 193 switch (TargetTriple.getEnvironment()) { 194 case Triple::Android: 195 case Triple::EABI: 196 case Triple::EABIHF: 197 case Triple::GNUEABI: 198 case Triple::GNUEABIHF: 199 case Triple::MachO: 200 TargetABI = ARM_ABI_AAPCS; 201 break; 202 default: 203 if (isTargetIOS() && isMClass()) 204 TargetABI = ARM_ABI_AAPCS; 205 else 206 TargetABI = ARM_ABI_APCS; 207 break; 208 } 209 } 210 211 if (isAAPCS_ABI()) 212 stackAlignment = 8; 213 214 UseMovt = hasV6T2Ops() && ArmUseMOVT; 215 216 if (isTargetMachO()) { 217 IsR9Reserved = ReserveR9 | !HasV6Ops; 218 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 219 } else 220 IsR9Reserved = ReserveR9; 221 222 if (!isThumb() || hasThumb2()) 223 PostRAScheduler = true; 224 225 switch (Align) { 226 case 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 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 (hasV6Ops() && isTargetMachO())); 243 break; 244 case StrictAlign: 245 AllowsUnalignedMem = false; 246 break; 247 case NoStrictAlign: 248 AllowsUnalignedMem = true; 249 break; 250 } 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 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 272 bool 273 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 274 Reloc::Model RelocM) const { 275 if (RelocM == Reloc::Static) 276 return false; 277 278 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 279 // load from stub. 280 bool isDecl = GV->hasAvailableExternallyLinkage(); 281 if (GV->isDeclaration() && !GV->isMaterializable()) 282 isDecl = true; 283 284 if (!isTargetMachO()) { 285 // Extra load is needed for all externally visible. 286 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 287 return false; 288 return true; 289 } else { 290 if (RelocM == Reloc::PIC_) { 291 // If this is a strong reference to a definition, it is definitely not 292 // through a stub. 293 if (!isDecl && !GV->isWeakForLinker()) 294 return false; 295 296 // Unless we have a symbol with hidden visibility, we have to go through a 297 // normal $non_lazy_ptr stub because this symbol might be resolved late. 298 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 299 return true; 300 301 // If symbol visibility is hidden, we have a stub for common symbol 302 // references and external declarations. 303 if (isDecl || GV->hasCommonLinkage()) 304 // Hidden $non_lazy_ptr reference. 305 return true; 306 307 return false; 308 } else { 309 // If this is a strong reference to a definition, it is definitely not 310 // through a stub. 311 if (!isDecl && !GV->isWeakForLinker()) 312 return false; 313 314 // Unless we have a symbol with hidden visibility, we have to go through a 315 // normal $non_lazy_ptr stub because this symbol might be resolved late. 316 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 317 return true; 318 } 319 } 320 321 return false; 322 } 323 324 unsigned ARMSubtarget::getMispredictionPenalty() const { 325 return SchedModel->MispredictPenalty; 326 } 327 328 bool ARMSubtarget::hasSinCos() const { 329 return getTargetTriple().getOS() == Triple::IOS && 330 !getTargetTriple().isOSVersionLT(7, 0); 331 } 332 333 bool ARMSubtarget::enablePostRAScheduler( 334 CodeGenOpt::Level OptLevel, 335 TargetSubtargetInfo::AntiDepBreakMode& Mode, 336 RegClassVector& CriticalPathRCs) const { 337 Mode = TargetSubtargetInfo::ANTIDEP_NONE; 338 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 339 } 340