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