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 "ARMFrameLowering.h" 16 #include "ARMISelLowering.h" 17 #include "ARMInstrInfo.h" 18 #include "ARMMachineFunctionInfo.h" 19 #include "ARMSelectionDAGInfo.h" 20 #include "ARMSubtarget.h" 21 #include "ARMTargetMachine.h" 22 #include "Thumb1FrameLowering.h" 23 #include "Thumb1InstrInfo.h" 24 #include "Thumb2InstrInfo.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/IR/Attributes.h" 27 #include "llvm/IR/Function.h" 28 #include "llvm/IR/GlobalValue.h" 29 #include "llvm/Support/CommandLine.h" 30 #include "llvm/Target/TargetInstrInfo.h" 31 #include "llvm/Target/TargetOptions.h" 32 #include "llvm/Target/TargetRegisterInfo.h" 33 34 using namespace llvm; 35 36 #define DEBUG_TYPE "arm-subtarget" 37 38 #define GET_SUBTARGETINFO_TARGET_DESC 39 #define GET_SUBTARGETINFO_CTOR 40 #include "ARMGenSubtargetInfo.inc" 41 42 static cl::opt<bool> 43 UseFusedMulOps("arm-use-mulops", 44 cl::init(true), cl::Hidden); 45 46 enum ITMode { 47 DefaultIT, 48 RestrictedIT, 49 NoRestrictedIT 50 }; 51 52 static cl::opt<ITMode> 53 IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), 54 cl::ZeroOrMore, 55 cl::values(clEnumValN(DefaultIT, "arm-default-it", 56 "Generate IT block based on arch"), 57 clEnumValN(RestrictedIT, "arm-restrict-it", 58 "Disallow deprecated IT based on ARMv8"), 59 clEnumValN(NoRestrictedIT, "arm-no-restrict-it", 60 "Allow IT blocks based on ARMv7"), 61 clEnumValEnd)); 62 63 /// initializeSubtargetDependencies - Initializes using a CPU and feature string 64 /// so that we can use initializer lists for subtarget initialization. 65 ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU, 66 StringRef FS) { 67 initializeEnvironment(); 68 initSubtargetFeatures(CPU, FS); 69 return *this; 70 } 71 72 ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU, 73 StringRef FS) { 74 ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS); 75 if (STI.isThumb1Only()) 76 return (ARMFrameLowering *)new Thumb1FrameLowering(STI); 77 78 return new ARMFrameLowering(STI); 79 } 80 81 ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU, 82 const std::string &FS, 83 const ARMBaseTargetMachine &TM, bool IsLittle) 84 : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), 85 ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle), 86 TargetTriple(TT), Options(TM.Options), TM(TM), 87 FrameLowering(initializeFrameLowering(CPU, FS)), 88 // At this point initializeSubtargetDependencies has been called so 89 // we can query directly. 90 InstrInfo(isThumb1Only() 91 ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this) 92 : !isThumb() 93 ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this) 94 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)), 95 TLInfo(TM, *this) {} 96 97 void ARMSubtarget::initializeEnvironment() { 98 HasV4TOps = false; 99 HasV5TOps = false; 100 HasV5TEOps = false; 101 HasV6Ops = false; 102 HasV6MOps = false; 103 HasV6KOps = false; 104 HasV6T2Ops = false; 105 HasV7Ops = false; 106 HasV8Ops = false; 107 HasV8_1aOps = false; 108 HasVFPv2 = false; 109 HasVFPv3 = false; 110 HasVFPv4 = false; 111 HasFPARMv8 = false; 112 HasNEON = false; 113 UseNEONForSinglePrecisionFP = false; 114 UseMulOps = UseFusedMulOps; 115 SlowFPVMLx = false; 116 HasVMLxForwarding = false; 117 SlowFPBrcc = false; 118 InThumbMode = false; 119 UseSoftFloat = false; 120 HasThumb2 = false; 121 NoARM = false; 122 ReserveR9 = false; 123 NoMovt = false; 124 SupportsTailCall = false; 125 HasFP16 = false; 126 HasD16 = false; 127 HasHardwareDivide = false; 128 HasHardwareDivideInARM = false; 129 HasT2ExtractPack = false; 130 HasDataBarrier = false; 131 Pref32BitThumb = false; 132 AvoidCPSRPartialUpdate = false; 133 AvoidMOVsShifterOperand = false; 134 HasRAS = false; 135 HasMPExtension = false; 136 HasVirtualization = false; 137 FPOnlySP = false; 138 HasPerfMon = false; 139 HasTrustZone = false; 140 HasCrypto = false; 141 HasCRC = false; 142 HasZeroCycleZeroing = false; 143 StrictAlign = false; 144 Thumb2DSP = false; 145 UseNaClTrap = false; 146 GenLongCalls = false; 147 UnsafeFPMath = false; 148 } 149 150 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { 151 if (CPUString.empty()) { 152 if (isTargetDarwin() && TargetTriple.getArchName().endswith("v7s")) 153 // Default to the Swift CPU when targeting armv7s/thumbv7s. 154 CPUString = "swift"; 155 else 156 CPUString = "generic"; 157 } 158 159 // Insert the architecture feature derived from the target triple into the 160 // feature string. This is important for setting features that are implied 161 // based on the architecture version. 162 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString); 163 if (!FS.empty()) { 164 if (!ArchFS.empty()) 165 ArchFS = (Twine(ArchFS) + "," + FS).str(); 166 else 167 ArchFS = FS; 168 } 169 ParseSubtargetFeatures(CPUString, ArchFS); 170 171 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 172 // Assert this for now to make the change obvious. 173 assert(hasV6T2Ops() || !hasThumb2()); 174 175 // Keep a pointer to static instruction cost data for the specified CPU. 176 SchedModel = getSchedModelForCPU(CPUString); 177 178 // Initialize scheduling itinerary for the specified CPU. 179 InstrItins = getInstrItineraryForCPU(CPUString); 180 181 // FIXME: this is invalid for WindowsCE 182 if (isTargetWindows()) 183 NoARM = true; 184 185 if (isAAPCS_ABI()) 186 stackAlignment = 8; 187 if (isTargetNaCl()) 188 stackAlignment = 16; 189 190 if (isTargetMachO()) 191 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0); 192 else 193 SupportsTailCall = !isThumb1Only(); 194 195 switch (IT) { 196 case DefaultIT: 197 RestrictIT = hasV8Ops(); 198 break; 199 case RestrictedIT: 200 RestrictIT = true; 201 break; 202 case NoRestrictedIT: 203 RestrictIT = false; 204 break; 205 } 206 207 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 208 const FeatureBitset &Bits = getFeatureBits(); 209 if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters 210 (Options.UnsafeFPMath || isTargetDarwin())) 211 UseNEONForSinglePrecisionFP = true; 212 } 213 214 bool ARMSubtarget::isAPCS_ABI() const { 215 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 216 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS; 217 } 218 bool ARMSubtarget::isAAPCS_ABI() const { 219 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 220 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS; 221 } 222 223 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 224 bool 225 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 226 Reloc::Model RelocM) const { 227 if (RelocM == Reloc::Static) 228 return false; 229 230 bool isDef = GV->isStrongDefinitionForLinker(); 231 232 if (!isTargetMachO()) { 233 // Extra load is needed for all externally visible. 234 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 235 return false; 236 return true; 237 } else { 238 // If this is a strong reference to a definition, it is definitely not 239 // through a stub. 240 if (isDef) 241 return false; 242 243 // Unless we have a symbol with hidden visibility, we have to go through a 244 // normal $non_lazy_ptr stub because this symbol might be resolved late. 245 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 246 return true; 247 248 if (RelocM == Reloc::PIC_) { 249 // If symbol visibility is hidden, we have a stub for common symbol 250 // references and external declarations. 251 if (GV->isDeclarationForLinker() || GV->hasCommonLinkage()) 252 // Hidden $non_lazy_ptr reference. 253 return true; 254 } 255 } 256 257 return false; 258 } 259 260 unsigned ARMSubtarget::getMispredictionPenalty() const { 261 return SchedModel.MispredictPenalty; 262 } 263 264 bool ARMSubtarget::hasSinCos() const { 265 return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0); 266 } 267 268 bool ARMSubtarget::enableMachineScheduler() const { 269 // Enable the MachineScheduler before register allocation for out-of-order 270 // architectures where we do not use the PostRA scheduler anymore (for now 271 // restricted to swift). 272 return getSchedModel().isOutOfOrder() && isSwift(); 273 } 274 275 // This overrides the PostRAScheduler bit in the SchedModel for any CPU. 276 bool ARMSubtarget::enablePostRAScheduler() const { 277 // No need for PostRA scheduling on out of order CPUs (for now restricted to 278 // swift). 279 if (getSchedModel().isOutOfOrder() && isSwift()) 280 return false; 281 return (!isThumb() || hasThumb2()); 282 } 283 284 bool ARMSubtarget::enableAtomicExpand() const { 285 return hasAnyDataBarrier() && !isThumb1Only(); 286 } 287 288 bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const { 289 return isSwift() && !MF.getFunction()->optForMinSize(); 290 } 291 292 bool ARMSubtarget::useMovt(const MachineFunction &MF) const { 293 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit 294 // immediates as it is inherently position independent, and may be out of 295 // range otherwise. 296 return !NoMovt && hasV6T2Ops() && 297 (isTargetWindows() || !MF.getFunction()->optForMinSize()); 298 } 299 300 bool ARMSubtarget::useFastISel() const { 301 // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl. 302 return TM.Options.EnableFastISel && 303 ((isTargetMachO() && !isThumb1Only()) || 304 (isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb())); 305 } 306