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 /// ForceFastISel - Use the fast-isel, even for subtargets where it is not 64 /// currently supported (for testing only). 65 static cl::opt<bool> 66 ForceFastISel("arm-force-fast-isel", 67 cl::init(false), cl::Hidden); 68 69 /// initializeSubtargetDependencies - Initializes using a CPU and feature string 70 /// so that we can use initializer lists for subtarget initialization. 71 ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU, 72 StringRef FS) { 73 initializeEnvironment(); 74 initSubtargetFeatures(CPU, FS); 75 return *this; 76 } 77 78 ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU, 79 StringRef FS) { 80 ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS); 81 if (STI.isThumb1Only()) 82 return (ARMFrameLowering *)new Thumb1FrameLowering(STI); 83 84 return new ARMFrameLowering(STI); 85 } 86 87 ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU, 88 const std::string &FS, 89 const ARMBaseTargetMachine &TM, bool IsLittle) 90 : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others), 91 ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle), 92 TargetTriple(TT), Options(TM.Options), TM(TM), 93 FrameLowering(initializeFrameLowering(CPU, FS)), 94 // At this point initializeSubtargetDependencies has been called so 95 // we can query directly. 96 InstrInfo(isThumb1Only() 97 ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this) 98 : !isThumb() 99 ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this) 100 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)), 101 TLInfo(TM, *this) {} 102 103 void ARMSubtarget::initializeEnvironment() { 104 HasV4TOps = false; 105 HasV5TOps = false; 106 HasV5TEOps = false; 107 HasV6Ops = false; 108 HasV6MOps = false; 109 HasV6KOps = false; 110 HasV6T2Ops = false; 111 HasV7Ops = false; 112 HasV8Ops = false; 113 HasV8_1aOps = false; 114 HasVFPv2 = false; 115 HasVFPv3 = false; 116 HasVFPv4 = false; 117 HasFPARMv8 = false; 118 HasNEON = false; 119 UseNEONForSinglePrecisionFP = false; 120 UseMulOps = UseFusedMulOps; 121 SlowFPVMLx = false; 122 HasVMLxForwarding = false; 123 SlowFPBrcc = false; 124 InThumbMode = false; 125 UseSoftFloat = false; 126 HasThumb2 = false; 127 NoARM = false; 128 ReserveR9 = false; 129 NoMovt = false; 130 SupportsTailCall = false; 131 HasFP16 = false; 132 HasD16 = false; 133 HasHardwareDivide = false; 134 HasHardwareDivideInARM = false; 135 HasT2ExtractPack = false; 136 HasDataBarrier = false; 137 Pref32BitThumb = false; 138 AvoidCPSRPartialUpdate = false; 139 AvoidMOVsShifterOperand = false; 140 HasRAS = false; 141 HasMPExtension = false; 142 HasVirtualization = false; 143 FPOnlySP = false; 144 HasPerfMon = false; 145 HasTrustZone = false; 146 HasCrypto = false; 147 HasCRC = false; 148 HasZeroCycleZeroing = false; 149 StrictAlign = false; 150 HasDSP = false; 151 UseNaClTrap = false; 152 GenLongCalls = false; 153 UnsafeFPMath = false; 154 } 155 156 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { 157 if (CPUString.empty()) { 158 if (isTargetDarwin() && 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, CPUString); 169 if (!FS.empty()) { 170 if (!ArchFS.empty()) 171 ArchFS = (Twine(ArchFS) + "," + FS).str(); 172 else 173 ArchFS = FS; 174 } 175 ParseSubtargetFeatures(CPUString, ArchFS); 176 177 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode. 178 // Assert this for now to make the change obvious. 179 assert(hasV6T2Ops() || !hasThumb2()); 180 181 // Keep a pointer to static instruction cost data for the specified CPU. 182 SchedModel = getSchedModelForCPU(CPUString); 183 184 // Initialize scheduling itinerary for the specified CPU. 185 InstrItins = getInstrItineraryForCPU(CPUString); 186 187 // FIXME: this is invalid for WindowsCE 188 if (isTargetWindows()) 189 NoARM = true; 190 191 if (isAAPCS_ABI()) 192 stackAlignment = 8; 193 if (isTargetNaCl()) 194 stackAlignment = 16; 195 196 // FIXME: Completely disable sibcall for Thumb1 since ThumbRegisterInfo:: 197 // emitEpilogue is not ready for them. Thumb tail calls also use t2B, as 198 // the Thumb1 16-bit unconditional branch doesn't have sufficient relocation 199 // support in the assembler and linker to be used. This would need to be 200 // fixed to fully support tail calls in Thumb1. 201 // 202 // Doing this is tricky, since the LDM/POP instruction on Thumb doesn't take 203 // LR. This means if we need to reload LR, it takes an extra instructions, 204 // which outweighs the value of the tail call; but here we don't know yet 205 // whether LR is going to be used. Probably the right approach is to 206 // generate the tail call here and turn it back into CALL/RET in 207 // emitEpilogue if LR is used. 208 209 // Thumb1 PIC calls to external symbols use BX, so they can be tail calls, 210 // but we need to make sure there are enough registers; the only valid 211 // registers are the 4 used for parameters. We don't currently do this 212 // case. 213 214 SupportsTailCall = !isThumb1Only(); 215 216 if (isTargetMachO() && isTargetIOS() && getTargetTriple().isOSVersionLT(5, 0)) 217 SupportsTailCall = false; 218 219 switch (IT) { 220 case DefaultIT: 221 RestrictIT = hasV8Ops(); 222 break; 223 case RestrictedIT: 224 RestrictIT = true; 225 break; 226 case NoRestrictedIT: 227 RestrictIT = false; 228 break; 229 } 230 231 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 232 const FeatureBitset &Bits = getFeatureBits(); 233 if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters 234 (Options.UnsafeFPMath || isTargetDarwin())) 235 UseNEONForSinglePrecisionFP = true; 236 } 237 238 bool ARMSubtarget::isAPCS_ABI() const { 239 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 240 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS; 241 } 242 bool ARMSubtarget::isAAPCS_ABI() const { 243 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN); 244 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS; 245 } 246 247 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 248 bool 249 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 250 Reloc::Model RelocM) const { 251 if (RelocM == Reloc::Static) 252 return false; 253 254 bool isDef = GV->isStrongDefinitionForLinker(); 255 256 if (!isTargetMachO()) { 257 // Extra load is needed for all externally visible. 258 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 259 return false; 260 return true; 261 } else { 262 // If this is a strong reference to a definition, it is definitely not 263 // through a stub. 264 if (isDef) 265 return false; 266 267 // Unless we have a symbol with hidden visibility, we have to go through a 268 // normal $non_lazy_ptr stub because this symbol might be resolved late. 269 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 270 return true; 271 272 if (RelocM == Reloc::PIC_) { 273 // If symbol visibility is hidden, we have a stub for common symbol 274 // references and external declarations. 275 if (GV->isDeclarationForLinker() || GV->hasCommonLinkage()) 276 // Hidden $non_lazy_ptr reference. 277 return true; 278 } 279 } 280 281 return false; 282 } 283 284 unsigned ARMSubtarget::getMispredictionPenalty() const { 285 return SchedModel.MispredictPenalty; 286 } 287 288 bool ARMSubtarget::hasSinCos() const { 289 return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0); 290 } 291 292 bool ARMSubtarget::enableMachineScheduler() const { 293 // Enable the MachineScheduler before register allocation for out-of-order 294 // architectures where we do not use the PostRA scheduler anymore (for now 295 // restricted to swift). 296 return getSchedModel().isOutOfOrder() && isSwift(); 297 } 298 299 // This overrides the PostRAScheduler bit in the SchedModel for any CPU. 300 bool ARMSubtarget::enablePostRAScheduler() const { 301 // No need for PostRA scheduling on out of order CPUs (for now restricted to 302 // swift). 303 if (getSchedModel().isOutOfOrder() && isSwift()) 304 return false; 305 return (!isThumb() || hasThumb2()); 306 } 307 308 bool ARMSubtarget::enableAtomicExpand() const { 309 return hasAnyDataBarrier() && !isThumb1Only(); 310 } 311 312 bool ARMSubtarget::useStride4VFPs(const MachineFunction &MF) const { 313 return isSwift() && !MF.getFunction()->optForMinSize(); 314 } 315 316 bool ARMSubtarget::useMovt(const MachineFunction &MF) const { 317 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit 318 // immediates as it is inherently position independent, and may be out of 319 // range otherwise. 320 return !NoMovt && hasV6T2Ops() && 321 (isTargetWindows() || !MF.getFunction()->optForMinSize()); 322 } 323 324 bool ARMSubtarget::useFastISel() const { 325 // Enable fast-isel for any target, for testing only. 326 if (ForceFastISel) 327 return true; 328 329 // Limit fast-isel to the targets that are or have been tested. 330 if (!hasV6Ops()) 331 return false; 332 333 // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl. 334 return TM.Options.EnableFastISel && 335 ((isTargetMachO() && !isThumb1Only()) || 336 (isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb())); 337 } 338