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