1dff0c46cSDimitry Andric //===-- PowerPCSubtarget.cpp - PPC Subtarget Information ------------------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
1017a519f9SDimitry Andric // This file implements the PPC specific subclass of TargetSubtargetInfo.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
13f22ef01cSRoman Divacky 
14f22ef01cSRoman Divacky #include "PPCSubtarget.h"
15f22ef01cSRoman Divacky #include "PPC.h"
16139f7f9bSDimitry Andric #include "PPCRegisterInfo.h"
17ff0cc061SDimitry Andric #include "PPCTargetMachine.h"
18f785676fSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
19f785676fSDimitry Andric #include "llvm/CodeGen/MachineScheduler.h"
20f785676fSDimitry Andric #include "llvm/IR/Attributes.h"
21f785676fSDimitry Andric #include "llvm/IR/Function.h"
2291bc56edSDimitry Andric #include "llvm/IR/GlobalValue.h"
2339d628a0SDimitry Andric #include "llvm/Support/CommandLine.h"
246122f3e6SDimitry Andric #include "llvm/Support/TargetRegistry.h"
25139f7f9bSDimitry Andric #include "llvm/Target/TargetMachine.h"
26f22ef01cSRoman Divacky #include <cstdlib>
2717a519f9SDimitry Andric 
2891bc56edSDimitry Andric using namespace llvm;
2991bc56edSDimitry Andric 
3091bc56edSDimitry Andric #define DEBUG_TYPE "ppc-subtarget"
3191bc56edSDimitry Andric 
3217a519f9SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
3317a519f9SDimitry Andric #define GET_SUBTARGETINFO_CTOR
3417a519f9SDimitry Andric #include "PPCGenSubtargetInfo.inc"
3517a519f9SDimitry Andric 
3639d628a0SDimitry Andric static cl::opt<bool> UseSubRegLiveness("ppc-track-subreg-liveness",
3739d628a0SDimitry Andric cl::desc("Enable subregister liveness tracking for PPC"), cl::Hidden);
38f22ef01cSRoman Divacky 
39ff0cc061SDimitry Andric static cl::opt<bool> QPXStackUnaligned("qpx-stack-unaligned",
40ff0cc061SDimitry Andric   cl::desc("Even when QPX is enabled the stack is not 32-byte aligned"),
41ff0cc061SDimitry Andric   cl::Hidden);
4291bc56edSDimitry Andric 
initializeSubtargetDependencies(StringRef CPU,StringRef FS)4391bc56edSDimitry Andric PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU,
4491bc56edSDimitry Andric                                                             StringRef FS) {
45f785676fSDimitry Andric   initializeEnvironment();
4639d628a0SDimitry Andric   initSubtargetFeatures(CPU, FS);
4791bc56edSDimitry Andric   return *this;
48f785676fSDimitry Andric }
49f22ef01cSRoman Divacky 
PPCSubtarget(const Triple & TT,const std::string & CPU,const std::string & FS,const PPCTargetMachine & TM)508f0fd8f6SDimitry Andric PPCSubtarget::PPCSubtarget(const Triple &TT, const std::string &CPU,
5139d628a0SDimitry Andric                            const std::string &FS, const PPCTargetMachine &TM)
5239d628a0SDimitry Andric     : PPCGenSubtargetInfo(TT, CPU, FS), TargetTriple(TT),
5339d628a0SDimitry Andric       IsPPC64(TargetTriple.getArch() == Triple::ppc64 ||
5439d628a0SDimitry Andric               TargetTriple.getArch() == Triple::ppc64le),
55ff0cc061SDimitry Andric       TM(TM), FrameLowering(initializeSubtargetDependencies(CPU, FS)),
56875ed548SDimitry Andric       InstrInfo(*this), TLInfo(TM, *this) {}
5791bc56edSDimitry Andric 
initializeEnvironment()58f785676fSDimitry Andric void PPCSubtarget::initializeEnvironment() {
59f785676fSDimitry Andric   StackAlignment = 16;
60f785676fSDimitry Andric   DarwinDirective = PPC::DIR_NONE;
61f785676fSDimitry Andric   HasMFOCRF = false;
62f785676fSDimitry Andric   Has64BitSupport = false;
63f785676fSDimitry Andric   Use64BitRegs = false;
6491bc56edSDimitry Andric   UseCRBits = false;
6511c1fce8SDimitry Andric   HasHardFloat = false;
66f785676fSDimitry Andric   HasAltivec = false;
6739d628a0SDimitry Andric   HasSPE = false;
684ba319b5SDimitry Andric   HasFPU = false;
69f785676fSDimitry Andric   HasQPX = false;
7091bc56edSDimitry Andric   HasVSX = false;
7139d628a0SDimitry Andric   HasP8Vector = false;
72ff0cc061SDimitry Andric   HasP8Altivec = false;
73ff0cc061SDimitry Andric   HasP8Crypto = false;
743ca95b02SDimitry Andric   HasP9Vector = false;
753ca95b02SDimitry Andric   HasP9Altivec = false;
76f785676fSDimitry Andric   HasFCPSGN = false;
77f785676fSDimitry Andric   HasFSQRT = false;
78f785676fSDimitry Andric   HasFRE = false;
79f785676fSDimitry Andric   HasFRES = false;
80f785676fSDimitry Andric   HasFRSQRTE = false;
81f785676fSDimitry Andric   HasFRSQRTES = false;
82f785676fSDimitry Andric   HasRecipPrec = false;
83f785676fSDimitry Andric   HasSTFIWX = false;
84f785676fSDimitry Andric   HasLFIWAX = false;
85f785676fSDimitry Andric   HasFPRND = false;
86f785676fSDimitry Andric   HasFPCVT = false;
87f785676fSDimitry Andric   HasISEL = false;
88ff0cc061SDimitry Andric   HasBPERMD = false;
89ff0cc061SDimitry Andric   HasExtDiv = false;
9039d628a0SDimitry Andric   HasCMPB = false;
91f785676fSDimitry Andric   HasLDBRX = false;
92f785676fSDimitry Andric   IsBookE = false;
9339d628a0SDimitry Andric   HasOnlyMSYNC = false;
9439d628a0SDimitry Andric   IsPPC4xx = false;
9539d628a0SDimitry Andric   IsPPC6xx = false;
9639d628a0SDimitry Andric   IsE500 = false;
978f0fd8f6SDimitry Andric   FeatureMFTB = false;
98f785676fSDimitry Andric   DeprecatedDST = false;
99f785676fSDimitry Andric   HasLazyResolverStubs = false;
100ff0cc061SDimitry Andric   HasICBT = false;
101ff0cc061SDimitry Andric   HasInvariantFunctionDescriptors = false;
102ff0cc061SDimitry Andric   HasPartwordAtomics = false;
103ff0cc061SDimitry Andric   HasDirectMove = false;
104ff0cc061SDimitry Andric   IsQPXStackUnaligned = false;
105ff0cc061SDimitry Andric   HasHTM = false;
1067d523365SDimitry Andric   HasFusion = false;
1077d523365SDimitry Andric   HasFloat128 = false;
1083ca95b02SDimitry Andric   IsISA3_0 = false;
109b6054a7bSDimitry Andric   UseLongCalls = false;
1104ba319b5SDimitry Andric   SecurePlt = false;
1113ca95b02SDimitry Andric 
1123ca95b02SDimitry Andric   HasPOPCNTD = POPCNTD_Unavailable;
113f785676fSDimitry Andric }
114f785676fSDimitry Andric 
initSubtargetFeatures(StringRef CPU,StringRef FS)11539d628a0SDimitry Andric void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
116f22ef01cSRoman Divacky   // Determine default and user specified characteristics
11717a519f9SDimitry Andric   std::string CPUName = CPU;
1183ca95b02SDimitry Andric   if (CPUName.empty() || CPU == "generic") {
119ff0cc061SDimitry Andric     // If cross-compiling with -march=ppc64le without -mcpu
120ff0cc061SDimitry Andric     if (TargetTriple.getArch() == Triple::ppc64le)
121ff0cc061SDimitry Andric       CPUName = "ppc64le";
122ff0cc061SDimitry Andric     else
12317a519f9SDimitry Andric       CPUName = "generic";
124ff0cc061SDimitry Andric   }
125f22ef01cSRoman Divacky 
12617a519f9SDimitry Andric   // Initialize scheduling itinerary for the specified CPU.
12717a519f9SDimitry Andric   InstrItins = getInstrItineraryForCPU(CPUName);
128f22ef01cSRoman Divacky 
1293861d79fSDimitry Andric   // Parse features string.
13039d628a0SDimitry Andric   ParseSubtargetFeatures(CPUName, FS);
1313861d79fSDimitry Andric 
132f22ef01cSRoman Divacky   // If the user requested use of 64-bit regs, but the cpu selected doesn't
133f22ef01cSRoman Divacky   // support it, ignore.
13439d628a0SDimitry Andric   if (IsPPC64 && has64BitSupport())
13539d628a0SDimitry Andric     Use64BitRegs = true;
136f22ef01cSRoman Divacky 
137f22ef01cSRoman Divacky   // Set up darwin-specific properties.
138f22ef01cSRoman Divacky   if (isDarwin())
139f22ef01cSRoman Divacky     HasLazyResolverStubs = true;
140139f7f9bSDimitry Andric 
141*85573313SDimitry Andric   if ((TargetTriple.isOSFreeBSD() && TargetTriple.getOSMajorVersion() >= 13)
142*85573313SDimitry Andric       || TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD())
143*85573313SDimitry Andric     SecurePlt = true;
144*85573313SDimitry Andric 
1454ba319b5SDimitry Andric   if (HasSPE && IsPPC64)
1464ba319b5SDimitry Andric     report_fatal_error( "SPE is only supported for 32-bit targets.\n", false);
1474ba319b5SDimitry Andric   if (HasSPE && (HasAltivec || HasQPX || HasVSX || HasFPU))
1484ba319b5SDimitry Andric     report_fatal_error(
1494ba319b5SDimitry Andric         "SPE and traditional floating point cannot both be enabled.\n", false);
1504ba319b5SDimitry Andric 
1514ba319b5SDimitry Andric   // If not SPE, set standard FPU
1524ba319b5SDimitry Andric   if (!HasSPE)
1534ba319b5SDimitry Andric     HasFPU = true;
1544ba319b5SDimitry Andric 
155139f7f9bSDimitry Andric   // QPX requires a 32-byte aligned stack. Note that we need to do this if
156139f7f9bSDimitry Andric   // we're compiling for a BG/Q system regardless of whether or not QPX
157139f7f9bSDimitry Andric   // is enabled because external functions will assume this alignment.
158ff0cc061SDimitry Andric   IsQPXStackUnaligned = QPXStackUnaligned;
159ff0cc061SDimitry Andric   StackAlignment = getPlatformStackAlignment();
160f785676fSDimitry Andric 
161f785676fSDimitry Andric   // Determine endianness.
162ff0cc061SDimitry Andric   // FIXME: Part of the TargetMachine.
163f785676fSDimitry Andric   IsLittleEndian = (TargetTriple.getArch() == Triple::ppc64le);
164f22ef01cSRoman Divacky }
165f22ef01cSRoman Divacky 
1663ca95b02SDimitry Andric /// Return true if accesses to the specified global have to go through a dyld
1673ca95b02SDimitry Andric /// lazy resolution stub.  This means that an extra load is required to get the
1683ca95b02SDimitry Andric /// address of the global.
hasLazyResolverStub(const GlobalValue * GV) const169ff0cc061SDimitry Andric bool PPCSubtarget::hasLazyResolverStub(const GlobalValue *GV) const {
1703ca95b02SDimitry Andric   if (!HasLazyResolverStubs)
171f22ef01cSRoman Divacky     return false;
1723ca95b02SDimitry Andric   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
1733ca95b02SDimitry Andric     return true;
1743ca95b02SDimitry Andric   // 32 bit macho has no relocation for a-b if a is undefined, even if b is in
1753ca95b02SDimitry Andric   // the section that is being relocated. This means we have to use o load even
1763ca95b02SDimitry Andric   // for GVs that are known to be local to the dso.
1773ca95b02SDimitry Andric   if (GV->isDeclarationForLinker() || GV->hasCommonLinkage())
1783ca95b02SDimitry Andric     return true;
179f22ef01cSRoman Divacky   return false;
180f22ef01cSRoman Divacky }
181dff0c46cSDimitry Andric 
enableMachineScheduler() const182f785676fSDimitry Andric bool PPCSubtarget::enableMachineScheduler() const {
1834ba319b5SDimitry Andric   return true;
184f785676fSDimitry Andric }
185f785676fSDimitry Andric 
18691bc56edSDimitry Andric // This overrides the PostRAScheduler bit in the SchedModel for each CPU.
enablePostRAScheduler() const1878f0fd8f6SDimitry Andric bool PPCSubtarget::enablePostRAScheduler() const { return true; }
18891bc56edSDimitry Andric 
getAntiDepBreakMode() const18991bc56edSDimitry Andric PPCGenSubtargetInfo::AntiDepBreakMode PPCSubtarget::getAntiDepBreakMode() const {
19091bc56edSDimitry Andric   return TargetSubtargetInfo::ANTIDEP_ALL;
19191bc56edSDimitry Andric }
19291bc56edSDimitry Andric 
getCriticalPathRCs(RegClassVector & CriticalPathRCs) const19391bc56edSDimitry Andric void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
19491bc56edSDimitry Andric   CriticalPathRCs.clear();
19591bc56edSDimitry Andric   CriticalPathRCs.push_back(isPPC64() ?
19691bc56edSDimitry Andric                             &PPC::G8RCRegClass : &PPC::GPRCRegClass);
19791bc56edSDimitry Andric }
19891bc56edSDimitry Andric 
overrideSchedPolicy(MachineSchedPolicy & Policy,unsigned NumRegionInstrs) const199f785676fSDimitry Andric void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
200f785676fSDimitry Andric                                        unsigned NumRegionInstrs) const {
2014ba319b5SDimitry Andric   // The GenericScheduler that we use defaults to scheduling bottom up only.
2024ba319b5SDimitry Andric   // We want to schedule from both the top and the bottom and so we set
2034ba319b5SDimitry Andric   // OnlyBottomUp to false.
2044ba319b5SDimitry Andric   // We want to do bi-directional scheduling since it provides a more balanced
2054ba319b5SDimitry Andric   // schedule leading to better performance.
206f785676fSDimitry Andric   Policy.OnlyBottomUp = false;
207f785676fSDimitry Andric   // Spilling is generally expensive on all PPC cores, so always enable
208f785676fSDimitry Andric   // register-pressure tracking.
209f785676fSDimitry Andric   Policy.ShouldTrackPressure = true;
210f785676fSDimitry Andric }
211f785676fSDimitry Andric 
useAA() const212f785676fSDimitry Andric bool PPCSubtarget::useAA() const {
2134ba319b5SDimitry Andric   return true;
214f785676fSDimitry Andric }
215f785676fSDimitry Andric 
enableSubRegLiveness() const21639d628a0SDimitry Andric bool PPCSubtarget::enableSubRegLiveness() const {
21739d628a0SDimitry Andric   return UseSubRegLiveness;
21839d628a0SDimitry Andric }
21939d628a0SDimitry Andric 
2207a7e6055SDimitry Andric unsigned char
classifyGlobalReference(const GlobalValue * GV) const2217a7e6055SDimitry Andric PPCSubtarget::classifyGlobalReference(const GlobalValue *GV) const {
2227d523365SDimitry Andric   // Note that currently we don't generate non-pic references.
2237d523365SDimitry Andric   // If a caller wants that, this will have to be updated.
2247d523365SDimitry Andric 
2257d523365SDimitry Andric   // Large code model always uses the TOC even for local symbols.
2267d523365SDimitry Andric   if (TM.getCodeModel() == CodeModel::Large)
2277d523365SDimitry Andric     return PPCII::MO_PIC_FLAG | PPCII::MO_NLP_FLAG;
2287d523365SDimitry Andric 
2297a7e6055SDimitry Andric   if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
2307a7e6055SDimitry Andric     return PPCII::MO_PIC_FLAG;
2317a7e6055SDimitry Andric   return PPCII::MO_PIC_FLAG | PPCII::MO_NLP_FLAG;
2327d523365SDimitry Andric }
2337d523365SDimitry Andric 
isELFv2ABI() const234ff0cc061SDimitry Andric bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); }
isPPC64() const235ff0cc061SDimitry Andric bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); }
236