ARMSubtarget.cpp revision a7603982dbf9e240ecc7ed6eddcd1cdb868107ac
1//===-- ARMSubtarget.cpp - ARM 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 ARM specific subclass of TargetSubtargetInfo. 11// 12//===----------------------------------------------------------------------===// 13 14#include "ARMSubtarget.h" 15#include "ARMBaseRegisterInfo.h" 16#include "llvm/GlobalValue.h" 17#include "llvm/Target/TargetSubtargetInfo.h" 18#include "llvm/Support/CommandLine.h" 19#include "llvm/ADT/SmallVector.h" 20 21#define GET_SUBTARGETINFO_CTOR 22#define GET_SUBTARGETINFO_MC_DESC 23#define GET_SUBTARGETINFO_TARGET_DESC 24#include "ARMGenSubtarget.inc" 25 26using namespace llvm; 27 28static cl::opt<bool> 29ReserveR9("arm-reserve-r9", cl::Hidden, 30 cl::desc("Reserve R9, making it unavailable as GPR")); 31 32static cl::opt<bool> 33DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden); 34 35static cl::opt<bool> 36StrictAlign("arm-strict-align", cl::Hidden, 37 cl::desc("Disallow all unaligned memory accesses")); 38 39ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, 40 const std::string &FS, bool isT) 41 : ARMGenSubtargetInfo() 42 , ARMArchVersion(V4) 43 , ARMProcFamily(Others) 44 , ARMFPUType(None) 45 , UseNEONForSinglePrecisionFP(false) 46 , SlowFPVMLx(false) 47 , HasVMLxForwarding(false) 48 , SlowFPBrcc(false) 49 , IsThumb(isT) 50 , ThumbMode(Thumb1) 51 , NoARM(false) 52 , PostRAScheduler(false) 53 , IsR9Reserved(ReserveR9) 54 , UseMovt(false) 55 , HasFP16(false) 56 , HasD16(false) 57 , HasHardwareDivide(false) 58 , HasT2ExtractPack(false) 59 , HasDataBarrier(false) 60 , Pref32BitThumb(false) 61 , AvoidCPSRPartialUpdate(false) 62 , HasMPExtension(false) 63 , FPOnlySP(false) 64 , AllowsUnalignedMem(false) 65 , Thumb2DSP(false) 66 , stackAlignment(4) 67 , CPUString(CPU) 68 , TargetTriple(TT) 69 , TargetABI(ARM_ABI_APCS) { 70 // Determine default and user specified characteristics 71 72 // When no arch is specified either by CPU or by attributes, make the default 73 // ARMv4T. 74 const char *ARMArchFeature = ""; 75 if (CPUString.empty()) 76 CPUString = "generic"; 77 if (CPUString == "generic" && (FS.empty() || FS == "generic")) { 78 ARMArchVersion = V4T; 79 ARMArchFeature = "+v4t"; 80 } 81 82 // Set the boolean corresponding to the current target triple, or the default 83 // if one cannot be determined, to true. 84 unsigned Len = TT.length(); 85 unsigned Idx = 0; 86 87 if (Len >= 5 && TT.substr(0, 4) == "armv") 88 Idx = 4; 89 else if (Len >= 6 && TT.substr(0, 5) == "thumb") { 90 IsThumb = true; 91 if (Len >= 7 && TT[5] == 'v') 92 Idx = 6; 93 } 94 if (Idx) { 95 unsigned SubVer = TT[Idx]; 96 if (SubVer >= '7' && SubVer <= '9') { 97 ARMArchVersion = V7A; 98 ARMArchFeature = "+v7a"; 99 if (Len >= Idx+2 && TT[Idx+1] == 'm') { 100 ARMArchVersion = V7M; 101 ARMArchFeature = "+v7m"; 102 } else if (Len >= Idx+3 && TT[Idx+1] == 'e'&& TT[Idx+2] == 'm') { 103 ARMArchVersion = V7EM; 104 ARMArchFeature = "+v7em"; 105 } 106 } else if (SubVer == '6') { 107 ARMArchVersion = V6; 108 ARMArchFeature = "+v6"; 109 if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') { 110 ARMArchVersion = V6T2; 111 ARMArchFeature = "+v6t2"; 112 } 113 } else if (SubVer == '5') { 114 ARMArchVersion = V5T; 115 ARMArchFeature = "+v5t"; 116 if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') { 117 ARMArchVersion = V5TE; 118 ARMArchFeature = "+v5te"; 119 } 120 } else if (SubVer == '4') { 121 if (Len >= Idx+2 && TT[Idx+1] == 't') { 122 ARMArchVersion = V4T; 123 ARMArchFeature = "+v4t"; 124 } else { 125 ARMArchVersion = V4; 126 ARMArchFeature = ""; 127 } 128 } 129 } 130 131 if (TT.find("eabi") != std::string::npos) 132 TargetABI = ARM_ABI_AAPCS; 133 134 // Insert the architecture feature derived from the target triple into the 135 // feature string. This is important for setting features that are implied 136 // based on the architecture version. 137 std::string FSWithArch = std::string(ARMArchFeature); 138 if (FSWithArch.empty()) 139 FSWithArch = FS; 140 else if (!FS.empty()) 141 FSWithArch = FSWithArch + "," + FS; 142 ParseSubtargetFeatures(FSWithArch, CPUString); 143 144 // Initialize scheduling itinerary for the specified CPU. 145 InstrItins = getInstrItineraryForCPU(CPUString); 146 147 // After parsing Itineraries, set ItinData.IssueWidth. 148 computeIssueWidth(); 149 150 // Thumb2 implies at least V6T2. 151 if (ARMArchVersion >= V6T2) 152 ThumbMode = Thumb2; 153 else if (ThumbMode >= Thumb2) 154 ARMArchVersion = V6T2; 155 156 if (isAAPCS_ABI()) 157 stackAlignment = 8; 158 159 if (!isTargetDarwin()) 160 UseMovt = hasV6T2Ops(); 161 else { 162 IsR9Reserved = ReserveR9 | (ARMArchVersion < V6); 163 UseMovt = DarwinUseMOVT && hasV6T2Ops(); 164 } 165 166 if (!isThumb() || hasThumb2()) 167 PostRAScheduler = true; 168 169 // v6+ may or may not support unaligned mem access depending on the system 170 // configuration. 171 if (!StrictAlign && hasV6Ops() && isTargetDarwin()) 172 AllowsUnalignedMem = true; 173} 174 175/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. 176bool 177ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, 178 Reloc::Model RelocM) const { 179 if (RelocM == Reloc::Static) 180 return false; 181 182 // Materializable GVs (in JIT lazy compilation mode) do not require an extra 183 // load from stub. 184 bool isDecl = GV->hasAvailableExternallyLinkage(); 185 if (GV->isDeclaration() && !GV->isMaterializable()) 186 isDecl = true; 187 188 if (!isTargetDarwin()) { 189 // Extra load is needed for all externally visible. 190 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) 191 return false; 192 return true; 193 } else { 194 if (RelocM == Reloc::PIC_) { 195 // If this is a strong reference to a definition, it is definitely not 196 // through a stub. 197 if (!isDecl && !GV->isWeakForLinker()) 198 return false; 199 200 // Unless we have a symbol with hidden visibility, we have to go through a 201 // normal $non_lazy_ptr stub because this symbol might be resolved late. 202 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 203 return true; 204 205 // If symbol visibility is hidden, we have a stub for common symbol 206 // references and external declarations. 207 if (isDecl || GV->hasCommonLinkage()) 208 // Hidden $non_lazy_ptr reference. 209 return true; 210 211 return false; 212 } else { 213 // If this is a strong reference to a definition, it is definitely not 214 // through a stub. 215 if (!isDecl && !GV->isWeakForLinker()) 216 return false; 217 218 // Unless we have a symbol with hidden visibility, we have to go through a 219 // normal $non_lazy_ptr stub because this symbol might be resolved late. 220 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. 221 return true; 222 } 223 } 224 225 return false; 226} 227 228unsigned ARMSubtarget::getMispredictionPenalty() const { 229 // If we have a reasonable estimate of the pipeline depth, then we can 230 // estimate the penalty of a misprediction based on that. 231 if (isCortexA8()) 232 return 13; 233 else if (isCortexA9()) 234 return 8; 235 236 // Otherwise, just return a sensible default. 237 return 10; 238} 239 240void ARMSubtarget::computeIssueWidth() { 241 unsigned allStage1Units = 0; 242 for (const InstrItinerary *itin = InstrItins.Itineraries; 243 itin->FirstStage != ~0U; ++itin) { 244 const InstrStage *IS = InstrItins.Stages + itin->FirstStage; 245 allStage1Units |= IS->getUnits(); 246 } 247 InstrItins.IssueWidth = 0; 248 while (allStage1Units) { 249 ++InstrItins.IssueWidth; 250 // clear the lowest bit 251 allStage1Units ^= allStage1Units & ~(allStage1Units - 1); 252 } 253 assert(InstrItins.IssueWidth <= 2 && "itinerary bug, too many stage 1 units"); 254} 255 256bool ARMSubtarget::enablePostRAScheduler( 257 CodeGenOpt::Level OptLevel, 258 TargetSubtargetInfo::AntiDepBreakMode& Mode, 259 RegClassVector& CriticalPathRCs) const { 260 Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; 261 CriticalPathRCs.clear(); 262 CriticalPathRCs.push_back(&ARM::GPRRegClass); 263 return PostRAScheduler && OptLevel >= CodeGenOpt::Default; 264} 265