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