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