LLVM API Documentation
00001 //===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the ARM specific subclass of TargetSubtargetInfo. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "ARMSubtarget.h" 00015 #include "ARMFrameLowering.h" 00016 #include "ARMISelLowering.h" 00017 #include "ARMInstrInfo.h" 00018 #include "ARMSelectionDAGInfo.h" 00019 #include "ARMSubtarget.h" 00020 #include "ARMMachineFunctionInfo.h" 00021 #include "Thumb1FrameLowering.h" 00022 #include "Thumb1InstrInfo.h" 00023 #include "Thumb2InstrInfo.h" 00024 #include "llvm/IR/Attributes.h" 00025 #include "llvm/IR/Function.h" 00026 #include "llvm/IR/GlobalValue.h" 00027 #include "llvm/Support/CommandLine.h" 00028 #include "llvm/Target/TargetInstrInfo.h" 00029 #include "llvm/Target/TargetOptions.h" 00030 #include "llvm/Target/TargetRegisterInfo.h" 00031 #include "llvm/CodeGen/MachineRegisterInfo.h" 00032 00033 using namespace llvm; 00034 00035 #define DEBUG_TYPE "arm-subtarget" 00036 00037 #define GET_SUBTARGETINFO_TARGET_DESC 00038 #define GET_SUBTARGETINFO_CTOR 00039 #include "ARMGenSubtargetInfo.inc" 00040 00041 static cl::opt<bool> 00042 ReserveR9("arm-reserve-r9", cl::Hidden, 00043 cl::desc("Reserve R9, making it unavailable as GPR")); 00044 00045 static cl::opt<bool> 00046 ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden); 00047 00048 static cl::opt<bool> 00049 UseFusedMulOps("arm-use-mulops", 00050 cl::init(true), cl::Hidden); 00051 00052 namespace { 00053 enum AlignMode { 00054 DefaultAlign, 00055 StrictAlign, 00056 NoStrictAlign 00057 }; 00058 } 00059 00060 static cl::opt<AlignMode> 00061 Align(cl::desc("Load/store alignment support"), 00062 cl::Hidden, cl::init(DefaultAlign), 00063 cl::values( 00064 clEnumValN(DefaultAlign, "arm-default-align", 00065 "Generate unaligned accesses only on hardware/OS " 00066 "combinations that are known to support them"), 00067 clEnumValN(StrictAlign, "arm-strict-align", 00068 "Disallow all unaligned memory accesses"), 00069 clEnumValN(NoStrictAlign, "arm-no-strict-align", 00070 "Allow unaligned memory accesses"), 00071 clEnumValEnd)); 00072 00073 enum ITMode { 00074 DefaultIT, 00075 RestrictedIT, 00076 NoRestrictedIT 00077 }; 00078 00079 static cl::opt<ITMode> 00080 IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), 00081 cl::ZeroOrMore, 00082 cl::values(clEnumValN(DefaultIT, "arm-default-it", 00083 "Generate IT block based on arch"), 00084 clEnumValN(RestrictedIT, "arm-restrict-it", 00085 "Disallow deprecated IT based on ARMv8"), 00086 clEnumValN(NoRestrictedIT, "arm-no-restrict-it", 00087 "Allow IT blocks based on ARMv7"), 00088 clEnumValEnd)); 00089 00090 static std::string computeDataLayout(ARMSubtarget &ST) { 00091 std::string Ret = ""; 00092 00093 if (ST.isLittle()) 00094 // Little endian. 00095 Ret += "e"; 00096 else 00097 // Big endian. 00098 Ret += "E"; 00099 00100 Ret += DataLayout::getManglingComponent(ST.getTargetTriple()); 00101 00102 // Pointers are 32 bits and aligned to 32 bits. 00103 Ret += "-p:32:32"; 00104 00105 // On thumb, i16,i18 and i1 have natural aligment requirements, but we try to 00106 // align to 32. 00107 if (ST.isThumb()) 00108 Ret += "-i1:8:32-i8:8:32-i16:16:32"; 00109 00110 // ABIs other than APCS have 64 bit integers with natural alignment. 00111 if (!ST.isAPCS_ABI()) 00112 Ret += "-i64:64"; 00113 00114 // We have 64 bits floats. The APCS ABI requires them to be aligned to 32 00115 // bits, others to 64 bits. We always try to align to 64 bits. 00116 if (ST.isAPCS_ABI()) 00117 Ret += "-f64:32:64"; 00118 00119 // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others 00120 // to 64. We always ty to give them natural alignment. 00121 if (ST.isAPCS_ABI()) 00122 Ret += "-v64:32:64-v128:32:128"; 00123 else 00124 Ret += "-v128:64:128"; 00125 00126 // On thumb and APCS, only try to align aggregates to 32 bits (the default is 00127 // 64 bits). 00128 if (ST.isThumb() || ST.isAPCS_ABI()) 00129 Ret += "-a:0:32"; 00130 00131 // Integer registers are 32 bits. 00132 Ret += "-n32"; 00133 00134 // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit 00135 // aligned everywhere else. 00136 if (ST.isTargetNaCl()) 00137 Ret += "-S128"; 00138 else if (ST.isAAPCS_ABI()) 00139 Ret += "-S64"; 00140 else 00141 Ret += "-S32"; 00142 00143 return Ret; 00144 } 00145 00146 /// initializeSubtargetDependencies - Initializes using a CPU and feature string 00147 /// so that we can use initializer lists for subtarget initialization. 00148 ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU, 00149 StringRef FS) { 00150 initializeEnvironment(); 00151 initSubtargetFeatures(CPU, FS); 00152 return *this; 00153 } 00154 00155 ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, 00156 const std::string &FS, TargetMachine &TM, 00157 bool IsLittle, const TargetOptions &Options) 00158 : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), 00159 ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle), 00160 TargetTriple(TT), Options(Options), TargetABI(ARM_ABI_UNKNOWN), 00161 DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS))), 00162 TSInfo(DL), 00163 InstrInfo(isThumb1Only() 00164 ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this) 00165 : !isThumb() 00166 ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this) 00167 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)), 00168 TLInfo(TM), 00169 FrameLowering(!isThumb1Only() 00170 ? new ARMFrameLowering(*this) 00171 : (ARMFrameLowering *)new Thumb1FrameLowering(*this)) {} 00172 00173 void ARMSubtarget::initializeEnvironment() { 00174 HasV4TOps = false; 00175 HasV5TOps = false; 00176 HasV5TEOps = false; 00177 HasV6Ops = false; 00178 HasV6MOps = false; 00179 HasV6T2Ops = false; 00180 HasV7Ops = false; 00181 HasV8Ops = false; 00182 HasVFPv2 = false; 00183 HasVFPv3 = false; 00184 HasVFPv4 = false; 00185 HasFPARMv8 = false; 00186 HasNEON = false; 00187 UseNEONForSinglePrecisionFP = false; 00188 UseMulOps = UseFusedMulOps; 00189 SlowFPVMLx = false; 00190 HasVMLxForwarding = false; 00191 SlowFPBrcc = false; 00192 InThumbMode = false; 00193 HasThumb2 = false; 00194 NoARM = false; 00195 IsR9Reserved = ReserveR9; 00196 UseMovt = false; 00197 SupportsTailCall = false; 00198 HasFP16 = false; 00199 HasD16 = false; 00200 HasHardwareDivide = false; 00201 HasHardwareDivideInARM = false; 00202 HasT2ExtractPack = false; 00203 HasDataBarrier = false; 00204 Pref32BitThumb = false; 00205 AvoidCPSRPartialUpdate = false; 00206 AvoidMOVsShifterOperand = false; 00207 HasRAS = false; 00208 HasMPExtension = false; 00209 HasVirtualization = false; 00210 FPOnlySP = false; 00211 HasPerfMon = false; 00212 HasTrustZone = false; 00213 HasCrypto = false; 00214 HasCRC = false; 00215 HasZeroCycleZeroing = false; 00216 AllowsUnalignedMem = false; 00217 Thumb2DSP = false; 00218 UseNaClTrap = false; 00219 UnsafeFPMath = false; 00220 } 00221 00222 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { 00223 if (CPUString.empty()) { 00224 if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s")) 00225 // Default to the Swift CPU when targeting armv7s/thumbv7s. 00226 CPUString = "swift"; 00227 else 00228 CPUString = "generic"; 00229 } 00230 00231 // Insert the architecture feature derived from the target triple into the 00232 // feature string. This is important for setting features that are implied 00233 // based on the architecture version. 00234 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 00235 CPUString); 00236 if (!FS.empty()) { 00237 if (!ArchFS.empty()) 00238 ArchFS = ArchFS + "," + FS.str(); 00239 else 00240 ArchFS = FS; 00241 } 00242 ParseSubtargetFeatures(CPUString, ArchFS); 00243 00244 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 00245 // Assert this for now to make the change obvious. 00246 assert(hasV6T2Ops() || !hasThumb2()); 00247 00248 // Keep a pointer to static instruction cost data for the specified CPU. 00249 SchedModel = getSchedModelForCPU(CPUString); 00250 00251 // Initialize scheduling itinerary for the specified CPU. 00252 InstrItins = getInstrItineraryForCPU(CPUString); 00253 00254 if (TargetABI == ARM_ABI_UNKNOWN) { 00255 switch (TargetTriple.getEnvironment()) { 00256 case Triple::Android: 00257 case Triple::EABI: 00258 case Triple::EABIHF: 00259 case Triple::GNUEABI: 00260 case Triple::GNUEABIHF: 00261 TargetABI = ARM_ABI_AAPCS; 00262 break; 00263 default: 00264 if ((isTargetIOS() && isMClass()) || 00265 (TargetTriple.isOSBinFormatMachO() && 00266 TargetTriple.getOS() == Triple::UnknownOS)) 00267 TargetABI = ARM_ABI_AAPCS; 00268 else 00269 TargetABI = ARM_ABI_APCS; 00270 break; 00271 } 00272 } 00273 00274 // FIXME: this is invalid for WindowsCE 00275 if (isTargetWindows()) { 00276 TargetABI = ARM_ABI_AAPCS; 00277 NoARM = true; 00278 } 00279 00280 if (isAAPCS_ABI()) 00281 stackAlignment = 8; 00282 if (isTargetNaCl()) 00283 stackAlignment = 16; 00284 00285 UseMovt = hasV6T2Ops() && ArmUseMOVT; 00286 00287 if (isTargetMachO()) { 00288 IsR9Reserved = ReserveR9 || !HasV6Ops; 00289 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 00290 } else { 00291 IsR9Reserved = ReserveR9; 00292 SupportsTailCall = !isThumb1Only(); 00293 } 00294 00295 switch (Align) { 00296 case DefaultAlign: 00297 // Assume pre-ARMv6 doesn't support unaligned accesses. 00298 // 00299 // ARMv6 may or may not support unaligned accesses depending on the 00300 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 00301 // Darwin and NetBSD targets support unaligned accesses, and others don't. 00302 // 00303 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 00304 // which raises an alignment fault on unaligned accesses. Linux 00305 // defaults this bit to 0 and handles it as a system-wide (not 00306 // per-process) setting. It is therefore safe to assume that ARMv7+ 00307 // Linux targets support unaligned accesses. The same goes for NaCl. 00308 // 00309 // The above behavior is consistent with GCC. 00310 AllowsUnalignedMem = 00311 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() || 00312 isTargetNetBSD())) || 00313 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD())); 00314 // The one exception is cortex-m0, which despite being v6, does not 00315 // support unaligned accesses. Rather than make the above boolean 00316 // expression even more obtuse, just override the value here. 00317 if (isThumb1Only() && isMClass()) 00318 AllowsUnalignedMem = false; 00319 break; 00320 case StrictAlign: 00321 AllowsUnalignedMem = false; 00322 break; 00323 case NoStrictAlign: 00324 AllowsUnalignedMem = true; 00325 break; 00326 } 00327 00328 switch (IT) { 00329 case DefaultIT: 00330 RestrictIT = hasV8Ops() ? true : false; 00331 break; 00332 case RestrictedIT: 00333 RestrictIT = true; 00334 break; 00335 case NoRestrictedIT: 00336 RestrictIT = false; 00337 break; 00338 } 00339 00340 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 00341 uint64_t Bits = getFeatureBits(); 00342 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 00343 (Options.UnsafeFPMath || isTargetDarwin())) 00344 UseNEONForSinglePrecisionFP = true; 00345 } 00346 00347 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 00348 bool 00349 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 00350 Reloc::Model RelocM) const { 00351 if (RelocM == Reloc::Static) 00352 return false; 00353 00354 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 00355 // load from stub. 00356 bool isDecl = GV->hasAvailableExternallyLinkage(); 00357 if (GV->isDeclaration() && !GV->isMaterializable()) 00358 isDecl = true; 00359 00360 if (!isTargetMachO()) { 00361 // Extra load is needed for all externally visible. 00362 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 00363 return false; 00364 return true; 00365 } else { 00366 if (RelocM == Reloc::PIC_) { 00367 // If this is a strong reference to a definition, it is definitely not 00368 // through a stub. 00369 if (!isDecl && !GV->isWeakForLinker()) 00370 return false; 00371 00372 // Unless we have a symbol with hidden visibility, we have to go through a 00373 // normal $non_lazy_ptr stub because this symbol might be resolved late. 00374 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 00375 return true; 00376 00377 // If symbol visibility is hidden, we have a stub for common symbol 00378 // references and external declarations. 00379 if (isDecl || GV->hasCommonLinkage()) 00380 // Hidden $non_lazy_ptr reference. 00381 return true; 00382 00383 return false; 00384 } else { 00385 // If this is a strong reference to a definition, it is definitely not 00386 // through a stub. 00387 if (!isDecl && !GV->isWeakForLinker()) 00388 return false; 00389 00390 // Unless we have a symbol with hidden visibility, we have to go through a 00391 // normal $non_lazy_ptr stub because this symbol might be resolved late. 00392 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 00393 return true; 00394 } 00395 } 00396 00397 return false; 00398 } 00399 00400 unsigned ARMSubtarget::getMispredictionPenalty() const { 00401 return SchedModel.MispredictPenalty; 00402 } 00403 00404 bool ARMSubtarget::hasSinCos() const { 00405 return getTargetTriple().getOS() == Triple::IOS && 00406 !getTargetTriple().isOSVersionLT(7, 0); 00407 } 00408 00409 // This overrides the PostRAScheduler bit in the SchedModel for any CPU. 00410 bool ARMSubtarget::enablePostMachineScheduler() const { 00411 return (!isThumb() || hasThumb2()); 00412 } 00413 00414 bool ARMSubtarget::enableAtomicExpand() const { 00415 return hasAnyDataBarrier() && !isThumb1Only(); 00416 } 00417 00418 bool ARMSubtarget::useMovt(const MachineFunction &MF) const { 00419 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit 00420 // immediates as it is inherently position independent, and may be out of 00421 // range otherwise. 00422 return UseMovt && (isTargetWindows() || 00423 !MF.getFunction()->getAttributes().hasAttribute( 00424 AttributeSet::FunctionIndex, Attribute::MinSize)); 00425 }