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"
260b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
27349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
280b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
290b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
300b57cec5SDimitry Andric #include <cstdlib>
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-subtarget"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
370b57cec5SDimitry Andric #define GET_SUBTARGETINFO_CTOR
380b57cec5SDimitry Andric #include "PPCGenSubtargetInfo.inc"
390b57cec5SDimitry Andric 
40bdd1243dSDimitry Andric static cl::opt<bool>
41bdd1243dSDimitry Andric     UseSubRegLiveness("ppc-track-subreg-liveness",
42bdd1243dSDimitry Andric                       cl::desc("Enable subregister liveness tracking for PPC"),
43bdd1243dSDimitry Andric                       cl::init(true), cl::Hidden);
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric static cl::opt<bool>
460b57cec5SDimitry Andric     EnableMachinePipeliner("ppc-enable-pipeliner",
470b57cec5SDimitry Andric                            cl::desc("Enable Machine Pipeliner for PPC"),
480b57cec5SDimitry Andric                            cl::init(false), cl::Hidden);
490b57cec5SDimitry Andric 
initializeSubtargetDependencies(StringRef CPU,StringRef TuneCPU,StringRef FS)500b57cec5SDimitry Andric PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU,
51bdd1243dSDimitry Andric                                                             StringRef TuneCPU,
520b57cec5SDimitry Andric                                                             StringRef FS) {
530b57cec5SDimitry Andric   initializeEnvironment();
54bdd1243dSDimitry Andric   initSubtargetFeatures(CPU, TuneCPU, FS);
550b57cec5SDimitry Andric   return *this;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
PPCSubtarget(const Triple & TT,const std::string & CPU,const std::string & TuneCPU,const std::string & FS,const PPCTargetMachine & TM)580b57cec5SDimitry Andric PPCSubtarget::PPCSubtarget(const Triple &TT, const std::string &CPU,
59bdd1243dSDimitry Andric                            const std::string &TuneCPU, const std::string &FS,
60bdd1243dSDimitry Andric                            const PPCTargetMachine &TM)
61bdd1243dSDimitry Andric     : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), TargetTriple(TT),
620b57cec5SDimitry Andric       IsPPC64(TargetTriple.getArch() == Triple::ppc64 ||
630b57cec5SDimitry Andric               TargetTriple.getArch() == Triple::ppc64le),
64bdd1243dSDimitry Andric       TM(TM), FrameLowering(initializeSubtargetDependencies(CPU, TuneCPU, FS)),
65e8d8bef9SDimitry Andric       InstrInfo(*this), TLInfo(TM, *this) {
66e8d8bef9SDimitry Andric   CallLoweringInfo.reset(new PPCCallLowering(*getTargetLowering()));
67e8d8bef9SDimitry Andric   Legalizer.reset(new PPCLegalizerInfo(*this));
68e8d8bef9SDimitry Andric   auto *RBI = new PPCRegisterBankInfo(*getRegisterInfo());
69e8d8bef9SDimitry Andric   RegBankInfo.reset(RBI);
70e8d8bef9SDimitry Andric 
71e8d8bef9SDimitry Andric   InstSelector.reset(createPPCInstructionSelector(
72e8d8bef9SDimitry Andric       *static_cast<const PPCTargetMachine *>(&TM), *this, *RBI));
73e8d8bef9SDimitry Andric }
740b57cec5SDimitry Andric 
initializeEnvironment()750b57cec5SDimitry Andric void PPCSubtarget::initializeEnvironment() {
768bcb0991SDimitry Andric   StackAlignment = Align(16);
77480093f4SDimitry Andric   CPUDirective = PPC::DIR_NONE;
780b57cec5SDimitry Andric   HasPOPCNTD = POPCNTD_Unavailable;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
initSubtargetFeatures(StringRef CPU,StringRef TuneCPU,StringRef FS)81bdd1243dSDimitry Andric void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,
82bdd1243dSDimitry Andric                                          StringRef FS) {
830b57cec5SDimitry Andric   // Determine default and user specified characteristics
845ffd83dbSDimitry Andric   std::string CPUName = std::string(CPU);
850b57cec5SDimitry Andric   if (CPUName.empty() || CPU == "generic") {
860b57cec5SDimitry Andric     // If cross-compiling with -march=ppc64le without -mcpu
870b57cec5SDimitry Andric     if (TargetTriple.getArch() == Triple::ppc64le)
880b57cec5SDimitry Andric       CPUName = "ppc64le";
89f8e1cfadSDimitry Andric     else if (TargetTriple.getSubArch() == Triple::PPCSubArch_spe)
90f8e1cfadSDimitry Andric       CPUName = "e500";
910b57cec5SDimitry Andric     else
920b57cec5SDimitry Andric       CPUName = "generic";
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
95bdd1243dSDimitry Andric   // Determine the CPU to schedule for.
96bdd1243dSDimitry Andric   if (TuneCPU.empty()) TuneCPU = CPUName;
97bdd1243dSDimitry Andric 
980b57cec5SDimitry Andric   // Initialize scheduling itinerary for the specified CPU.
990b57cec5SDimitry Andric   InstrItins = getInstrItineraryForCPU(CPUName);
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // Parse features string.
102bdd1243dSDimitry Andric   ParseSubtargetFeatures(CPUName, TuneCPU, FS);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   // If the user requested use of 64-bit regs, but the cpu selected doesn't
1050b57cec5SDimitry Andric   // support it, ignore.
1060b57cec5SDimitry Andric   if (IsPPC64 && has64BitSupport())
1070b57cec5SDimitry Andric     Use64BitRegs = true;
1080b57cec5SDimitry Andric 
10906c3fb27SDimitry Andric   if (TargetTriple.isPPC32SecurePlt())
110bdd1243dSDimitry Andric     IsSecurePlt = true;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   if (HasSPE && IsPPC64)
1130b57cec5SDimitry Andric     report_fatal_error( "SPE is only supported for 32-bit targets.\n", false);
114e8d8bef9SDimitry Andric   if (HasSPE && (HasAltivec || HasVSX || HasFPU))
1150b57cec5SDimitry Andric     report_fatal_error(
1160b57cec5SDimitry Andric         "SPE and traditional floating point cannot both be enabled.\n", false);
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   // If not SPE, set standard FPU
1190b57cec5SDimitry Andric   if (!HasSPE)
1200b57cec5SDimitry Andric     HasFPU = true;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   StackAlignment = getPlatformStackAlignment();
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   // Determine endianness.
125fe6060f1SDimitry Andric   IsLittleEndian = TM.isLittleEndian();
1265f757f3fSDimitry Andric 
1275f757f3fSDimitry Andric   if (HasAIXSmallLocalExecTLS && (!TargetTriple.isOSAIX() || !IsPPC64))
1285f757f3fSDimitry Andric     report_fatal_error(
1295f757f3fSDimitry Andric       "The aix-small-local-exec-tls attribute is only supported on AIX in "
1305f757f3fSDimitry Andric       "64-bit mode.\n", false);
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
enableMachineScheduler() const1330b57cec5SDimitry Andric bool PPCSubtarget::enableMachineScheduler() const { return true; }
1340b57cec5SDimitry Andric 
enableMachinePipeliner() const1350b57cec5SDimitry Andric bool PPCSubtarget::enableMachinePipeliner() const {
1365ffd83dbSDimitry Andric   return getSchedModel().hasInstrSchedModel() && EnableMachinePipeliner;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
useDFAforSMS() const1390b57cec5SDimitry Andric bool PPCSubtarget::useDFAforSMS() const { return false; }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric // This overrides the PostRAScheduler bit in the SchedModel for each CPU.
enablePostRAScheduler() const1420b57cec5SDimitry Andric bool PPCSubtarget::enablePostRAScheduler() const { return true; }
1430b57cec5SDimitry Andric 
getAntiDepBreakMode() const1440b57cec5SDimitry Andric PPCGenSubtargetInfo::AntiDepBreakMode PPCSubtarget::getAntiDepBreakMode() const {
1450b57cec5SDimitry Andric   return TargetSubtargetInfo::ANTIDEP_ALL;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
getCriticalPathRCs(RegClassVector & CriticalPathRCs) const1480b57cec5SDimitry Andric void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
1490b57cec5SDimitry Andric   CriticalPathRCs.clear();
1500b57cec5SDimitry Andric   CriticalPathRCs.push_back(isPPC64() ?
1510b57cec5SDimitry Andric                             &PPC::G8RCRegClass : &PPC::GPRCRegClass);
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
overrideSchedPolicy(MachineSchedPolicy & Policy,unsigned NumRegionInstrs) const1540b57cec5SDimitry Andric void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
1550b57cec5SDimitry Andric                                        unsigned NumRegionInstrs) const {
1560b57cec5SDimitry Andric   // The GenericScheduler that we use defaults to scheduling bottom up only.
1570b57cec5SDimitry Andric   // We want to schedule from both the top and the bottom and so we set
1580b57cec5SDimitry Andric   // OnlyBottomUp to false.
1590b57cec5SDimitry Andric   // We want to do bi-directional scheduling since it provides a more balanced
1600b57cec5SDimitry Andric   // schedule leading to better performance.
1610b57cec5SDimitry Andric   Policy.OnlyBottomUp = false;
1620b57cec5SDimitry Andric   // Spilling is generally expensive on all PPC cores, so always enable
1630b57cec5SDimitry Andric   // register-pressure tracking.
1640b57cec5SDimitry Andric   Policy.ShouldTrackPressure = true;
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
useAA() const1670b57cec5SDimitry Andric bool PPCSubtarget::useAA() const {
1680b57cec5SDimitry Andric   return true;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
enableSubRegLiveness() const1710b57cec5SDimitry Andric bool PPCSubtarget::enableSubRegLiveness() const {
1720b57cec5SDimitry Andric   return UseSubRegLiveness;
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
isGVIndirectSymbol(const GlobalValue * GV) const1758bcb0991SDimitry Andric bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
1760b57cec5SDimitry Andric   // Large code model always uses the TOC even for local symbols.
1770b57cec5SDimitry Andric   if (TM.getCodeModel() == CodeModel::Large)
1788bcb0991SDimitry Andric     return true;
1790b57cec5SDimitry Andric   if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
1808bcb0991SDimitry Andric     return false;
1818bcb0991SDimitry Andric   return true;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
isELFv2ABI() const1840b57cec5SDimitry Andric bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); }
isPPC64() const1850b57cec5SDimitry Andric bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); }
1865ffd83dbSDimitry Andric 
isUsingPCRelativeCalls() const1875ffd83dbSDimitry Andric bool PPCSubtarget::isUsingPCRelativeCalls() const {
1885ffd83dbSDimitry Andric   return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() &&
1895ffd83dbSDimitry Andric          CodeModel::Medium == getTargetMachine().getCodeModel();
1905ffd83dbSDimitry Andric }
191e8d8bef9SDimitry Andric 
192e8d8bef9SDimitry Andric // GlobalISEL
getCallLowering() const193e8d8bef9SDimitry Andric const CallLowering *PPCSubtarget::getCallLowering() const {
194e8d8bef9SDimitry Andric   return CallLoweringInfo.get();
195e8d8bef9SDimitry Andric }
196e8d8bef9SDimitry Andric 
getRegBankInfo() const197e8d8bef9SDimitry Andric const RegisterBankInfo *PPCSubtarget::getRegBankInfo() const {
198e8d8bef9SDimitry Andric   return RegBankInfo.get();
199e8d8bef9SDimitry Andric }
200e8d8bef9SDimitry Andric 
getLegalizerInfo() const201e8d8bef9SDimitry Andric const LegalizerInfo *PPCSubtarget::getLegalizerInfo() const {
202e8d8bef9SDimitry Andric   return Legalizer.get();
203e8d8bef9SDimitry Andric }
204e8d8bef9SDimitry Andric 
getInstructionSelector() const205e8d8bef9SDimitry Andric InstructionSelector *PPCSubtarget::getInstructionSelector() const {
206e8d8bef9SDimitry Andric   return InstSelector.get();
207e8d8bef9SDimitry Andric }
208