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> 35DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden); 36 37static cl::opt<bool> 38UseFusedMulOps("arm-use-mulops", 39 cl::init(true), cl::Hidden); 40 41static cl::opt<bool> 42StrictAlign("arm-strict-align", cl::Hidden, 43 cl::desc("Disallow all unaligned memory accesses")); 44 45ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, 46 const std::string &FS, const TargetOptions &Options) 47 : ARMGenSubtargetInfo(TT, CPU, FS) 48 , ARMProcFamily(Others) 49 , stackAlignment(4) 50 , CPUString(CPU) 51 , TargetTriple(TT) 52 , Options(Options) 53 , TargetABI(ARM_ABI_APCS) { 54 initializeEnvironment(); 55 resetSubtargetFeatures(CPU, FS); 56} 57 58void ARMSubtarget::initializeEnvironment() { 59 HasV4TOps = false; 60 HasV5TOps = false; 61 HasV5TEOps = false; 62 HasV6Ops = false; 63 HasV6T2Ops = false; 64 HasV7Ops = false; 65 HasVFPv2 = false; 66 HasVFPv3 = false; 67 HasVFPv4 = false; 68 HasNEON = false; 69 UseNEONForSinglePrecisionFP = false; 70 UseMulOps = UseFusedMulOps; 71 SlowFPVMLx = false; 72 HasVMLxForwarding = false; 73 SlowFPBrcc = false; 74 InThumbMode = false; 75 HasThumb2 = false; 76 IsMClass = false; 77 NoARM = false; 78 PostRAScheduler = false; 79 IsR9Reserved = ReserveR9; 80 UseMovt = false; 81 SupportsTailCall = false; 82 HasFP16 = false; 83 HasD16 = false; 84 HasHardwareDivide = false; 85 HasHardwareDivideInARM = false; 86 HasT2ExtractPack = false; 87 HasDataBarrier = false; 88 Pref32BitThumb = false; 89 AvoidCPSRPartialUpdate = false; 90 AvoidMOVsShifterOperand = false; 91 HasRAS = false; 92 HasMPExtension = false; 93 FPOnlySP = false; 94 HasTrustZone = false; 95 AllowsUnalignedMem = false; 96 Thumb2DSP = false; 97 UseNaClTrap = false; 98 UnsafeFPMath = false; 99} 100 101void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { 102 AttributeSet FnAttrs = MF->getFunction()->getAttributes(); 103 Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 104 "target-cpu"); 105 Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, 106 "target-features"); 107 std::string CPU = 108 !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; 109 std::string FS = 110 !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; 111 if (!FS.empty()) { 112 initializeEnvironment(); 113 resetSubtargetFeatures(CPU, FS); 114 } 115} 116 117void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { 118 if (CPUString.empty()) 119 CPUString = "generic"; 120 121 // Insert the architecture feature derived from the target triple into the 122 // feature string. This is important for setting features that are implied 123 // based on the architecture version. 124 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple.getTriple(), 125 CPUString); 126 if (!FS.empty()) { 127 if (!ArchFS.empty()) 128 ArchFS = ArchFS + "," + FS.str(); 129 else 130 ArchFS = FS; 131 } 132 ParseSubtargetFeatures(CPUString, ArchFS); 133 134 // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a 135 // ARM version or CPU and then remove this. 136 if (!HasV6T2Ops && hasThumb2()) 137 HasV4TOps = HasV5TOps = HasV5TEOps = HasV6Ops = HasV6T2Ops = true; 138 139 // Keep a pointer to static instruction cost data for the specified CPU. 140 SchedModel = getSchedModelForCPU(CPUString); 141 142 // Initialize scheduling itinerary for the specified CPU. 143 InstrItins = getInstrItineraryForCPU(CPUString); 144 145 if ((TargetTriple.getTriple().find("eabi") != std::string::npos) || 146 (isTargetIOS() && isMClass())) 147 // FIXME: We might want to separate AAPCS and EABI. Some systems, e.g. 148 // Darwin-EABI conforms to AACPS but not the rest of EABI. 149 TargetABI = ARM_ABI_AAPCS; 150 151 if (isAAPCS_ABI()) 152 stackAlignment = 8; 153 154 if (!isTargetIOS()) 155 UseMovt = hasV6T2Ops(); 156 else { 157 IsR9Reserved = ReserveR9 | !HasV6Ops; 158 UseMovt = DarwinUseMOVT && hasV6T2Ops(); 159 SupportsTailCall = !getTargetTriple().isOSVersionLT(5, 0); 160 } 161 162 if (!isThumb() || hasThumb2()) 163 PostRAScheduler = true; 164 165 // v6+ may or may not support unaligned mem access depending on the system 166 // configuration. 167 if (!StrictAlign && hasV6Ops() && isTargetDarwin()) 168 AllowsUnalignedMem = true; 169 170 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default. 171 uint64_t Bits = getFeatureBits(); 172 if ((Bits & ARM::ProcA5 || Bits & ARM::ProcA8) && // Where this matters 173 (Options.UnsafeFPMath || isTargetDarwin())) 174 UseNEONForSinglePrecisionFP = true; 175} 176 177/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 178bool 179ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 180 Reloc::Model RelocM) const { 181 if (RelocM == Reloc::Static) 182 return false; 183 184 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 185 // load from stub. 186 bool isDecl = GV->hasAvailableExternallyLinkage(); 187 if (GV->isDeclaration() && !GV->isMaterializable()) 188 isDecl = true; 189 190 if (!isTargetDarwin()) { 191 // Extra load is needed for all externally visible. 192 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 193 return false; 194 return true; 195 } else { 196 if (RelocM == Reloc::PIC_) { 197 // If this is a strong reference to a definition, it is definitely not 198 // through a stub. 199 if (!isDecl && !GV->isWeakForLinker()) 200 return false; 201 202 // Unless we have a symbol with hidden visibility, we have to go through a 203 // normal $non_lazy_ptr stub because this symbol might be resolved late. 204 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 205 return true; 206 207 // If symbol visibility is hidden, we have a stub for common symbol 208 // references and external declarations. 209 if (isDecl || GV->hasCommonLinkage()) 210 // Hidden $non_lazy_ptr reference. 211 return true; 212 213 return false; 214 } else { 215 // If this is a strong reference to a definition, it is definitely not 216 // through a stub. 217 if (!isDecl && !GV->isWeakForLinker()) 218 return false; 219 220 // Unless we have a symbol with hidden visibility, we have to go through a 221 // normal $non_lazy_ptr stub because this symbol might be resolved late. 222 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 223 return true; 224 } 225 } 226 227 return false; 228} 229 230unsigned ARMSubtarget::getMispredictionPenalty() const { 231 return SchedModel->MispredictPenalty; 232} 233 234bool ARMSubtarget::enablePostRAScheduler( 235 CodeGenOpt::Level OptLevel, 236 TargetSubtargetInfo::AntiDepBreakMode& Mode, 237 RegClassVector& CriticalPathRCs) const { 238 Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; 239 CriticalPathRCs.clear(); 240 CriticalPathRCs.push_back(&ARM::GPRRegClass); 241 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 242} 243