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 ReserveR9("arm-reserve-r9", cl::Hidden,
44 cl::desc("Reserve R9, making it unavailable as GPR"));
45
46 static cl::opt<bool>
47 ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden);
48
49 static cl::opt<bool>
50 UseFusedMulOps("arm-use-mulops",
51 cl::init(true), cl::Hidden);
52
53 namespace {
54 enum AlignMode {
55 DefaultAlign,
56 StrictAlign,
57 NoStrictAlign
58 };
59 }
60
61 static cl::opt<AlignMode>
62 Align(cl::desc("Load/store alignment support"),
63 cl::Hidden, cl::init(DefaultAlign),
64 cl::values(
65 clEnumValN(DefaultAlign, "arm-default-align",
66 "Generate unaligned accesses only on hardware/OS "
67 "combinations that are known to support them"),
68 clEnumValN(StrictAlign, "arm-strict-align",
69 "Disallow all unaligned memory accesses"),
70 clEnumValN(NoStrictAlign, "arm-no-strict-align",
71 "Allow unaligned memory accesses"),
72 clEnumValEnd));
73
74 enum ITMode {
75 DefaultIT,
76 RestrictedIT,
77 NoRestrictedIT
78 };
79
80 static cl::opt<ITMode>
81 IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
82 cl::ZeroOrMore,
83 cl::values(clEnumValN(DefaultIT, "arm-default-it",
84 "Generate IT block based on arch"),
85 clEnumValN(RestrictedIT, "arm-restrict-it",
86 "Disallow deprecated IT based on ARMv8"),
87 clEnumValN(NoRestrictedIT, "arm-no-restrict-it",
88 "Allow IT blocks based on ARMv7"),
89 clEnumValEnd));
90
91 /// initializeSubtargetDependencies - Initializes using a CPU and feature string
92 /// so that we can use initializer lists for subtarget initialization.
initializeSubtargetDependencies(StringRef CPU,StringRef FS)93 ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
94 StringRef FS) {
95 initializeEnvironment();
96 initSubtargetFeatures(CPU, FS);
97 return *this;
98 }
99
initializeFrameLowering(StringRef CPU,StringRef FS)100 ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
101 StringRef FS) {
102 ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
103 if (STI.isThumb1Only())
104 return (ARMFrameLowering *)new Thumb1FrameLowering(STI);
105
106 return new ARMFrameLowering(STI);
107 }
108
ARMSubtarget(const Triple & TT,const std::string & CPU,const std::string & FS,const ARMBaseTargetMachine & TM,bool IsLittle)109 ARMSubtarget::ARMSubtarget(const Triple &TT, const std::string &CPU,
110 const std::string &FS,
111 const ARMBaseTargetMachine &TM, bool IsLittle)
112 : ARMGenSubtargetInfo(TT, CPU, FS), ARMProcFamily(Others),
113 ARMProcClass(None), stackAlignment(4), CPUString(CPU), IsLittle(IsLittle),
114 TargetTriple(TT), Options(TM.Options), TM(TM),
115 FrameLowering(initializeFrameLowering(CPU, FS)),
116 // At this point initializeSubtargetDependencies has been called so
117 // we can query directly.
118 InstrInfo(isThumb1Only()
119 ? (ARMBaseInstrInfo *)new Thumb1InstrInfo(*this)
120 : !isThumb()
121 ? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
122 : (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
123 TLInfo(TM, *this) {}
124
initializeEnvironment()125 void ARMSubtarget::initializeEnvironment() {
126 HasV4TOps = false;
127 HasV5TOps = false;
128 HasV5TEOps = false;
129 HasV6Ops = false;
130 HasV6MOps = false;
131 HasV6KOps = false;
132 HasV6T2Ops = false;
133 HasV7Ops = false;
134 HasV8Ops = false;
135 HasV8_1aOps = false;
136 HasVFPv2 = false;
137 HasVFPv3 = false;
138 HasVFPv4 = false;
139 HasFPARMv8 = false;
140 HasNEON = false;
141 UseNEONForSinglePrecisionFP = false;
142 UseMulOps = UseFusedMulOps;
143 SlowFPVMLx = false;
144 HasVMLxForwarding = false;
145 SlowFPBrcc = false;
146 InThumbMode = false;
147 UseSoftFloat = false;
148 HasThumb2 = false;
149 NoARM = false;
150 IsR9Reserved = ReserveR9;
151 UseMovt = false;
152 SupportsTailCall = false;
153 HasFP16 = false;
154 HasD16 = false;
155 HasHardwareDivide = false;
156 HasHardwareDivideInARM = false;
157 HasT2ExtractPack = false;
158 HasDataBarrier = false;
159 Pref32BitThumb = false;
160 AvoidCPSRPartialUpdate = false;
161 AvoidMOVsShifterOperand = false;
162 HasRAS = false;
163 HasMPExtension = false;
164 HasVirtualization = false;
165 FPOnlySP = false;
166 HasPerfMon = false;
167 HasTrustZone = false;
168 HasCrypto = false;
169 HasCRC = false;
170 HasZeroCycleZeroing = false;
171 AllowsUnalignedMem = false;
172 Thumb2DSP = false;
173 UseNaClTrap = false;
174 GenLongCalls = false;
175 UnsafeFPMath = false;
176 }
177
initSubtargetFeatures(StringRef CPU,StringRef FS)178 void ARMSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
179 if (CPUString.empty()) {
180 if (isTargetDarwin() && TargetTriple.getArchName().endswith("v7s"))
181 // Default to the Swift CPU when targeting armv7s/thumbv7s.
182 CPUString = "swift";
183 else
184 CPUString = "generic";
185 }
186
187 // Insert the architecture feature derived from the target triple into the
188 // feature string. This is important for setting features that are implied
189 // based on the architecture version.
190 std::string ArchFS = ARM_MC::ParseARMTriple(TargetTriple, CPUString);
191 if (!FS.empty()) {
192 if (!ArchFS.empty())
193 ArchFS = (Twine(ArchFS) + "," + FS).str();
194 else
195 ArchFS = FS;
196 }
197 ParseSubtargetFeatures(CPUString, ArchFS);
198
199 // FIXME: This used enable V6T2 support implicitly for Thumb2 mode.
200 // Assert this for now to make the change obvious.
201 assert(hasV6T2Ops() || !hasThumb2());
202
203 // Keep a pointer to static instruction cost data for the specified CPU.
204 SchedModel = getSchedModelForCPU(CPUString);
205
206 // Initialize scheduling itinerary for the specified CPU.
207 InstrItins = getInstrItineraryForCPU(CPUString);
208
209 // FIXME: this is invalid for WindowsCE
210 if (isTargetWindows())
211 NoARM = true;
212
213 if (isAAPCS_ABI())
214 stackAlignment = 8;
215 if (isTargetNaCl())
216 stackAlignment = 16;
217
218 UseMovt = hasV6T2Ops() && ArmUseMOVT;
219
220 if (isTargetMachO()) {
221 IsR9Reserved = ReserveR9 || !HasV6Ops;
222 SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0);
223 } else {
224 IsR9Reserved = ReserveR9;
225 SupportsTailCall = !isThumb1Only();
226 }
227
228 if (Align == DefaultAlign) {
229 // Assume pre-ARMv6 doesn't support unaligned accesses.
230 //
231 // ARMv6 may or may not support unaligned accesses depending on the
232 // SCTLR.U bit, which is architecture-specific. We assume ARMv6
233 // Darwin and NetBSD targets support unaligned accesses, and others don't.
234 //
235 // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit
236 // which raises an alignment fault on unaligned accesses. Linux
237 // defaults this bit to 0 and handles it as a system-wide (not
238 // per-process) setting. It is therefore safe to assume that ARMv7+
239 // Linux targets support unaligned accesses. The same goes for NaCl.
240 //
241 // The above behavior is consistent with GCC.
242 AllowsUnalignedMem =
243 (hasV7Ops() && (isTargetLinux() || isTargetNaCl() ||
244 isTargetNetBSD())) ||
245 (hasV6Ops() && (isTargetMachO() || isTargetNetBSD()));
246 } else {
247 AllowsUnalignedMem = !(Align == StrictAlign);
248 }
249
250 // No v6M core supports unaligned memory access (v6M ARM ARM A3.2)
251 if (isV6M())
252 AllowsUnalignedMem = false;
253
254 switch (IT) {
255 case DefaultIT:
256 RestrictIT = hasV8Ops();
257 break;
258 case RestrictedIT:
259 RestrictIT = true;
260 break;
261 case NoRestrictedIT:
262 RestrictIT = false;
263 break;
264 }
265
266 // NEON f32 ops are non-IEEE 754 compliant. Darwin is ok with it by default.
267 const FeatureBitset &Bits = getFeatureBits();
268 if ((Bits[ARM::ProcA5] || Bits[ARM::ProcA8]) && // Where this matters
269 (Options.UnsafeFPMath || isTargetDarwin()))
270 UseNEONForSinglePrecisionFP = true;
271 }
272
isAPCS_ABI() const273 bool ARMSubtarget::isAPCS_ABI() const {
274 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
275 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS;
276 }
isAAPCS_ABI() const277 bool ARMSubtarget::isAAPCS_ABI() const {
278 assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
279 return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS;
280 }
281
282 /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
283 bool
GVIsIndirectSymbol(const GlobalValue * GV,Reloc::Model RelocM) const284 ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
285 Reloc::Model RelocM) const {
286 if (RelocM == Reloc::Static)
287 return false;
288
289 bool isDef = GV->isStrongDefinitionForLinker();
290
291 if (!isTargetMachO()) {
292 // Extra load is needed for all externally visible.
293 if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
294 return false;
295 return true;
296 } else {
297 // If this is a strong reference to a definition, it is definitely not
298 // through a stub.
299 if (isDef)
300 return false;
301
302 // Unless we have a symbol with hidden visibility, we have to go through a
303 // normal $non_lazy_ptr stub because this symbol might be resolved late.
304 if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference.
305 return true;
306
307 if (RelocM == Reloc::PIC_) {
308 // If symbol visibility is hidden, we have a stub for common symbol
309 // references and external declarations.
310 if (GV->isDeclarationForLinker() || GV->hasCommonLinkage())
311 // Hidden $non_lazy_ptr reference.
312 return true;
313 }
314 }
315
316 return false;
317 }
318
getMispredictionPenalty() const319 unsigned ARMSubtarget::getMispredictionPenalty() const {
320 return SchedModel.MispredictPenalty;
321 }
322
hasSinCos() const323 bool ARMSubtarget::hasSinCos() const {
324 return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0);
325 }
326
327 // This overrides the PostRAScheduler bit in the SchedModel for any CPU.
enablePostRAScheduler() const328 bool ARMSubtarget::enablePostRAScheduler() const {
329 return (!isThumb() || hasThumb2());
330 }
331
enableAtomicExpand() const332 bool ARMSubtarget::enableAtomicExpand() const {
333 return hasAnyDataBarrier() && !isThumb1Only();
334 }
335
useMovt(const MachineFunction & MF) const336 bool ARMSubtarget::useMovt(const MachineFunction &MF) const {
337 // NOTE Windows on ARM needs to use mov.w/mov.t pairs to materialise 32-bit
338 // immediates as it is inherently position independent, and may be out of
339 // range otherwise.
340 return UseMovt && (isTargetWindows() ||
341 !MF.getFunction()->hasFnAttribute(Attribute::MinSize));
342 }
343
useFastISel() const344 bool ARMSubtarget::useFastISel() const {
345 // Thumb2 support on iOS; ARM support on iOS, Linux and NaCl.
346 return TM.Options.EnableFastISel &&
347 ((isTargetMachO() && !isThumb1Only()) ||
348 (isTargetLinux() && !isThumb()) || (isTargetNaCl() && !isThumb()));
349 }
350