X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FARM%2FARMSubtarget.cpp;h=e11314d4fcd2745bdab617dccd1fcf0d1f57e8aa;hb=9be8b4fc92e1ace819a78db512c1f945c1471be7;hp=8df59e4789e34e9f6c177beab8868b32f446ac34;hpb=65cef00142c9a187707c56a293ae794765f7463b;p=oota-llvm.git diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 8df59e4789e..e11314d4fcd 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -1,4 +1,4 @@ -//===-- ARMSubtarget.cpp - ARM Subtarget Information ------------*- C++ -*-===// +//===-- ARMSubtarget.cpp - ARM Subtarget Information ----------------------===// // // The LLVM Compiler Infrastructure // @@ -7,144 +7,175 @@ // //===----------------------------------------------------------------------===// // -// This file implements the ARM specific subclass of TargetSubtarget. +// This file implements the ARM specific subclass of TargetSubtargetInfo. // //===----------------------------------------------------------------------===// #include "ARMSubtarget.h" -#include "ARMGenSubtarget.inc" -#include "llvm/GlobalValue.h" -#include "llvm/Target/TargetOptions.h" +#include "ARMBaseInstrInfo.h" +#include "ARMBaseRegisterInfo.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/Target/TargetInstrInfo.h" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "ARMGenSubtargetInfo.inc" + using namespace llvm; static cl::opt ReserveR9("arm-reserve-r9", cl::Hidden, cl::desc("Reserve R9, making it unavailable as GPR")); + static cl::opt -UseNEONFP("arm-use-neon-fp", - cl::desc("Use NEON for single-precision FP"), - cl::init(false), cl::Hidden); +DarwinUseMOVT("arm-darwin-use-movt", cl::init(true), cl::Hidden); + static cl::opt -UseVMLxInstructions("arm-use-vmlx", - cl::desc("Use VFP vmla and vmls instructions"), - cl::init(true), cl::Hidden); +UseFusedMulOps("arm-use-mulops", + cl::init(true), cl::Hidden); static cl::opt -UseMOVT("arm-use-movt", - cl::init(true), cl::Hidden); - -ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, - bool isT) - : ARMArchVersion(V4) - , ARMFPUType(None) - , UseNEONForSinglePrecisionFP(UseNEONFP) - , UseVMLx(UseVMLxInstructions) - , IsThumb(isT) - , ThumbMode(Thumb1) - , PostRAScheduler(false) - , IsR9Reserved(ReserveR9) - , UseMovt(UseMOVT) - , HasFP16(false) +StrictAlign("arm-strict-align", cl::Hidden, + cl::desc("Disallow all unaligned memory accesses")); + +ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &CPU, + const std::string &FS) + : ARMGenSubtargetInfo(TT, CPU, FS) + , ARMProcFamily(Others) , stackAlignment(4) - , CPUString("generic") - , TargetType(isELF) // Default to ELF unless otherwise specified. + , CPUString(CPU) + , TargetTriple(TT) , TargetABI(ARM_ABI_APCS) { - // default to soft float ABI - if (FloatABIType == FloatABI::Default) - FloatABIType = FloatABI::Soft; - - // Determine default and user specified characteristics - - // Parse features string. - CPUString = ParseSubtargetFeatures(FS, CPUString); - - // When no arch is specified either by CPU or by attributes, make the default - // ARMv4T. - if (CPUString == "generic" && (FS.empty() || FS == "generic")) - ARMArchVersion = V4T; - - // Set the boolean corresponding to the current target triple, or the default - // if one cannot be determined, to true. - unsigned Len = TT.length(); - unsigned Idx = 0; - - if (Len >= 5 && TT.substr(0, 4) == "armv") - Idx = 4; - else if (Len >= 6 && TT.substr(0, 5) == "thumb") { - IsThumb = true; - if (Len >= 7 && TT[5] == 'v') - Idx = 6; + initializeEnvironment(); + resetSubtargetFeatures(CPU, FS); +} + +void ARMSubtarget::initializeEnvironment() { + HasV4TOps = false; + HasV5TOps = false; + HasV5TEOps = false; + HasV6Ops = false; + HasV6T2Ops = false; + HasV7Ops = false; + HasVFPv2 = false; + HasVFPv3 = false; + HasVFPv4 = false; + HasNEON = false; + UseNEONForSinglePrecisionFP = false; + UseMulOps = UseFusedMulOps; + SlowFPVMLx = false; + HasVMLxForwarding = false; + SlowFPBrcc = false; + InThumbMode = false; + HasThumb2 = false; + IsMClass = false; + NoARM = false; + PostRAScheduler = 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; + FPOnlySP = false; + AllowsUnalignedMem = false; + Thumb2DSP = false; + UseNaClTrap = false; +} + +void ARMSubtarget::resetSubtargetFeatures(const MachineFunction *MF) { + AttributeSet FnAttrs = MF->getFunction()->getAttributes(); + Attribute CPUAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, + "target-cpu"); + Attribute FSAttr = FnAttrs.getAttribute(AttributeSet::FunctionIndex, + "target-features"); + std::string CPU = + !CPUAttr.hasAttribute(Attribute::None) ?CPUAttr.getValueAsString() : ""; + std::string FS = + !FSAttr.hasAttribute(Attribute::None) ? FSAttr.getValueAsString() : ""; + if (!FS.empty()) { + initializeEnvironment(); + resetSubtargetFeatures(CPU, FS); } - if (Idx) { - unsigned SubVer = TT[Idx]; - if (SubVer >= '7' && SubVer <= '9') { - ARMArchVersion = V7A; - } else if (SubVer == '6') { - ARMArchVersion = V6; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') - ARMArchVersion = V6T2; - } else if (SubVer == '5') { - ARMArchVersion = V5T; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') - ARMArchVersion = V5TE; - } else if (SubVer == '4') { - if (Len >= Idx+2 && TT[Idx+1] == 't') - ARMArchVersion = V4T; - else - ARMArchVersion = V4; - } +} + +void ARMSubtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) { + if (CPUString.empty()) + 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.getTriple(), + CPUString); + if (!FS.empty()) { + if (!ArchFS.empty()) + ArchFS = ArchFS + "," + FS.str(); + else + ArchFS = FS; } + ParseSubtargetFeatures(CPUString, ArchFS); - // Thumb2 implies at least V6T2. - if (ARMArchVersion >= V6T2) - ThumbMode = Thumb2; - else if (ThumbMode >= Thumb2) - ARMArchVersion = V6T2; + // Thumb2 implies at least V6T2. FIXME: Fix tests to explicitly specify a + // ARM version or CPU and then remove this. + if (!HasV6T2Ops && hasThumb2()) + HasV4TOps = HasV5TOps = HasV5TEOps = HasV6Ops = HasV6T2Ops = true; - if (Len >= 10) { - if (TT.find("-darwin") != std::string::npos) - // arm-darwin - TargetType = isDarwin; - } + // Keep a pointer to static instruction cost data for the specified CPU. + SchedModel = getSchedModelForCPU(CPUString); - if (TT.find("eabi") != std::string::npos) + // Initialize scheduling itinerary for the specified CPU. + InstrItins = getInstrItineraryForCPU(CPUString); + + if ((TargetTriple.getTriple().find("eabi") != std::string::npos) || + (isTargetIOS() && isMClass())) + // FIXME: We might want to separate AAPCS and EABI. Some systems, e.g. + // Darwin-EABI conforms to AACPS but not the rest of EABI. TargetABI = ARM_ABI_AAPCS; if (isAAPCS_ABI()) stackAlignment = 8; - if (isTargetDarwin()) - IsR9Reserved = ReserveR9 | (ARMArchVersion < V6); + if (!isTargetIOS()) + UseMovt = hasV6T2Ops(); + else { + IsR9Reserved = ReserveR9 | !HasV6Ops; + UseMovt = DarwinUseMOVT && hasV6T2Ops(); + SupportsTailCall = !getTargetTriple().isOSVersionLT(5, 0); + } if (!isThumb() || hasThumb2()) PostRAScheduler = true; - // Set CPU specific features. - if (CPUString == "cortex-a8") { - // On Cortex-a8, it's faster to perform some single-precision FP - // operations with NEON instructions. - if (UseNEONFP.getPosition() == 0) - UseNEONForSinglePrecisionFP = true; - // The VFP vlma and vlms instructions don't play nicely with others; - // disable them. - // FIXME: This may be true for other variants as well. Get benchmark - // numbers and add them if determined that's the case. - if (UseVMLxInstructions.getPosition() == 0) - UseVMLx = false; - } + // v6+ may or may not support unaligned mem access depending on the system + // configuration. + if (!StrictAlign && hasV6Ops() && isTargetDarwin()) + AllowsUnalignedMem = true; } /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. bool -ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const { +ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV, + Reloc::Model RelocM) const { if (RelocM == Reloc::Static) return false; // Materializable GVs (in JIT lazy compilation mode) do not require an extra // load from stub. - bool isDecl = GV->isDeclaration() && !GV->isMaterializable(); + bool isDecl = GV->hasAvailableExternallyLinkage(); + if (GV->isDeclaration() && !GV->isMaterializable()) + isDecl = true; if (!isTargetDarwin()) { // Extra load is needed for all externally visible. @@ -175,7 +206,7 @@ ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const { // through a stub. if (!isDecl && !GV->isWeakForLinker()) 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. @@ -186,11 +217,15 @@ ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const { return false; } +unsigned ARMSubtarget::getMispredictionPenalty() const { + return SchedModel->MispredictPenalty; +} + bool ARMSubtarget::enablePostRAScheduler( CodeGenOpt::Level OptLevel, - TargetSubtarget::AntiDepBreakMode& Mode, + TargetSubtargetInfo::AntiDepBreakMode& Mode, RegClassVector& CriticalPathRCs) const { - Mode = TargetSubtarget::ANTIDEP_CRITICAL; + Mode = TargetSubtargetInfo::ANTIDEP_CRITICAL; CriticalPathRCs.clear(); CriticalPathRCs.push_back(&ARM::GPRRegClass); return PostRAScheduler && OptLevel >= CodeGenOpt::Default;