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