1 //===-- AArch64Subtarget.cpp - AArch64 Subtarget Information ----*- C++ -*-===// 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 AArch64 specific subclass of TargetSubtarget. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AArch64Subtarget.h" 15 16 #include "AArch64.h" 17 #include "AArch64InstrInfo.h" 18 #include "AArch64PBQPRegAlloc.h" 19 #include "AArch64TargetMachine.h" 20 21 #include "AArch64CallLowering.h" 22 #include "AArch64LegalizerInfo.h" 23 #include "AArch64RegisterBankInfo.h" 24 #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 25 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 26 #include "llvm/CodeGen/GlobalISel/Legalizer.h" 27 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 28 #include "llvm/CodeGen/MachineScheduler.h" 29 #include "llvm/IR/GlobalValue.h" 30 #include "llvm/Support/TargetRegistry.h" 31 32 using namespace llvm; 33 34 #define DEBUG_TYPE "aarch64-subtarget" 35 36 #define GET_SUBTARGETINFO_CTOR 37 #define GET_SUBTARGETINFO_TARGET_DESC 38 #include "AArch64GenSubtargetInfo.inc" 39 40 static cl::opt<bool> 41 EnableEarlyIfConvert("aarch64-early-ifcvt", cl::desc("Enable the early if " 42 "converter pass"), cl::init(true), cl::Hidden); 43 44 // If OS supports TBI, use this flag to enable it. 45 static cl::opt<bool> 46 UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of " 47 "an address is ignored"), cl::init(false), cl::Hidden); 48 49 static cl::opt<bool> 50 UseNonLazyBind("aarch64-enable-nonlazybind", 51 cl::desc("Call nonlazybind functions via direct GOT load"), 52 cl::init(false), cl::Hidden); 53 54 AArch64Subtarget & 55 AArch64Subtarget::initializeSubtargetDependencies(StringRef FS, 56 StringRef CPUString) { 57 // Determine default and user-specified characteristics 58 59 if (CPUString.empty()) 60 CPUString = "generic"; 61 62 ParseSubtargetFeatures(CPUString, FS); 63 initializeProperties(); 64 65 return *this; 66 } 67 68 void AArch64Subtarget::initializeProperties() { 69 // Initialize CPU specific properties. We should add a tablegen feature for 70 // this in the future so we can specify it together with the subtarget 71 // features. 72 switch (ARMProcFamily) { 73 case Cyclone: 74 CacheLineSize = 64; 75 PrefetchDistance = 280; 76 MinPrefetchStride = 2048; 77 MaxPrefetchIterationsAhead = 3; 78 break; 79 case CortexA57: 80 MaxInterleaveFactor = 4; 81 PrefFunctionAlignment = 4; 82 break; 83 case ExynosM1: 84 MaxInterleaveFactor = 4; 85 MaxJumpTableSize = 8; 86 PrefFunctionAlignment = 4; 87 PrefLoopAlignment = 3; 88 break; 89 case Falkor: 90 MaxInterleaveFactor = 4; 91 // FIXME: remove this to enable 64-bit SLP if performance looks good. 92 MinVectorRegisterBitWidth = 128; 93 CacheLineSize = 128; 94 PrefetchDistance = 820; 95 MinPrefetchStride = 2048; 96 MaxPrefetchIterationsAhead = 8; 97 break; 98 case Saphira: 99 MaxInterleaveFactor = 4; 100 // FIXME: remove this to enable 64-bit SLP if performance looks good. 101 MinVectorRegisterBitWidth = 128; 102 break; 103 case Kryo: 104 MaxInterleaveFactor = 4; 105 VectorInsertExtractBaseCost = 2; 106 CacheLineSize = 128; 107 PrefetchDistance = 740; 108 MinPrefetchStride = 1024; 109 MaxPrefetchIterationsAhead = 11; 110 // FIXME: remove this to enable 64-bit SLP if performance looks good. 111 MinVectorRegisterBitWidth = 128; 112 break; 113 case ThunderX2T99: 114 CacheLineSize = 64; 115 PrefFunctionAlignment = 3; 116 PrefLoopAlignment = 2; 117 MaxInterleaveFactor = 4; 118 PrefetchDistance = 128; 119 MinPrefetchStride = 1024; 120 MaxPrefetchIterationsAhead = 4; 121 // FIXME: remove this to enable 64-bit SLP if performance looks good. 122 MinVectorRegisterBitWidth = 128; 123 break; 124 case ThunderX: 125 case ThunderXT88: 126 case ThunderXT81: 127 case ThunderXT83: 128 CacheLineSize = 128; 129 PrefFunctionAlignment = 3; 130 PrefLoopAlignment = 2; 131 // FIXME: remove this to enable 64-bit SLP if performance looks good. 132 MinVectorRegisterBitWidth = 128; 133 break; 134 case CortexA35: break; 135 case CortexA53: 136 PrefFunctionAlignment = 3; 137 break; 138 case CortexA55: break; 139 case CortexA72: 140 case CortexA73: 141 case CortexA75: 142 PrefFunctionAlignment = 4; 143 break; 144 case Others: break; 145 } 146 } 147 148 AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU, 149 const std::string &FS, 150 const TargetMachine &TM, bool LittleEndian) 151 : AArch64GenSubtargetInfo(TT, CPU, FS), 152 ReserveX18(TT.isOSDarwin() || TT.isOSWindows()), IsLittle(LittleEndian), 153 TargetTriple(TT), FrameLowering(), 154 InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(), 155 TLInfo(TM, *this) { 156 CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering())); 157 Legalizer.reset(new AArch64LegalizerInfo()); 158 159 auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo()); 160 161 // FIXME: At this point, we can't rely on Subtarget having RBI. 162 // It's awkward to mix passing RBI and the Subtarget; should we pass 163 // TII/TRI as well? 164 InstSelector.reset(createAArch64InstructionSelector( 165 *static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI)); 166 167 RegBankInfo.reset(RBI); 168 } 169 170 const CallLowering *AArch64Subtarget::getCallLowering() const { 171 return CallLoweringInfo.get(); 172 } 173 174 const InstructionSelector *AArch64Subtarget::getInstructionSelector() const { 175 return InstSelector.get(); 176 } 177 178 const LegalizerInfo *AArch64Subtarget::getLegalizerInfo() const { 179 return Legalizer.get(); 180 } 181 182 const RegisterBankInfo *AArch64Subtarget::getRegBankInfo() const { 183 return RegBankInfo.get(); 184 } 185 186 /// Find the target operand flags that describe how a global value should be 187 /// referenced for the current subtarget. 188 unsigned char 189 AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV, 190 const TargetMachine &TM) const { 191 // MachO large model always goes via a GOT, simply to get a single 8-byte 192 // absolute relocation on all global addresses. 193 if (TM.getCodeModel() == CodeModel::Large && isTargetMachO()) 194 return AArch64II::MO_GOT; 195 196 if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) 197 return AArch64II::MO_GOT; 198 199 // The small code model's direct accesses use ADRP, which cannot 200 // necessarily produce the value 0 (if the code is above 4GB). 201 if (useSmallAddressing() && GV->hasExternalWeakLinkage()) 202 return AArch64II::MO_GOT; 203 204 return AArch64II::MO_NO_FLAG; 205 } 206 207 unsigned char AArch64Subtarget::classifyGlobalFunctionReference( 208 const GlobalValue *GV, const TargetMachine &TM) const { 209 // MachO large model always goes via a GOT, because we don't have the 210 // relocations available to do anything else.. 211 if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() && 212 !GV->hasInternalLinkage()) 213 return AArch64II::MO_GOT; 214 215 // NonLazyBind goes via GOT unless we know it's available locally. 216 auto *F = dyn_cast<Function>(GV); 217 if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) && 218 !TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) 219 return AArch64II::MO_GOT; 220 221 return AArch64II::MO_NO_FLAG; 222 } 223 224 /// This function returns the name of a function which has an interface 225 /// like the non-standard bzero function, if such a function exists on 226 /// the current subtarget and it is considered prefereable over 227 /// memset with zero passed as the second argument. Otherwise it 228 /// returns null. 229 const char *AArch64Subtarget::getBZeroEntry() const { 230 // Prefer bzero on Darwin only. 231 if(isTargetDarwin()) 232 return "bzero"; 233 234 return nullptr; 235 } 236 237 void AArch64Subtarget::overrideSchedPolicy(MachineSchedPolicy &Policy, 238 unsigned NumRegionInstrs) const { 239 // LNT run (at least on Cyclone) showed reasonably significant gains for 240 // bi-directional scheduling. 253.perlbmk. 241 Policy.OnlyTopDown = false; 242 Policy.OnlyBottomUp = false; 243 // Enabling or Disabling the latency heuristic is a close call: It seems to 244 // help nearly no benchmark on out-of-order architectures, on the other hand 245 // it regresses register pressure on a few benchmarking. 246 Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic; 247 } 248 249 bool AArch64Subtarget::enableEarlyIfConversion() const { 250 return EnableEarlyIfConvert; 251 } 252 253 bool AArch64Subtarget::supportsAddressTopByteIgnored() const { 254 if (!UseAddressTopByteIgnored) 255 return false; 256 257 if (TargetTriple.isiOS()) { 258 unsigned Major, Minor, Micro; 259 TargetTriple.getiOSVersion(Major, Minor, Micro); 260 return Major >= 8; 261 } 262 263 return false; 264 } 265 266 std::unique_ptr<PBQPRAConstraint> 267 AArch64Subtarget::getCustomPBQPConstraints() const { 268 return balanceFPOps() ? llvm::make_unique<A57ChainingConstraint>() : nullptr; 269 } 270