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 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 224 if (!isThumb() || hasThumb2()) 225 PostRAScheduler = true; 226 227 switch (Align) { 228 case 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 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 break; 247 case StrictAlign: 248 AllowsUnalignedMem = false; 249 break; 250 case NoStrictAlign: 251 AllowsUnalignedMem = true; 252 break; 253 } 254 255 switch (IT) { 256 case DefaultIT: 257 RestrictIT = hasV8Ops() ? true : false; 258 break; 259 case RestrictedIT: 260 RestrictIT = true; 261 break; 262 case NoRestrictedIT: 263 RestrictIT = false; 264 break; 265 } 266 267 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 268 uint64_t Bits = getFeatureBits(); 269 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 270 (Options.UnsafeFPMath || isTargetDarwin())) 271 UseNEONForSinglePrecisionFP = true; 272 } 273 274 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 275 bool 276 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 277 Reloc::Model RelocM) const { 278 if (RelocM == Reloc::Static) 279 return false; 280 281 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 282 // load from stub. 283 bool isDecl = GV->hasAvailableExternallyLinkage(); 284 if (GV->isDeclaration() && !GV->isMaterializable()) 285 isDecl = true; 286 287 if (!isTargetMachO()) { 288 // Extra load is needed for all externally visible. 289 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 290 return false; 291 return true; 292 } else { 293 if (RelocM == Reloc::PIC_) { 294 // If this is a strong reference to a definition, it is definitely not 295 // through a stub. 296 if (!isDecl && !GV->isWeakForLinker()) 297 return false; 298 299 // Unless we have a symbol with hidden visibility, we have to go through a 300 // normal $non_lazy_ptr stub because this symbol might be resolved late. 301 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 302 return true; 303 304 // If symbol visibility is hidden, we have a stub for common symbol 305 // references and external declarations. 306 if (isDecl || GV->hasCommonLinkage()) 307 // Hidden $non_lazy_ptr reference. 308 return true; 309 310 return false; 311 } else { 312 // If this is a strong reference to a definition, it is definitely not 313 // through a stub. 314 if (!isDecl && !GV->isWeakForLinker()) 315 return false; 316 317 // Unless we have a symbol with hidden visibility, we have to go through a 318 // normal $non_lazy_ptr stub because this symbol might be resolved late. 319 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 320 return true; 321 } 322 } 323 324 return false; 325 } 326 327 unsigned ARMSubtarget::getMispredictionPenalty() const { 328 return SchedModel->MispredictPenalty; 329 } 330 331 bool ARMSubtarget::hasSinCos() const { 332 return getTargetTriple().getOS() == Triple::IOS && 333 !getTargetTriple().isOSVersionLT(7, 0); 334 } 335 336 bool ARMSubtarget::enablePostRAScheduler( 337 CodeGenOpt::Level OptLevel, 338 TargetSubtargetInfo::AntiDepBreakMode& Mode, 339 RegClassVector& CriticalPathRCs) const { 340 Mode = TargetSubtargetInfo::ANTIDEP_NONE; 341 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 342 } 343