270 lines · cpp
1//===-- PowerPCSubtarget.cpp - PPC Subtarget Information ------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the PPC specific subclass of TargetSubtargetInfo.10//11//===----------------------------------------------------------------------===//12 13#include "PPCSubtarget.h"14#include "GISel/PPCCallLowering.h"15#include "GISel/PPCLegalizerInfo.h"16#include "GISel/PPCRegisterBankInfo.h"17#include "PPC.h"18#include "PPCRegisterInfo.h"19#include "PPCSelectionDAGInfo.h"20#include "PPCTargetMachine.h"21#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"22#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"23#include "llvm/CodeGen/MachineFunction.h"24#include "llvm/CodeGen/MachineScheduler.h"25#include "llvm/IR/GlobalAlias.h"26#include "llvm/IR/GlobalValue.h"27#include "llvm/IR/GlobalVariable.h"28#include "llvm/MC/TargetRegistry.h"29#include "llvm/Support/CommandLine.h"30#include "llvm/Target/TargetMachine.h"31#include "llvm/TargetParser/PPCTargetParser.h"32#include <cstdlib>33 34using namespace llvm;35 36#define DEBUG_TYPE "ppc-subtarget"37 38#define GET_SUBTARGETINFO_TARGET_DESC39#define GET_SUBTARGETINFO_CTOR40#include "PPCGenSubtargetInfo.inc"41 42static cl::opt<bool>43 EnableMachinePipeliner("ppc-enable-pipeliner",44 cl::desc("Enable Machine Pipeliner for PPC"),45 cl::init(false), cl::Hidden);46 47PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU,48 StringRef TuneCPU,49 StringRef FS) {50 initializeEnvironment();51 initSubtargetFeatures(CPU, TuneCPU, FS);52 return *this;53}54 55PPCSubtarget::PPCSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,56 StringRef FS, const PPCTargetMachine &TM)57 : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), TM(TM),58 FrameLowering(initializeSubtargetDependencies(CPU, TuneCPU, FS)),59 InstrInfo(*this), TLInfo(TM, *this) {60 TSInfo = std::make_unique<PPCSelectionDAGInfo>();61 62 CallLoweringInfo.reset(new PPCCallLowering(*getTargetLowering()));63 Legalizer.reset(new PPCLegalizerInfo(*this));64 auto *RBI = new PPCRegisterBankInfo(*getRegisterInfo());65 RegBankInfo.reset(RBI);66 67 InstSelector.reset(createPPCInstructionSelector(TM, *this, *RBI));68}69 70PPCSubtarget::~PPCSubtarget() = default;71 72const SelectionDAGTargetInfo *PPCSubtarget::getSelectionDAGInfo() const {73 return TSInfo.get();74}75 76void PPCSubtarget::initializeEnvironment() {77 StackAlignment = Align(16);78 CPUDirective = PPC::DIR_NONE;79 HasPOPCNTD = POPCNTD_Unavailable;80}81 82void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU,83 StringRef FS) {84 // Determine default and user specified characteristics85 std::string CPUName = std::string(CPU);86 if (CPUName.empty() || CPU == "generic") {87 if (getTargetTriple().getSubArch() == Triple::PPCSubArch_spe)88 CPUName = "e500";89 else90 CPUName = std::string(PPC::getNormalizedPPCTargetCPU(getTargetTriple()));91 }92 93 // Determine the CPU to schedule for.94 if (TuneCPU.empty()) TuneCPU = CPUName;95 96 // Initialize scheduling itinerary for the specified CPU.97 InstrItins = getInstrItineraryForCPU(CPUName);98 99 // Parse features string.100 ParseSubtargetFeatures(CPUName, TuneCPU, FS);101 102 // If the user requested use of 64-bit regs, but the cpu selected doesn't103 // support it, ignore.104 if (IsPPC64 && has64BitSupport())105 Use64BitRegs = true;106 107 if (getTargetTriple().isPPC32SecurePlt())108 IsSecurePlt = true;109 110 if (HasSPE && IsPPC64)111 report_fatal_error( "SPE is only supported for 32-bit targets.\n", false);112 if (HasSPE && (HasAltivec || HasVSX || HasFPU))113 report_fatal_error(114 "SPE and traditional floating point cannot both be enabled.\n", false);115 116 // If not SPE, set standard FPU117 if (!HasSPE)118 HasFPU = true;119 120 StackAlignment = getPlatformStackAlignment();121 122 // Determine endianness.123 IsLittleEndian = TM.isLittleEndian();124 125 if (HasAIXSmallLocalExecTLS || HasAIXSmallLocalDynamicTLS) {126 if (!getTargetTriple().isOSAIX() || !IsPPC64)127 report_fatal_error("The aix-small-local-[exec|dynamic]-tls attribute is "128 "only supported on AIX in "129 "64-bit mode.\n",130 false);131 // The aix-small-local-[exec|dynamic]-tls attribute should only be used with132 // -data-sections, as having data sections turned off with this option133 // is not ideal for performance. Moreover, the134 // small-local-[exec|dynamic]-tls region is a limited resource, and should135 // not be used for variables that may be replaced.136 if (!TM.getDataSections())137 report_fatal_error("The aix-small-local-[exec|dynamic]-tls attribute can "138 "only be specified with "139 "-data-sections.\n",140 false);141 }142 143 if (HasAIXShLibTLSModelOpt && (!getTargetTriple().isOSAIX() || !IsPPC64))144 report_fatal_error("The aix-shared-lib-tls-model-opt attribute "145 "is only supported on AIX in 64-bit mode.\n",146 false);147}148 149bool PPCSubtarget::enableMachineScheduler() const { return true; }150 151bool PPCSubtarget::enableMachinePipeliner() const {152 return getSchedModel().hasInstrSchedModel() && EnableMachinePipeliner;153}154 155bool PPCSubtarget::useDFAforSMS() const { return false; }156 157// This overrides the PostRAScheduler bit in the SchedModel for each CPU.158bool PPCSubtarget::enablePostRAScheduler() const { return true; }159 160PPCGenSubtargetInfo::AntiDepBreakMode PPCSubtarget::getAntiDepBreakMode() const {161 return TargetSubtargetInfo::ANTIDEP_ALL;162}163 164void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const {165 CriticalPathRCs.clear();166 CriticalPathRCs.push_back(isPPC64() ?167 &PPC::G8RCRegClass : &PPC::GPRCRegClass);168}169 170void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,171 const SchedRegion &Region) const {172 // The GenericScheduler that we use defaults to scheduling bottom up only.173 // We want to schedule from both the top and the bottom and so we set174 // OnlyBottomUp to false.175 // We want to do bi-directional scheduling since it provides a more balanced176 // schedule leading to better performance.177 Policy.OnlyBottomUp = false;178 // Spilling is generally expensive on all PPC cores, so always enable179 // register-pressure tracking.180 Policy.ShouldTrackPressure = true;181}182 183bool PPCSubtarget::useAA() const {184 return true;185}186 187bool PPCSubtarget::enableSubRegLiveness() const { return true; }188 189bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const {190 if (isAIXABI()) {191 if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))192 // On AIX the only symbols that aren't indirect are toc-data.193 return !GVar->hasAttribute("toc-data");194 195 return true;196 }197 198 // Large code model always uses the TOC even for local symbols.199 if (TM.getCodeModel() == CodeModel::Large)200 return true;201 202 if (TM.shouldAssumeDSOLocal(GV))203 return false;204 return true;205}206 207CodeModel::Model PPCSubtarget::getCodeModel(const TargetMachine &TM,208 const GlobalValue *GV) const {209 // If there isn't an attribute to override the module code model210 // this will be the effective code model.211 CodeModel::Model ModuleModel = TM.getCodeModel();212 213 // Initially support per global code model for AIX only.214 if (!isAIXABI())215 return ModuleModel;216 217 // Only GlobalVariables carry an attribute which can override the module code218 // model.219 assert(GV && "Unexpected NULL GlobalValue");220 const GlobalVariable *GlobalVar =221 [](const GlobalValue *GV) -> const GlobalVariable * {222 const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV);223 if (Var)224 return Var;225 226 const GlobalAlias *Alias = dyn_cast<GlobalAlias>(GV);227 if (Alias)228 return dyn_cast<GlobalVariable>(Alias->getAliaseeObject());229 230 return nullptr;231 }(GV);232 233 if (!GlobalVar)234 return ModuleModel;235 236 std::optional<CodeModel::Model> MaybeCodeModel = GlobalVar->getCodeModel();237 if (MaybeCodeModel) {238 CodeModel::Model CM = *MaybeCodeModel;239 assert((CM == CodeModel::Small || CM == CodeModel::Large) &&240 "invalid code model for AIX");241 return CM;242 }243 244 return ModuleModel;245}246 247bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); }248 249bool PPCSubtarget::isUsingPCRelativeCalls() const {250 return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() &&251 CodeModel::Medium == getTargetMachine().getCodeModel();252}253 254// GlobalISEL255const CallLowering *PPCSubtarget::getCallLowering() const {256 return CallLoweringInfo.get();257}258 259const RegisterBankInfo *PPCSubtarget::getRegBankInfo() const {260 return RegBankInfo.get();261}262 263const LegalizerInfo *PPCSubtarget::getLegalizerInfo() const {264 return Legalizer.get();265}266 267InstructionSelector *PPCSubtarget::getInstructionSelector() const {268 return InstSelector.get();269}270