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-exception |
6 | // |
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 | |
34 | using namespace llvm; |
35 | |
36 | #define DEBUG_TYPE "ppc-subtarget" |
37 | |
38 | #define GET_SUBTARGETINFO_TARGET_DESC |
39 | #define GET_SUBTARGETINFO_CTOR |
40 | #include "PPCGenSubtargetInfo.inc" |
41 | |
42 | static cl::opt<bool> |
43 | EnableMachinePipeliner("ppc-enable-pipeliner" , |
44 | cl::desc("Enable Machine Pipeliner for PPC" ), |
45 | cl::init(Val: false), cl::Hidden); |
46 | |
47 | PPCSubtarget &PPCSubtarget::initializeSubtargetDependencies(StringRef CPU, |
48 | StringRef TuneCPU, |
49 | StringRef FS) { |
50 | initializeEnvironment(); |
51 | initSubtargetFeatures(CPU, TuneCPU, FS); |
52 | return *this; |
53 | } |
54 | |
55 | PPCSubtarget::PPCSubtarget(const Triple &TT, const std::string &CPU, |
56 | const std::string &TuneCPU, const std::string &FS, |
57 | const PPCTargetMachine &TM) |
58 | : PPCGenSubtargetInfo(TT, CPU, TuneCPU, FS), TargetTriple(TT), |
59 | IsPPC64(TargetTriple.getArch() == Triple::ppc64 || |
60 | TargetTriple.getArch() == Triple::ppc64le), |
61 | TM(TM), FrameLowering(initializeSubtargetDependencies(CPU, TuneCPU, FS)), |
62 | InstrInfo(*this), TLInfo(TM, *this) { |
63 | TSInfo = std::make_unique<PPCSelectionDAGInfo>(); |
64 | |
65 | CallLoweringInfo.reset(p: new PPCCallLowering(*getTargetLowering())); |
66 | Legalizer.reset(p: new PPCLegalizerInfo(*this)); |
67 | auto *RBI = new PPCRegisterBankInfo(*getRegisterInfo()); |
68 | RegBankInfo.reset(p: RBI); |
69 | |
70 | InstSelector.reset(p: createPPCInstructionSelector(TM, *this, *RBI)); |
71 | } |
72 | |
73 | PPCSubtarget::~PPCSubtarget() = default; |
74 | |
75 | const SelectionDAGTargetInfo *PPCSubtarget::getSelectionDAGInfo() const { |
76 | return TSInfo.get(); |
77 | } |
78 | |
79 | void PPCSubtarget::initializeEnvironment() { |
80 | StackAlignment = Align(16); |
81 | CPUDirective = PPC::DIR_NONE; |
82 | HasPOPCNTD = POPCNTD_Unavailable; |
83 | } |
84 | |
85 | void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef TuneCPU, |
86 | StringRef FS) { |
87 | // Determine default and user specified characteristics |
88 | std::string CPUName = std::string(CPU); |
89 | if (CPUName.empty() || CPU == "generic" ) { |
90 | if (TargetTriple.getSubArch() == Triple::PPCSubArch_spe) |
91 | CPUName = "e500" ; |
92 | else |
93 | CPUName = std::string(PPC::getNormalizedPPCTargetCPU(T: TargetTriple)); |
94 | } |
95 | |
96 | // Determine the CPU to schedule for. |
97 | if (TuneCPU.empty()) TuneCPU = CPUName; |
98 | |
99 | // Initialize scheduling itinerary for the specified CPU. |
100 | InstrItins = getInstrItineraryForCPU(CPU: CPUName); |
101 | |
102 | // Parse features string. |
103 | ParseSubtargetFeatures(CPU: CPUName, TuneCPU, FS); |
104 | |
105 | // If the user requested use of 64-bit regs, but the cpu selected doesn't |
106 | // support it, ignore. |
107 | if (IsPPC64 && has64BitSupport()) |
108 | Use64BitRegs = true; |
109 | |
110 | if (TargetTriple.isPPC32SecurePlt()) |
111 | IsSecurePlt = true; |
112 | |
113 | if (HasSPE && IsPPC64) |
114 | report_fatal_error( reason: "SPE is only supported for 32-bit targets.\n" , gen_crash_diag: false); |
115 | if (HasSPE && (HasAltivec || HasVSX || HasFPU)) |
116 | report_fatal_error( |
117 | reason: "SPE and traditional floating point cannot both be enabled.\n" , gen_crash_diag: false); |
118 | |
119 | // If not SPE, set standard FPU |
120 | if (!HasSPE) |
121 | HasFPU = true; |
122 | |
123 | StackAlignment = getPlatformStackAlignment(); |
124 | |
125 | // Determine endianness. |
126 | IsLittleEndian = TM.isLittleEndian(); |
127 | |
128 | if (HasAIXSmallLocalExecTLS || HasAIXSmallLocalDynamicTLS) { |
129 | if (!TargetTriple.isOSAIX() || !IsPPC64) |
130 | report_fatal_error(reason: "The aix-small-local-[exec|dynamic]-tls attribute is " |
131 | "only supported on AIX in " |
132 | "64-bit mode.\n" , |
133 | gen_crash_diag: false); |
134 | // The aix-small-local-[exec|dynamic]-tls attribute should only be used with |
135 | // -data-sections, as having data sections turned off with this option |
136 | // is not ideal for performance. Moreover, the |
137 | // small-local-[exec|dynamic]-tls region is a limited resource, and should |
138 | // not be used for variables that may be replaced. |
139 | if (!TM.getDataSections()) |
140 | report_fatal_error(reason: "The aix-small-local-[exec|dynamic]-tls attribute can " |
141 | "only be specified with " |
142 | "-data-sections.\n" , |
143 | gen_crash_diag: false); |
144 | } |
145 | |
146 | if (HasAIXShLibTLSModelOpt && (!TargetTriple.isOSAIX() || !IsPPC64)) |
147 | report_fatal_error(reason: "The aix-shared-lib-tls-model-opt attribute " |
148 | "is only supported on AIX in 64-bit mode.\n" , |
149 | gen_crash_diag: false); |
150 | } |
151 | |
152 | bool PPCSubtarget::enableMachineScheduler() const { return true; } |
153 | |
154 | bool PPCSubtarget::enableMachinePipeliner() const { |
155 | return getSchedModel().hasInstrSchedModel() && EnableMachinePipeliner; |
156 | } |
157 | |
158 | bool PPCSubtarget::useDFAforSMS() const { return false; } |
159 | |
160 | // This overrides the PostRAScheduler bit in the SchedModel for each CPU. |
161 | bool PPCSubtarget::enablePostRAScheduler() const { return true; } |
162 | |
163 | PPCGenSubtargetInfo::AntiDepBreakMode PPCSubtarget::getAntiDepBreakMode() const { |
164 | return TargetSubtargetInfo::ANTIDEP_ALL; |
165 | } |
166 | |
167 | void PPCSubtarget::getCriticalPathRCs(RegClassVector &CriticalPathRCs) const { |
168 | CriticalPathRCs.clear(); |
169 | CriticalPathRCs.push_back(Elt: isPPC64() ? |
170 | &PPC::G8RCRegClass : &PPC::GPRCRegClass); |
171 | } |
172 | |
173 | void PPCSubtarget::overrideSchedPolicy(MachineSchedPolicy &Policy, |
174 | unsigned NumRegionInstrs) const { |
175 | // The GenericScheduler that we use defaults to scheduling bottom up only. |
176 | // We want to schedule from both the top and the bottom and so we set |
177 | // OnlyBottomUp to false. |
178 | // We want to do bi-directional scheduling since it provides a more balanced |
179 | // schedule leading to better performance. |
180 | Policy.OnlyBottomUp = false; |
181 | // Spilling is generally expensive on all PPC cores, so always enable |
182 | // register-pressure tracking. |
183 | Policy.ShouldTrackPressure = true; |
184 | } |
185 | |
186 | bool PPCSubtarget::useAA() const { |
187 | return true; |
188 | } |
189 | |
190 | bool PPCSubtarget::enableSubRegLiveness() const { return true; } |
191 | |
192 | bool PPCSubtarget::isGVIndirectSymbol(const GlobalValue *GV) const { |
193 | if (isAIXABI()) { |
194 | if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(Val: GV)) |
195 | // On AIX the only symbols that aren't indirect are toc-data. |
196 | return !GVar->hasAttribute(Kind: "toc-data" ); |
197 | |
198 | return true; |
199 | } |
200 | |
201 | // Large code model always uses the TOC even for local symbols. |
202 | if (TM.getCodeModel() == CodeModel::Large) |
203 | return true; |
204 | |
205 | if (TM.shouldAssumeDSOLocal(GV)) |
206 | return false; |
207 | return true; |
208 | } |
209 | |
210 | CodeModel::Model PPCSubtarget::getCodeModel(const TargetMachine &TM, |
211 | const GlobalValue *GV) const { |
212 | // If there isn't an attribute to override the module code model |
213 | // this will be the effective code model. |
214 | CodeModel::Model ModuleModel = TM.getCodeModel(); |
215 | |
216 | // Initially support per global code model for AIX only. |
217 | if (!isAIXABI()) |
218 | return ModuleModel; |
219 | |
220 | // Only GlobalVariables carry an attribute which can override the module code |
221 | // model. |
222 | assert(GV && "Unexpected NULL GlobalValue" ); |
223 | const GlobalVariable *GlobalVar = |
224 | [](const GlobalValue *GV) -> const GlobalVariable * { |
225 | const GlobalVariable *Var = dyn_cast<GlobalVariable>(Val: GV); |
226 | if (Var) |
227 | return Var; |
228 | |
229 | const GlobalAlias *Alias = dyn_cast<GlobalAlias>(Val: GV); |
230 | if (Alias) |
231 | return dyn_cast<GlobalVariable>(Val: Alias->getAliaseeObject()); |
232 | |
233 | return nullptr; |
234 | }(GV); |
235 | |
236 | if (!GlobalVar) |
237 | return ModuleModel; |
238 | |
239 | std::optional<CodeModel::Model> MaybeCodeModel = GlobalVar->getCodeModel(); |
240 | if (MaybeCodeModel) { |
241 | CodeModel::Model CM = *MaybeCodeModel; |
242 | assert((CM == CodeModel::Small || CM == CodeModel::Large) && |
243 | "invalid code model for AIX" ); |
244 | return CM; |
245 | } |
246 | |
247 | return ModuleModel; |
248 | } |
249 | |
250 | bool PPCSubtarget::isELFv2ABI() const { return TM.isELFv2ABI(); } |
251 | bool PPCSubtarget::isPPC64() const { return TM.isPPC64(); } |
252 | |
253 | bool PPCSubtarget::isUsingPCRelativeCalls() const { |
254 | return isPPC64() && hasPCRelativeMemops() && isELFv2ABI() && |
255 | CodeModel::Medium == getTargetMachine().getCodeModel(); |
256 | } |
257 | |
258 | // GlobalISEL |
259 | const CallLowering *PPCSubtarget::getCallLowering() const { |
260 | return CallLoweringInfo.get(); |
261 | } |
262 | |
263 | const RegisterBankInfo *PPCSubtarget::getRegBankInfo() const { |
264 | return RegBankInfo.get(); |
265 | } |
266 | |
267 | const LegalizerInfo *PPCSubtarget::getLegalizerInfo() const { |
268 | return Legalizer.get(); |
269 | } |
270 | |
271 | InstructionSelector *PPCSubtarget::getInstructionSelector() const { |
272 | return InstSelector.get(); |
273 | } |
274 | |