1
//===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This file implements the ARM specific subclass of TargetSubtargetInfo.
12
//===----------------------------------------------------------------------===//
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"
36
#define DEBUG_TYPE "arm-subtarget"
38
#define GET_SUBTARGETINFO_TARGET_DESC
39
#define GET_SUBTARGETINFO_CTOR
40
#include "ARMGenSubtargetInfo.inc"
43
ReserveR9("arm-reserve-r9", cl::Hidden,
44
cl::desc("Reserve R9, making it unavailable as GPR"));
47
ArmUseMOVT("arm-use-movt", cl::init(true), cl::Hidden);
50
UseFusedMulOps("arm-use-mulops",
51
cl::init(true), cl::Hidden);
61
static cl::opt<AlignMode>
62
Align(cl::desc("Load/store alignment support"),
63
cl::Hidden, cl::init(DefaultAlign),
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"),
80
static cl::opt<ITMode>
81
IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT),
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"),
91
/// initializeSubtargetDependencies - Initializes using a CPU and feature string
92
/// so that we can use initializer lists for subtarget initialization.
93
ARMSubtarget &ARMSubtarget::initializeSubtargetDependencies(StringRef CPU,
95
initializeEnvironment();
96
initSubtargetFeatures(CPU, FS);
100
ARMFrameLowering *ARMSubtarget::initializeFrameLowering(StringRef CPU,
102
ARMSubtarget &STI = initializeSubtargetDependencies(CPU, FS);
103
if (STI.isThumb1Only())
104
return (ARMFrameLowering *)new Thumb1FrameLowering(STI);
106
return new ARMFrameLowering(STI);
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)
121
? (ARMBaseInstrInfo *)new ARMInstrInfo(*this)
122
: (ARMBaseInstrInfo *)new Thumb2InstrInfo(*this)),
125
void ARMSubtarget::initializeEnvironment() {
141
UseNEONForSinglePrecisionFP = false;
142
UseMulOps = UseFusedMulOps;
144
HasVMLxForwarding = false;
147
UseSoftFloat = false;
150
IsR9Reserved = ReserveR9;
152
SupportsTailCall = false;
155
HasHardwareDivide = false;
156
HasHardwareDivideInARM = false;
157
HasT2ExtractPack = false;
158
HasDataBarrier = false;
159
Pref32BitThumb = false;
160
AvoidCPSRPartialUpdate = false;
161
AvoidMOVsShifterOperand = false;
163
HasMPExtension = false;
164
HasVirtualization = false;
167
HasTrustZone = false;
170
HasZeroCycleZeroing = false;
171
AllowsUnalignedMem = false;
174
GenLongCalls = false;
175
UnsafeFPMath = false;
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.
184
CPUString = "generic";
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);
193
ArchFS = (Twine(ArchFS) + "," + FS).str();
197
ParseSubtargetFeatures(CPUString, ArchFS);
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());
203
// Keep a pointer to static instruction cost data for the specified CPU.
204
SchedModel = getSchedModelForCPU(CPUString);
206
// Initialize scheduling itinerary for the specified CPU.
207
InstrItins = getInstrItineraryForCPU(CPUString);
209
// FIXME: this is invalid for WindowsCE
210
if (isTargetWindows())
218
UseMovt = hasV6T2Ops() && ArmUseMOVT;
220
if (isTargetMachO()) {
221
IsR9Reserved = ReserveR9 || !HasV6Ops;
222
SupportsTailCall = !isTargetIOS() || !getTargetTriple().isOSVersionLT(5, 0);
224
IsR9Reserved = ReserveR9;
225
SupportsTailCall = !isThumb1Only();
228
if (Align == DefaultAlign) {
229
// Assume pre-ARMv6 doesn't support unaligned accesses.
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.
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.
241
// The above behavior is consistent with GCC.
243
(hasV7Ops() && (isTargetLinux() || isTargetNaCl() ||
244
isTargetNetBSD())) ||
245
(hasV6Ops() && (isTargetMachO() || isTargetNetBSD()));
247
AllowsUnalignedMem = !(Align == StrictAlign);
250
// No v6M core supports unaligned memory access (v6M ARM ARM A3.2)
252
AllowsUnalignedMem = false;
256
RestrictIT = hasV8Ops();
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;
273
bool ARMSubtarget::isAPCS_ABI() const {
274
assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
275
return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_APCS;
277
bool ARMSubtarget::isAAPCS_ABI() const {
278
assert(TM.TargetABI != ARMBaseTargetMachine::ARM_ABI_UNKNOWN);
279
return TM.TargetABI == ARMBaseTargetMachine::ARM_ABI_AAPCS;
282
/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol.
284
ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
285
Reloc::Model RelocM) const {
286
if (RelocM == Reloc::Static)
289
bool isDef = GV->isStrongDefinitionForLinker();
291
if (!isTargetMachO()) {
292
// Extra load is needed for all externally visible.
293
if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
297
// If this is a strong reference to a definition, it is definitely not
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.
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.
319
unsigned ARMSubtarget::getMispredictionPenalty() const {
320
return SchedModel.MispredictPenalty;
323
bool ARMSubtarget::hasSinCos() const {
324
return getTargetTriple().isiOS() && !getTargetTriple().isOSVersionLT(7, 0);
327
// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
328
bool ARMSubtarget::enablePostRAScheduler() const {
329
return (!isThumb() || hasThumb2());
332
bool ARMSubtarget::enableAtomicExpand() const {
333
return hasAnyDataBarrier() && !isThumb1Only();
336
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
340
return UseMovt && (isTargetWindows() ||
341
!MF.getFunction()->hasFnAttribute(Attribute::MinSize));
344
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()));