xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- PowerPCSubtarget.cpp - PPC Subtarget Information ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the PPC specific subclass of TargetSubtargetInfo.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "PPCSubtarget.h"
14e8d8bef9SDimitry Andric #include "GISel/PPCCallLowering.h"
15e8d8bef9SDimitry Andric #include "GISel/PPCLegalizerInfo.h"
16e8d8bef9SDimitry Andric #include "GISel/PPCRegisterBankInfo.h"
170b57cec5SDimitry Andric #include "PPC.h"
180b57cec5SDimitry Andric #include "PPCRegisterInfo.h"
190b57cec5SDimitry Andric #include "PPCTargetMachine.h"
20e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
2181ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h"
240b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
250b57cec5SDimitry Andric #include "llvm/IR/Function.h"
26*0fca6ea1SDimitry Andric #include "llvm/IR/GlobalAlias.h"
270b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
28*0fca6ea1SDimitry Andric #include "llvm/IR/GlobalVariable.h"
29349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
300b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
310b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
320b57cec5SDimitry Andric #include <cstdlib>
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric using namespace llvm;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-subtarget"
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
390b57cec5SDimitry Andric #define GET_SUBTARGETINFO_CTOR
400b57cec5SDimitry Andric #include "PPCGenSubtargetInfo.inc"
410b57cec5SDimitry Andric 
42bdd1243dSDimitry Andric static cl::opt<bool>
430b57cec5SDimitry Andric     EnableMachinePipeliner("ppc-enable-pipeliner",
440b57cec5SDimitry Andric                            cl::desc("Enable Machine Pipeliner for PPC"),
450b57cec5SDimitry Andric                            cl::init(false), cl::Hidden);
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU,
48bdd1243dSDimitry Andric                                                             StringRef TuneCPU,
490b57cec5SDimitry Andric                                                             StringRef FS) {
500b57cec5SDimitry Andric   initializeEnvironment();
51bdd1243dSDimitry Andric   initSubtargetFeatures(CPU, TuneCPU, FS);
520b57cec5SDimitry Andric   return *this;
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric PPCSubtarget::PPCSubtarget(const Triple &TT, const std::string &CPU,
56bdd1243dSDimitry Andric                            const std::string &TuneCPU, const std::string &FS,
57bdd1243dSDimitry Andric                            const PPCTargetMachine &TM)
58bdd1243dSDimitry Andric     : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), TargetTriple(TT),
590b57cec5SDimitry Andric       IsPPC64(TargetTriple.getArch() == Triple::ppc64 ||
600b57cec5SDimitry Andric               TargetTriple.getArch() == Triple::ppc64le),
61bdd1243dSDimitry Andric       TM(TM), FrameLowering(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
62e8d8bef9SDimitry Andric       InstrInfo(*this), TLInfo(TM, *this) {
63e8d8bef9SDimitry Andric   CallLoweringInfo.reset(new PPCCallLowering(*getTargetLowering()));
64e8d8bef9SDimitry Andric   Legalizer.reset(new PPCLegalizerInfo(*this));
65e8d8bef9SDimitry Andric   auto *RBI = new PPCRegisterBankInfo(*getRegisterInfo());
66e8d8bef9SDimitry Andric   RegBankInfo.reset(RBI);
67e8d8bef9SDimitry Andric 
68*0fca6ea1SDimitry Andric   InstSelector.reset(createPPCInstructionSelector(TM, *this, *RBI));
69e8d8bef9SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric void PPCSubtarget::initializeEnvironment() {
728bcb0991SDimitry Andric   StackAlignment = Align(16);
73480093f4SDimitry Andric   CPUDirective = PPC::DIR_NONE;
740b57cec5SDimitry Andric   HasPOPCNTD = POPCNTD_Unavailable;
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
77bdd1243dSDimitry Andric void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
78bdd1243dSDimitry Andric                                          StringRef FS) {
790b57cec5SDimitry Andric   // Determine default and user specified characteristics
805ffd83dbSDimitry Andric   std::string CPUName = std::string(CPU);
810b57cec5SDimitry Andric   if (CPUName.empty() || CPU == "generic") {
820b57cec5SDimitry Andric     // If cross-compiling with -march=ppc64le without -mcpu
830b57cec5SDimitry Andric     if (TargetTriple.getArch() == Triple::ppc64le)
840b57cec5SDimitry Andric       CPUName = "ppc64le";
85f8e1cfadSDimitry Andric     else if (TargetTriple.getSubArch() == Triple::PPCSubArch_spe)
86f8e1cfadSDimitry Andric       CPUName = "e500";
870b57cec5SDimitry Andric     else
880b57cec5SDimitry Andric       CPUName = "generic";
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric 
91bdd1243dSDimitry Andric   // Determine the CPU to schedule for.
92bdd1243dSDimitry Andric   if (TuneCPU.empty()) TuneCPU = CPUName;
93bdd1243dSDimitry Andric 
940b57cec5SDimitry Andric   // Initialize scheduling itinerary for the specified CPU.
950b57cec5SDimitry Andric   InstrItins = getInstrItineraryForCPU(CPUName);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   // Parse features string.
98bdd1243dSDimitry Andric   ParseSubtargetFeatures(CPUName, TuneCPU, FS);
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   // If the user requested use of 64-bit regs, but the cpu selected doesn't
1010b57cec5SDimitry Andric   // support it, ignore.
1020b57cec5SDimitry Andric   if (IsPPC64 && has64BitSupport())
1030b57cec5SDimitry Andric     Use64BitRegs = true;
1040b57cec5SDimitry Andric 
10506c3fb27SDimitry Andric   if (TargetTriple.isPPC32SecurePlt())
106bdd1243dSDimitry Andric     IsSecurePlt = true;
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   if (HasSPE && IsPPC64)
1090b57cec5SDimitry Andric     report_fatal_error( "SPE is only supported for 32-bit targets.\n", false);
110e8d8bef9SDimitry Andric   if (HasSPE && (HasAltivec || HasVSX || HasFPU))
1110b57cec5SDimitry Andric     report_fatal_error(
1120b57cec5SDimitry Andric         "SPE and traditional floating point cannot both be enabled.\n", false);
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   // If not SPE, set standard FPU
1150b57cec5SDimitry Andric   if (!HasSPE)
1160b57cec5SDimitry Andric     HasFPU = true;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   StackAlignment = getPlatformStackAlignment();
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   // Determine endianness.
121fe6060f1SDimitry Andric   IsLittleEndian = TM.isLittleEndian();
1225f757f3fSDimitry Andric 
123*0fca6ea1SDimitry Andric   if (HasAIXSmallLocalExecTLS || HasAIXSmallLocalDynamicTLS) {
124*0fca6ea1SDimitry Andric     if (!TargetTriple.isOSAIX() || !IsPPC64)
125*0fca6ea1SDimitry Andric       report_fatal_error("The aix-small-local-[exec|dynamic]-tls attribute is "
126*0fca6ea1SDimitry Andric                          "only supported on AIX in "
127*0fca6ea1SDimitry Andric                          "64-bit mode.\n",
128*0fca6ea1SDimitry Andric                          false);
129*0fca6ea1SDimitry Andric     // The aix-small-local-[exec|dynamic]-tls attribute should only be used with
130*0fca6ea1SDimitry Andric     // -data-sections, as having data sections turned off with this option
131*0fca6ea1SDimitry Andric     // is not ideal for performance. Moreover, the
132*0fca6ea1SDimitry Andric     // small-local-[exec|dynamic]-tls region is a limited resource, and should
133*0fca6ea1SDimitry Andric     // not be used for variables that may be replaced.
134*0fca6ea1SDimitry Andric     if (!TM.getDataSections())
135*0fca6ea1SDimitry Andric       report_fatal_error("The aix-small-local-[exec|dynamic]-tls attribute can "
136*0fca6ea1SDimitry Andric                          "only be specified with "
137*0fca6ea1SDimitry Andric                          "-data-sections.\n",
138*0fca6ea1SDimitry Andric                          false);
139*0fca6ea1SDimitry Andric   }
140*0fca6ea1SDimitry Andric 
141*0fca6ea1SDimitry Andric   if (HasAIXShLibTLSModelOpt && (!TargetTriple.isOSAIX() || !IsPPC64))
142*0fca6ea1SDimitry Andric     report_fatal_error("The aix-shared-lib-tls-model-opt attribute "
143*0fca6ea1SDimitry Andric                        "is only supported on AIX in 64-bit mode.\n",
144*0fca6ea1SDimitry Andric                        false);
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric bool PPCSubtarget::enableMachineScheduler() const { return true; }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric bool PPCSubtarget::enableMachinePipeliner() const {
1505ffd83dbSDimitry Andric   return getSchedModel().hasInstrSchedModel() && EnableMachinePipeliner;
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric bool PPCSubtarget::useDFAforSMS() const { return false; }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric // This overrides the PostRAScheduler bit in the SchedModel for each CPU.
1560b57cec5SDimitry Andric bool PPCSubtarget::enablePostRAScheduler() const { return true; }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric PPCGenSubtargetInfo::AntiDepBreakMode PPCSubtarget::getAntiDepBreakMode() const {
1590b57cec5SDimitry Andric   return TargetSubtargetInfo::ANTIDEP_ALL;
1600b57cec5SDimitry Andric }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
1630b57cec5SDimitry Andric   CriticalPathRCs.clear();
1640b57cec5SDimitry Andric   CriticalPathRCs.push_back(isPPC64() ?
1650b57cec5SDimitry Andric                             &PPC::G8RCRegClass : &PPC::GPRCRegClass);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
1690b57cec5SDimitry Andric                                        unsigned NumRegionInstrs) const {
1700b57cec5SDimitry Andric   // The GenericScheduler that we use defaults to scheduling bottom up only.
1710b57cec5SDimitry Andric   // We want to schedule from both the top and the bottom and so we set
1720b57cec5SDimitry Andric   // OnlyBottomUp to false.
1730b57cec5SDimitry Andric   // We want to do bi-directional scheduling since it provides a more balanced
1740b57cec5SDimitry Andric   // schedule leading to better performance.
1750b57cec5SDimitry Andric   Policy.OnlyBottomUp = false;
1760b57cec5SDimitry Andric   // Spilling is generally expensive on all PPC cores, so always enable
1770b57cec5SDimitry Andric   // register-pressure tracking.
1780b57cec5SDimitry Andric   Policy.ShouldTrackPressure = true;
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric bool PPCSubtarget::useAA() const {
1820b57cec5SDimitry Andric   return true;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric 
185*0fca6ea1SDimitry Andric bool PPCSubtarget::enableSubRegLiveness() const { return true; }
1860b57cec5SDimitry Andric 
1878bcb0991SDimitry Andric bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
188*0fca6ea1SDimitry Andric   if (isAIXABI()) {
189*0fca6ea1SDimitry Andric     if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
190*0fca6ea1SDimitry Andric       // On AIX the only symbols that aren't indirect are toc-data.
191*0fca6ea1SDimitry Andric       return !GVar->hasAttribute("toc-data");
192*0fca6ea1SDimitry Andric 
193*0fca6ea1SDimitry Andric     return true;
194*0fca6ea1SDimitry Andric   }
195*0fca6ea1SDimitry Andric 
1960b57cec5SDimitry Andric   // Large code model always uses the TOC even for local symbols.
1970b57cec5SDimitry Andric   if (TM.getCodeModel() == CodeModel::Large)
1988bcb0991SDimitry Andric     return true;
199*0fca6ea1SDimitry Andric 
200*0fca6ea1SDimitry Andric   if (TM.shouldAssumeDSOLocal(GV))
2018bcb0991SDimitry Andric     return false;
2028bcb0991SDimitry Andric   return true;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
205*0fca6ea1SDimitry Andric CodeModel::Model PPCSubtarget::getCodeModel(const TargetMachine &TM,
206*0fca6ea1SDimitry Andric                                             const GlobalValue *GV) const {
207*0fca6ea1SDimitry Andric   // If there isn't an attribute to override the module code model
208*0fca6ea1SDimitry Andric   // this will be the effective code model.
209*0fca6ea1SDimitry Andric   CodeModel::Model ModuleModel = TM.getCodeModel();
210*0fca6ea1SDimitry Andric 
211*0fca6ea1SDimitry Andric   // Initially support per global code model for AIX only.
212*0fca6ea1SDimitry Andric   if (!isAIXABI())
213*0fca6ea1SDimitry Andric     return ModuleModel;
214*0fca6ea1SDimitry Andric 
215*0fca6ea1SDimitry Andric   // Only GlobalVariables carry an attribute which can override the module code
216*0fca6ea1SDimitry Andric   // model.
217*0fca6ea1SDimitry Andric   assert(GV && "Unexpected NULL GlobalValue");
218*0fca6ea1SDimitry Andric   const GlobalVariable *GlobalVar =
219*0fca6ea1SDimitry Andric       [](const GlobalValue *GV) -> const GlobalVariable * {
220*0fca6ea1SDimitry Andric     const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV);
221*0fca6ea1SDimitry Andric     if (Var)
222*0fca6ea1SDimitry Andric       return Var;
223*0fca6ea1SDimitry Andric 
224*0fca6ea1SDimitry Andric     const GlobalAlias *Alias = dyn_cast<GlobalAlias>(GV);
225*0fca6ea1SDimitry Andric     if (Alias)
226*0fca6ea1SDimitry Andric       return dyn_cast<GlobalVariable>(Alias->getAliaseeObject());
227*0fca6ea1SDimitry Andric 
228*0fca6ea1SDimitry Andric     return nullptr;
229*0fca6ea1SDimitry Andric   }(GV);
230*0fca6ea1SDimitry Andric 
231*0fca6ea1SDimitry Andric   if (!GlobalVar)
232*0fca6ea1SDimitry Andric     return ModuleModel;
233*0fca6ea1SDimitry Andric 
234*0fca6ea1SDimitry Andric   std::optional<CodeModel::Model> MaybeCodeModel = GlobalVar->getCodeModel();
235*0fca6ea1SDimitry Andric   if (MaybeCodeModel) {
236*0fca6ea1SDimitry Andric     CodeModel::Model CM = *MaybeCodeModel;
237*0fca6ea1SDimitry Andric     assert((CM == CodeModel::Small || CM == CodeModel::Large) &&
238*0fca6ea1SDimitry Andric            "invalid code model for AIX");
239*0fca6ea1SDimitry Andric     return CM;
240*0fca6ea1SDimitry Andric   }
241*0fca6ea1SDimitry Andric 
242*0fca6ea1SDimitry Andric   return ModuleModel;
243*0fca6ea1SDimitry Andric }
244*0fca6ea1SDimitry Andric 
2450b57cec5SDimitry Andric bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); }
2460b57cec5SDimitry Andric bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); }
2475ffd83dbSDimitry Andric 
2485ffd83dbSDimitry Andric bool PPCSubtarget::isUsingPCRelativeCalls() const {
2495ffd83dbSDimitry Andric   return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() &&
2505ffd83dbSDimitry Andric          CodeModel::Medium == getTargetMachine().getCodeModel();
2515ffd83dbSDimitry Andric }
252e8d8bef9SDimitry Andric 
253e8d8bef9SDimitry Andric // GlobalISEL
254e8d8bef9SDimitry Andric const CallLowering *PPCSubtarget::getCallLowering() const {
255e8d8bef9SDimitry Andric   return CallLoweringInfo.get();
256e8d8bef9SDimitry Andric }
257e8d8bef9SDimitry Andric 
258e8d8bef9SDimitry Andric const RegisterBankInfo *PPCSubtarget::getRegBankInfo() const {
259e8d8bef9SDimitry Andric   return RegBankInfo.get();
260e8d8bef9SDimitry Andric }
261e8d8bef9SDimitry Andric 
262e8d8bef9SDimitry Andric const LegalizerInfo *PPCSubtarget::getLegalizerInfo() const {
263e8d8bef9SDimitry Andric   return Legalizer.get();
264e8d8bef9SDimitry Andric }
265e8d8bef9SDimitry Andric 
266e8d8bef9SDimitry Andric InstructionSelector *PPCSubtarget::getInstructionSelector() const {
267e8d8bef9SDimitry Andric   return InstSelector.get();
268e8d8bef9SDimitry Andric }
269