ARMSubtarget.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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 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, 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 93void 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 UseLong64 = false; 143} 144 145void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { 146 AttributeSet FnAttrs = MF->getFunction()->getAttributes(); 147 Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 148 "target-cpu"); 149 Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 150 "target-features"); 151 std::string CPU = 152 !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; 153 std::string FS = 154 !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; 155 if (!FS.empty()) { 156 initializeEnvironment(); 157 resetSubtargetFeatures(CPU, FS); 158 } 159 160 MinSize = 161 FnAttrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::MinSize); 162} 163 164void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { 165 if (CPUString.empty()) { 166 if (isTargetIOS() && TargetTriple.getArchName().endswith("v7s")) 167 // Default to the Swift CPU when targeting armv7s/thumbv7s. 168 CPUString = "swift"; 169 else 170 CPUString = "generic"; 171 } 172 173 // Insert the architecture feature derived from the target triple into the 174 // feature string. This is important for setting features that are implied 175 // based on the architecture version. 176 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 177 CPUString); 178 if (!FS.empty()) { 179 if (!ArchFS.empty()) 180 ArchFS = ArchFS + "," + FS.str(); 181 else 182 ArchFS = FS; 183 } 184 ParseSubtargetFeatures(CPUString, ArchFS); 185 186 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 187 // Assert this for now to make the change obvious. 188 assert(hasV6T2Ops() || !hasThumb2()); 189 190 // Keep a pointer to static instruction cost data for the specified CPU. 191 SchedModel = getSchedModelForCPU(CPUString); 192 193 // Initialize scheduling itinerary for the specified CPU. 194 InstrItins = getInstrItineraryForCPU(CPUString); 195 196 if (TargetABI == ARM_ABI_UNKNOWN) { 197 switch (TargetTriple.getEnvironment()) { 198 case Triple::Android: 199 case Triple::EABI: 200 case Triple::EABIHF: 201 case Triple::GNUEABI: 202 case Triple::GNUEABIHF: 203 TargetABI = ARM_ABI_AAPCS; 204 break; 205 default: 206 if ((isTargetIOS() && isMClass()) || 207 (TargetTriple.isOSBinFormatMachO() && 208 TargetTriple.getOS() == Triple::UnknownOS)) 209 TargetABI = ARM_ABI_AAPCS; 210 else 211 TargetABI = ARM_ABI_APCS; 212 break; 213 } 214 } 215 216 // FIXME: this is invalid for WindowsCE 217 if (isTargetWindows()) { 218 TargetABI = ARM_ABI_AAPCS; 219 NoARM = true; 220 } 221 222 if (isAAPCS_ABI()) 223 stackAlignment = 8; 224 if (isTargetNaCl()) 225 stackAlignment = 16; 226 227 UseMovt = hasV6T2Ops() && ArmUseMOVT; 228 229 if (isTargetMachO()) { 230 IsR9Reserved = ReserveR9 | !HasV6Ops; 231 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 232 } else { 233 IsR9Reserved = ReserveR9; 234 SupportsTailCall = !isThumb1Only(); 235 } 236 237 if (!isThumb() || hasThumb2()) 238 PostRAScheduler = true; 239 240 switch (Align) { 241 case DefaultAlign: 242 // Assume pre-ARMv6 doesn't support unaligned accesses. 243 // 244 // ARMv6 may or may not support unaligned accesses depending on the 245 // SCTLR.U bit, which is architecture-specific. We assume ARMv6 246 // Darwin and NetBSD targets support unaligned accesses, and others don't. 247 // 248 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit 249 // which raises an alignment fault on unaligned accesses. Linux 250 // defaults this bit to 0 and handles it as a system-wide (not 251 // per-process) setting. It is therefore safe to assume that ARMv7+ 252 // Linux targets support unaligned accesses. The same goes for NaCl. 253 // 254 // The above behavior is consistent with GCC. 255 AllowsUnalignedMem = 256 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() || 257 isTargetNetBSD())) || 258 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD())); 259 // The one exception is cortex-m0, which despite being v6, does not 260 // support unaligned accesses. Rather than make the above boolean 261 // expression even more obtuse, just override the value here. 262 if (isThumb1Only() && isMClass()) 263 AllowsUnalignedMem = false; 264 break; 265 case StrictAlign: 266 AllowsUnalignedMem = false; 267 break; 268 case NoStrictAlign: 269 AllowsUnalignedMem = true; 270 break; 271 } 272 273 switch (IT) { 274 case DefaultIT: 275 RestrictIT = hasV8Ops() ? true : false; 276 break; 277 case RestrictedIT: 278 RestrictIT = true; 279 break; 280 case NoRestrictedIT: 281 RestrictIT = false; 282 break; 283 } 284 285 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 286 uint64_t Bits = getFeatureBits(); 287 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 288 (Options.UnsafeFPMath || isTargetDarwin())) 289 UseNEONForSinglePrecisionFP = true; 290} 291 292/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 293bool 294ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 295 Reloc::Model RelocM) const { 296 if (RelocM == Reloc::Static) 297 return false; 298 299 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 300 // load from stub. 301 bool isDecl = GV->hasAvailableExternallyLinkage(); 302 if (GV->isDeclaration() && !GV->isMaterializable()) 303 isDecl = true; 304 305 if (!isTargetMachO()) { 306 // Extra load is needed for all externally visible. 307 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 308 return false; 309 return true; 310 } else { 311 if (RelocM == Reloc::PIC_) { 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 // If symbol visibility is hidden, we have a stub for common symbol 323 // references and external declarations. 324 if (isDecl || GV->hasCommonLinkage()) 325 // Hidden $non_lazy_ptr reference. 326 return true; 327 328 return false; 329 } else { 330 // If this is a strong reference to a definition, it is definitely not 331 // through a stub. 332 if (!isDecl && !GV->isWeakForLinker()) 333 return false; 334 335 // Unless we have a symbol with hidden visibility, we have to go through a 336 // normal $non_lazy_ptr stub because this symbol might be resolved late. 337 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 338 return true; 339 } 340 } 341 342 return false; 343} 344 345unsigned ARMSubtarget::getMispredictionPenalty() const { 346 return SchedModel->MispredictPenalty; 347} 348 349bool ARMSubtarget::hasSinCos() const { 350 return getTargetTriple().getOS() == Triple::IOS && 351 !getTargetTriple().isOSVersionLT(7, 0); 352} 353 354bool ARMSubtarget::enablePostRAScheduler( 355 CodeGenOpt::Level OptLevel, 356 TargetSubtargetInfo::AntiDepBreakMode& Mode, 357 RegClassVector& CriticalPathRCs) const { 358 Mode = TargetSubtargetInfo::ANTIDEP_NONE; 359 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 360} 361