xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCSubtarget.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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"
14*e8d8bef9SDimitry Andric #include "GISel/PPCCallLowering.h"
15*e8d8bef9SDimitry Andric #include "GISel/PPCLegalizerInfo.h"
16*e8d8bef9SDimitry Andric #include "GISel/PPCRegisterBankInfo.h"
170b57cec5SDimitry Andric #include "PPC.h"
180b57cec5SDimitry Andric #include "PPCRegisterInfo.h"
190b57cec5SDimitry Andric #include "PPCTargetMachine.h"
20*e8d8bef9SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineScheduler.h"
230b57cec5SDimitry Andric #include "llvm/IR/Attributes.h"
240b57cec5SDimitry Andric #include "llvm/IR/Function.h"
250b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
260b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
270b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
280b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
290b57cec5SDimitry Andric #include <cstdlib>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-subtarget"
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
360b57cec5SDimitry Andric #define GET_SUBTARGETINFO_CTOR
370b57cec5SDimitry Andric #include "PPCGenSubtargetInfo.inc"
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric static cl::opt<bool> UseSubRegLiveness("ppc-track-subreg-liveness",
400b57cec5SDimitry Andric cl::desc("Enable subregister liveness tracking for PPC"), cl::Hidden);
410b57cec5SDimitry Andric 
420b57cec5SDimitry 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,
480b57cec5SDimitry Andric                                                             StringRef FS) {
490b57cec5SDimitry Andric   initializeEnvironment();
500b57cec5SDimitry Andric   initSubtargetFeatures(CPU, FS);
510b57cec5SDimitry Andric   return *this;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric PPCSubtarget::PPCSubtarget(const Triple &TT, const std::string &CPU,
550b57cec5SDimitry Andric                            const std::string &FS, const PPCTargetMachine &TM)
56*e8d8bef9SDimitry Andric     : PPCGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS), TargetTriple(TT),
570b57cec5SDimitry Andric       IsPPC64(TargetTriple.getArch() == Triple::ppc64 ||
580b57cec5SDimitry Andric               TargetTriple.getArch() == Triple::ppc64le),
590b57cec5SDimitry Andric       TM(TM), FrameLowering(initializeSubtargetDependencies(CPU, FS)),
60*e8d8bef9SDimitry Andric       InstrInfo(*this), TLInfo(TM, *this) {
61*e8d8bef9SDimitry Andric   CallLoweringInfo.reset(new PPCCallLowering(*getTargetLowering()));
62*e8d8bef9SDimitry Andric   Legalizer.reset(new PPCLegalizerInfo(*this));
63*e8d8bef9SDimitry Andric   auto *RBI = new PPCRegisterBankInfo(*getRegisterInfo());
64*e8d8bef9SDimitry Andric   RegBankInfo.reset(RBI);
65*e8d8bef9SDimitry Andric 
66*e8d8bef9SDimitry Andric   InstSelector.reset(createPPCInstructionSelector(
67*e8d8bef9SDimitry Andric       *static_cast<const PPCTargetMachine *>(&TM), *this, *RBI));
68*e8d8bef9SDimitry Andric }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric void PPCSubtarget::initializeEnvironment() {
718bcb0991SDimitry Andric   StackAlignment = Align(16);
72480093f4SDimitry Andric   CPUDirective = PPC::DIR_NONE;
730b57cec5SDimitry Andric   HasMFOCRF = false;
740b57cec5SDimitry Andric   Has64BitSupport = false;
750b57cec5SDimitry Andric   Use64BitRegs = false;
760b57cec5SDimitry Andric   UseCRBits = false;
770b57cec5SDimitry Andric   HasHardFloat = false;
780b57cec5SDimitry Andric   HasAltivec = false;
790b57cec5SDimitry Andric   HasSPE = false;
80*e8d8bef9SDimitry Andric   HasEFPU2 = false;
810b57cec5SDimitry Andric   HasFPU = false;
820b57cec5SDimitry Andric   HasVSX = false;
830b57cec5SDimitry Andric   NeedsTwoConstNR = false;
840b57cec5SDimitry Andric   HasP8Vector = false;
850b57cec5SDimitry Andric   HasP8Altivec = false;
860b57cec5SDimitry Andric   HasP8Crypto = false;
870b57cec5SDimitry Andric   HasP9Vector = false;
880b57cec5SDimitry Andric   HasP9Altivec = false;
89*e8d8bef9SDimitry Andric   HasMMA = false;
905ffd83dbSDimitry Andric   HasP10Vector = false;
915ffd83dbSDimitry Andric   HasPrefixInstrs = false;
925ffd83dbSDimitry Andric   HasPCRelativeMemops = false;
930b57cec5SDimitry Andric   HasFCPSGN = false;
940b57cec5SDimitry Andric   HasFSQRT = false;
950b57cec5SDimitry Andric   HasFRE = false;
960b57cec5SDimitry Andric   HasFRES = false;
970b57cec5SDimitry Andric   HasFRSQRTE = false;
980b57cec5SDimitry Andric   HasFRSQRTES = false;
990b57cec5SDimitry Andric   HasRecipPrec = false;
1000b57cec5SDimitry Andric   HasSTFIWX = false;
1010b57cec5SDimitry Andric   HasLFIWAX = false;
1020b57cec5SDimitry Andric   HasFPRND = false;
1030b57cec5SDimitry Andric   HasFPCVT = false;
1040b57cec5SDimitry Andric   HasISEL = false;
1050b57cec5SDimitry Andric   HasBPERMD = false;
1060b57cec5SDimitry Andric   HasExtDiv = false;
1070b57cec5SDimitry Andric   HasCMPB = false;
1080b57cec5SDimitry Andric   HasLDBRX = false;
1090b57cec5SDimitry Andric   IsBookE = false;
1100b57cec5SDimitry Andric   HasOnlyMSYNC = false;
1110b57cec5SDimitry Andric   IsPPC4xx = false;
1120b57cec5SDimitry Andric   IsPPC6xx = false;
1130b57cec5SDimitry Andric   IsE500 = false;
1140b57cec5SDimitry Andric   FeatureMFTB = false;
1155ffd83dbSDimitry Andric   AllowsUnalignedFPAccess = false;
1160b57cec5SDimitry Andric   DeprecatedDST = false;
1170b57cec5SDimitry Andric   HasICBT = false;
1180b57cec5SDimitry Andric   HasInvariantFunctionDescriptors = false;
1190b57cec5SDimitry Andric   HasPartwordAtomics = false;
1200b57cec5SDimitry Andric   HasDirectMove = false;
1210b57cec5SDimitry Andric   HasHTM = false;
1220b57cec5SDimitry Andric   HasFloat128 = false;
1235ffd83dbSDimitry Andric   HasFusion = false;
124*e8d8bef9SDimitry Andric   HasStoreFusion = false;
1255ffd83dbSDimitry Andric   HasAddiLoadFusion = false;
1265ffd83dbSDimitry Andric   HasAddisLoadFusion = false;
1270b57cec5SDimitry Andric   IsISA3_0 = false;
1285ffd83dbSDimitry Andric   IsISA3_1 = false;
1290b57cec5SDimitry Andric   UseLongCalls = false;
1300b57cec5SDimitry Andric   SecurePlt = false;
1310b57cec5SDimitry Andric   VectorsUseTwoUnits = false;
1320b57cec5SDimitry Andric   UsePPCPreRASchedStrategy = false;
1330b57cec5SDimitry Andric   UsePPCPostRASchedStrategy = false;
134*e8d8bef9SDimitry Andric   PairedVectorMemops = false;
1355ffd83dbSDimitry Andric   PredictableSelectIsExpensive = false;
136*e8d8bef9SDimitry Andric   HasModernAIXAs = false;
137*e8d8bef9SDimitry Andric   IsAIX = false;
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   HasPOPCNTD = POPCNTD_Unavailable;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
1430b57cec5SDimitry Andric   // Determine default and user specified characteristics
1445ffd83dbSDimitry Andric   std::string CPUName = std::string(CPU);
1450b57cec5SDimitry Andric   if (CPUName.empty() || CPU == "generic") {
1460b57cec5SDimitry Andric     // If cross-compiling with -march=ppc64le without -mcpu
1470b57cec5SDimitry Andric     if (TargetTriple.getArch() == Triple::ppc64le)
1480b57cec5SDimitry Andric       CPUName = "ppc64le";
149f8e1cfadSDimitry Andric     else if (TargetTriple.getSubArch() == Triple::PPCSubArch_spe)
150f8e1cfadSDimitry Andric       CPUName = "e500";
1510b57cec5SDimitry Andric     else
1520b57cec5SDimitry Andric       CPUName = "generic";
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   // Initialize scheduling itinerary for the specified CPU.
1560b57cec5SDimitry Andric   InstrItins = getInstrItineraryForCPU(CPUName);
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   // Parse features string.
159*e8d8bef9SDimitry Andric   ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // If the user requested use of 64-bit regs, but the cpu selected doesn't
1620b57cec5SDimitry Andric   // support it, ignore.
1630b57cec5SDimitry Andric   if (IsPPC64 && has64BitSupport())
1640b57cec5SDimitry Andric     Use64BitRegs = true;
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   if ((TargetTriple.isOSFreeBSD() && TargetTriple.getOSMajorVersion() >= 13) ||
1670b57cec5SDimitry Andric       TargetTriple.isOSNetBSD() || TargetTriple.isOSOpenBSD() ||
1680b57cec5SDimitry Andric       TargetTriple.isMusl())
1690b57cec5SDimitry Andric     SecurePlt = true;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   if (HasSPE && IsPPC64)
1720b57cec5SDimitry Andric     report_fatal_error( "SPE is only supported for 32-bit targets.\n", false);
173*e8d8bef9SDimitry Andric   if (HasSPE && (HasAltivec || HasVSX || HasFPU))
1740b57cec5SDimitry Andric     report_fatal_error(
1750b57cec5SDimitry Andric         "SPE and traditional floating point cannot both be enabled.\n", false);
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   // If not SPE, set standard FPU
1780b57cec5SDimitry Andric   if (!HasSPE)
1790b57cec5SDimitry Andric     HasFPU = true;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   StackAlignment = getPlatformStackAlignment();
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   // Determine endianness.
1840b57cec5SDimitry Andric   // FIXME: Part of the TargetMachine.
185*e8d8bef9SDimitry Andric   IsLittleEndian = (TargetTriple.getArch() == Triple::ppc64le ||
186*e8d8bef9SDimitry Andric                     TargetTriple.getArch() == Triple::ppcle);
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric bool PPCSubtarget::enableMachineScheduler() const { return true; }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric bool PPCSubtarget::enableMachinePipeliner() const {
1925ffd83dbSDimitry Andric   return getSchedModel().hasInstrSchedModel() && EnableMachinePipeliner;
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric bool PPCSubtarget::useDFAforSMS() const { return false; }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric // This overrides the PostRAScheduler bit in the SchedModel for each CPU.
1980b57cec5SDimitry Andric bool PPCSubtarget::enablePostRAScheduler() const { return true; }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric PPCGenSubtargetInfo::AntiDepBreakMode PPCSubtarget::getAntiDepBreakMode() const {
2010b57cec5SDimitry Andric   return TargetSubtargetInfo::ANTIDEP_ALL;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {
2050b57cec5SDimitry Andric   CriticalPathRCs.clear();
2060b57cec5SDimitry Andric   CriticalPathRCs.push_back(isPPC64() ?
2070b57cec5SDimitry Andric                             &PPC::G8RCRegClass : &PPC::GPRCRegClass);
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
2110b57cec5SDimitry Andric                                        unsigned NumRegionInstrs) const {
2120b57cec5SDimitry Andric   // The GenericScheduler that we use defaults to scheduling bottom up only.
2130b57cec5SDimitry Andric   // We want to schedule from both the top and the bottom and so we set
2140b57cec5SDimitry Andric   // OnlyBottomUp to false.
2150b57cec5SDimitry Andric   // We want to do bi-directional scheduling since it provides a more balanced
2160b57cec5SDimitry Andric   // schedule leading to better performance.
2170b57cec5SDimitry Andric   Policy.OnlyBottomUp = false;
2180b57cec5SDimitry Andric   // Spilling is generally expensive on all PPC cores, so always enable
2190b57cec5SDimitry Andric   // register-pressure tracking.
2200b57cec5SDimitry Andric   Policy.ShouldTrackPressure = true;
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric bool PPCSubtarget::useAA() const {
2240b57cec5SDimitry Andric   return true;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric bool PPCSubtarget::enableSubRegLiveness() const {
2280b57cec5SDimitry Andric   return UseSubRegLiveness;
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
2318bcb0991SDimitry Andric bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {
2320b57cec5SDimitry Andric   // Large code model always uses the TOC even for local symbols.
2330b57cec5SDimitry Andric   if (TM.getCodeModel() == CodeModel::Large)
2348bcb0991SDimitry Andric     return true;
2350b57cec5SDimitry Andric   if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
2368bcb0991SDimitry Andric     return false;
2378bcb0991SDimitry Andric   return true;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); }
2410b57cec5SDimitry Andric bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); }
2425ffd83dbSDimitry Andric 
2435ffd83dbSDimitry Andric bool PPCSubtarget::isUsingPCRelativeCalls() const {
2445ffd83dbSDimitry Andric   return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() &&
2455ffd83dbSDimitry Andric          CodeModel::Medium == getTargetMachine().getCodeModel();
2465ffd83dbSDimitry Andric }
247*e8d8bef9SDimitry Andric 
248*e8d8bef9SDimitry Andric // GlobalISEL
249*e8d8bef9SDimitry Andric const CallLowering *PPCSubtarget::getCallLowering() const {
250*e8d8bef9SDimitry Andric   return CallLoweringInfo.get();
251*e8d8bef9SDimitry Andric }
252*e8d8bef9SDimitry Andric 
253*e8d8bef9SDimitry Andric const RegisterBankInfo *PPCSubtarget::getRegBankInfo() const {
254*e8d8bef9SDimitry Andric   return RegBankInfo.get();
255*e8d8bef9SDimitry Andric }
256*e8d8bef9SDimitry Andric 
257*e8d8bef9SDimitry Andric const LegalizerInfo *PPCSubtarget::getLegalizerInfo() const {
258*e8d8bef9SDimitry Andric   return Legalizer.get();
259*e8d8bef9SDimitry Andric }
260*e8d8bef9SDimitry Andric 
261*e8d8bef9SDimitry Andric InstructionSelector *PPCSubtarget::getInstructionSelector() const {
262*e8d8bef9SDimitry Andric   return InstSelector.get();
263*e8d8bef9SDimitry Andric }
264