ARMSubtarget.cpp revision 296373
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/GlobalValue.h" 19#include "llvm/IR/Function.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 28using namespace llvm; 29 30static cl::opt<bool> 31ReserveR9("arm-reserve-r9", cl::Hidden, 32 cl::desc("Reserve R9, making it unavailable as GPR")); 33 34static cl::opt<bool> 35ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden); 36 37static cl::opt<bool> 38UseFusedMulOps("arm-use-mulops", 39 cl::init(true), cl::Hidden); 40 41enum AlignMode { 42 DefaultAlign, 43 StrictAlign, 44 NoStrictAlign 45}; 46 47static cl::opt<AlignMode> 48Align(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 60enum ITMode { 61 DefaultIT, 62 RestrictedIT, 63 NoRestrictedIT 64}; 65 66static cl::opt<ITMode> 67IT(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 77ARMSubtarget::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_APCS) { 87 initializeEnvironment(); 88 resetSubtargetFeatures(CPU, FS); 89} 90 91void 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 UseNEONForSinglePrecisionFP = false; 106 UseMulOps = UseFusedMulOps; 107 SlowFPVMLx = false; 108 HasVMLxForwarding = false; 109 SlowFPBrcc = false; 110 InThumbMode = false; 111 HasThumb2 = false; 112 NoARM = false; 113 PostRAScheduler = false; 114 IsR9Reserved = ReserveR9; 115 UseMovt = false; 116 SupportsTailCall = false; 117 HasFP16 = false; 118 HasD16 = false; 119 HasHardwareDivide = false; 120 HasHardwareDivideInARM = false; 121 HasT2ExtractPack = false; 122 HasDataBarrier = false; 123 Pref32BitThumb = false; 124 AvoidCPSRPartialUpdate = false; 125 AvoidMOVsShifterOperand = false; 126 HasRAS = false; 127 HasMPExtension = false; 128 HasVirtualization = false; 129 FPOnlySP = false; 130 HasPerfMon = false; 131 HasTrustZone = false; 132 HasCrypto = false; 133 HasCRC = false; 134 AllowsUnalignedMem = false; 135 Thumb2DSP = false; 136 UseNaClTrap = false; 137 UnsafeFPMath = false; 138} 139 140void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { 141 AttributeSet FnAttrs = MF->getFunction()->getAttributes(); 142 Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 143 "target-cpu"); 144 Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 145 "target-features"); 146 std::string CPU = 147 !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; 148 std::string FS = 149 !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; 150 if (!FS.empty()) { 151 initializeEnvironment(); 152 resetSubtargetFeatures(CPU, FS); 153 } 154} 155 156void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { 157 if (CPUString.empty()) { 158 if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s")) 159 // Default to the Swift CPU when targeting armv7s/thumbv7s. 160 CPUString = "swift"; 161 else 162 CPUString = "generic"; 163 } 164 165 // Insert the architecture feature derived from the target triple into the 166 // feature string. This is important for setting features that are implied 167 // based on the architecture version. 168 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 169 CPUString); 170 if (!FS.empty()) { 171 if (!ArchFS.empty()) 172 ArchFS = ArchFS + "," + FS.str(); 173 else 174 ArchFS = FS; 175 } 176 ParseSubtargetFeatures(CPUString, ArchFS); 177 178 // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a 179 // ARM version or CPU and then remove this. 180 if (!HasV6T2Ops && hasThumb2()) 181 HasV4TOps = HasV5TOps = HasV5TEOps = HasV6Ops = HasV6MOps = HasV6T2Ops = true; 182 183 // Keep a pointer to static instruction cost data for the specified CPU. 184 SchedModel = getSchedModelForCPU(CPUString); 185 186 // Initialize scheduling itinerary for the specified CPU. 187 InstrItins = getInstrItineraryForCPU(CPUString); 188 189 if ((TargetTriple.getTriple().find("eabi") != std::string::npos) || 190 (isTargetIOS() && isMClass())) 191 // FIXME: We might want to separate AAPCS and EABI. Some systems, e.g. 192 // Darwin-EABI conforms to AACPS but not the rest of EABI. 193 TargetABI = ARM_ABI_AAPCS; 194 195 if (isAAPCS_ABI()) 196 stackAlignment = 8; 197 198 UseMovt = hasV6T2Ops() && ArmUseMOVT; 199 200 if (!isTargetIOS()) { 201 IsR9Reserved = ReserveR9; 202 } else { 203 IsR9Reserved = ReserveR9 | !HasV6Ops; 204 SupportsTailCall = !getTargetTriple().isOSVersionLT(5, 0); 205 } 206 207 if (!isThumb() || hasThumb2()) 208 PostRAScheduler = true; 209 210 switch (Align) { 211 case DefaultAlign: 212 // Assume pre-ARMv6 doesn't support unaligned accesses. 213 // 214 // ARMv6 may or may not support unaligned accesses depending on the 215 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 216 // Darwin targets support unaligned accesses, and others don't. 217 // 218 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 219 // which raises an alignment fault on unaligned accesses. Linux 220 // defaults this bit to 0 and handles it as a system-wide (not 221 // per-process) setting. It is therefore safe to assume that ARMv7+ 222 // Linux targets support unaligned accesses. The same goes for NaCl. 223 // 224 // The above behavior is consistent with GCC. 225 AllowsUnalignedMem = ( 226 (hasV7Ops() && (isTargetLinux() || isTargetNaCl())) || 227 (hasV6Ops() && isTargetDarwin())); 228 break; 229 case StrictAlign: 230 AllowsUnalignedMem = false; 231 break; 232 case NoStrictAlign: 233 AllowsUnalignedMem = true; 234 break; 235 } 236 237 switch (IT) { 238 case DefaultIT: 239 RestrictIT = hasV8Ops() ? true : false; 240 break; 241 case RestrictedIT: 242 RestrictIT = true; 243 break; 244 case NoRestrictedIT: 245 RestrictIT = false; 246 break; 247 } 248 249 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 250 uint64_t Bits = getFeatureBits(); 251 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 252 (Options.UnsafeFPMath || isTargetDarwin())) 253 UseNEONForSinglePrecisionFP = true; 254} 255 256/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 257bool 258ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 259 Reloc::Model RelocM) const { 260 if (RelocM == Reloc::Static) 261 return false; 262 263 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 264 // load from stub. 265 bool isDecl = GV->hasAvailableExternallyLinkage(); 266 if (GV->isDeclaration() && !GV->isMaterializable()) 267 isDecl = true; 268 269 if (!isTargetDarwin()) { 270 // Extra load is needed for all externally visible. 271 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 272 return false; 273 return true; 274 } else { 275 if (RelocM == Reloc::PIC_) { 276 // If this is a strong reference to a definition, it is definitely not 277 // through a stub. 278 if (!isDecl && !GV->isWeakForLinker()) 279 return false; 280 281 // Unless we have a symbol with hidden visibility, we have to go through a 282 // normal $non_lazy_ptr stub because this symbol might be resolved late. 283 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 284 return true; 285 286 // If symbol visibility is hidden, we have a stub for common symbol 287 // references and external declarations. 288 if (isDecl || GV->hasCommonLinkage()) 289 // Hidden $non_lazy_ptr reference. 290 return true; 291 292 return false; 293 } else { 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 } 305 306 return false; 307} 308 309unsigned ARMSubtarget::getMispredictionPenalty() const { 310 return SchedModel->MispredictPenalty; 311} 312 313bool ARMSubtarget::hasSinCos() const { 314 return getTargetTriple().getOS() == Triple::IOS && 315 !getTargetTriple().isOSVersionLT(7, 0); 316} 317 318bool ARMSubtarget::enablePostRAScheduler( 319 CodeGenOpt::Level OptLevel, 320 TargetSubtargetInfo::AntiDepBreakMode& Mode, 321 RegClassVector& CriticalPathRCs) const { 322 Mode = TargetSubtargetInfo::ANTIDEP_NONE; 323 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 324} 325