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