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