LLVM 24.0.0git
SystemZTargetMachine.cpp
Go to the documentation of this file.
1//===-- SystemZTargetMachine.cpp - Define TargetMachine for SystemZ -------===//
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
11#include "SystemZ.h"
17#include "llvm/ADT/StringRef.h"
19#include "llvm/CodeGen/Passes.h"
22#include "llvm/IR/DataLayout.h"
28#include <memory>
29#include <optional>
30#include <string>
31
32using namespace llvm;
33
35 EnableMachineCombinerPass("systemz-machine-combiner",
36 cl::desc("Enable the machine combiner pass"),
37 cl::init(true), cl::Hidden);
38
40 "generic-sched", cl::Hidden, cl::init(false),
41 cl::desc("Run the generic pre-ra scheduler instead of the SystemZ "
42 "scheduler."));
43
44// NOLINTNEXTLINE(readability-identifier-naming)
61
62static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
63 if (TT.isOSzOS())
64 return std::make_unique<TargetLoweringObjectFileGOFF>();
65
66 // Note: Some times run with -triple s390x-unknown.
67 // In this case, default to ELF unless z/OS specifically provided.
68 return std::make_unique<SystemZELFTargetObjectFile>();
69}
70
72 std::optional<Reloc::Model> RM) {
73 if (TT.isOSzOS()) {
74 // z/OS code is always position-independent, so -fpic and -fno-pic have
75 // no effect. Ignore the relocation model requested by the frontend.
76 // This also prevents optimizations (such as relative lookup tables)
77 // that generate 32-bit relative offsets, which are
78 // incompatible with the GOFF binder's requirement for 8-byte relocations
79 // in C_WSA64.
80 //
81 // Constant globals whose initializers contain pointer relocations (e.g.
82 // vtables) must be placed in a writable section (C_WSA64) so the GOFF
83 // binder can apply relocations at link time. Using DynamicNoPIC causes
84 // getKindForGlobal() to classify such globals as ReadOnlyWithRel instead
85 // of ReadOnly, which routes them to C_WSA64 rather than C_CODE64.
87 }
88 // For ELF/Linux, static code is suitable for use in a dynamic executable;
89 // there is no separate DynamicNoPIC model.
90 if (!RM || *RM == Reloc::DynamicNoPIC)
91 return Reloc::Static;
92 return *RM;
93}
94
95// For SystemZ we define the models as follows:
96//
97// Small: BRASL can call any function and will use a stub if necessary.
98// Locally-binding symbols will always be in range of LARL.
99//
100// Medium: BRASL can call any function and will use a stub if necessary.
101// GOT slots and locally-defined text will always be in range
102// of LARL, but other symbols might not be.
103//
104// Large: Equivalent to Medium for now.
105//
106// Kernel: Equivalent to Medium for now.
107//
108// This means that any PIC module smaller than 4GB meets the
109// requirements of Small, so Small seems like the best default there.
110//
111// All symbols bind locally in a non-PIC module, so the choice is less
112// obvious. There are two cases:
113//
114// - When creating an executable, PLTs and copy relocations allow
115// us to treat external symbols as part of the executable.
116// Any executable smaller than 4GB meets the requirements of Small,
117// so that seems like the best default.
118//
119// - When creating JIT code, stubs will be in range of BRASL if the
120// image is less than 4GB in size. GOT entries will likewise be
121// in range of LARL. However, the JIT environment has no equivalent
122// of copy relocs, so locally-binding data symbols might not be in
123// the range of LARL. We need the Medium model in that case.
124static CodeModel::Model
125getEffectiveSystemZCodeModel(std::optional<CodeModel::Model> CM,
126 Reloc::Model RM, bool JIT) {
127 if (CM) {
128 if (*CM == CodeModel::Tiny)
129 report_fatal_error("Target does not support the tiny CodeModel", false);
130 if (*CM == CodeModel::Kernel)
131 report_fatal_error("Target does not support the kernel CodeModel", false);
132 return *CM;
133 }
134 if (JIT)
136 return CodeModel::Small;
137}
138
140 StringRef CPU, StringRef FS,
141 const TargetOptions &Options,
142 std::optional<Reloc::Model> RM,
143 std::optional<CodeModel::Model> CM,
144 CodeGenOptLevel OL, bool JIT)
146 T, TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM),
148 OL),
149 TLOF(createTLOF(getTargetTriple())) {
150 initAsmInfo();
151}
152
154
155const SystemZSubtarget *
157 Attribute CPUAttr = F.getFnAttribute("target-cpu");
158 Attribute TuneAttr = F.getFnAttribute("tune-cpu");
159 Attribute FSAttr = F.getFnAttribute("target-features");
160
161 std::string CPU =
162 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
163 std::string TuneCPU =
164 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
165 std::string FS =
166 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
167
168 // FIXME: This is related to the code below to reset the target options,
169 // we need to know whether the soft float and backchain flags are set on the
170 // function, so we can enable them as subtarget features.
171 bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
172 if (SoftFloat)
173 FS += FS.empty() ? "+soft-float" : ",+soft-float";
174 bool BackChain = F.hasFnAttribute("backchain");
175 if (BackChain)
176 FS += FS.empty() ? "+backchain" : ",+backchain";
177
178 auto &I = SubtargetMap[CPU + TuneCPU + FS];
179 if (!I) {
180 I = std::make_unique<SystemZSubtarget>(TargetTriple, CPU, TuneCPU, FS,
181 *this);
182 }
183
184 return I.get();
185}
186
189 // Use GenericScheduler if requested on CL or for Z10 which has no sched
190 // model.
191 if (GenericSched ||
192 !C->MF->getSubtarget().getSchedModel().hasInstrSchedModel())
193 return nullptr;
194
196}
197
202
203namespace {
204
205/// SystemZ Code Generator Pass Configuration Options.
206class SystemZPassConfig : public TargetPassConfig {
207public:
208 SystemZPassConfig(SystemZTargetMachine &TM, PassManagerBase &PM)
209 : TargetPassConfig(TM, PM) {}
210
211 SystemZTargetMachine &getSystemZTargetMachine() const {
213 }
214
215 void addIRPasses() override;
216 bool addInstSelector() override;
217 bool addILPOpts() override;
218 void addPreRegAlloc() override;
219 void addPostRewrite() override;
220 void addPostRegAlloc() override;
221 void addPreSched2() override;
222 void addPreEmitPass() override;
223};
224
225} // end anonymous namespace
226
227void SystemZPassConfig::addIRPasses() {
228 if (getOptLevel() != CodeGenOptLevel::None) {
232 }
233
235
237}
238
239bool SystemZPassConfig::addInstSelector() {
240 addPass(
241 createSystemZISelDagLegacyPass(getSystemZTargetMachine(), getOptLevel()));
242
243 if (getOptLevel() != CodeGenOptLevel::None)
244 addPass(createSystemZLDCleanupLegacyPass(getSystemZTargetMachine()));
245
246 return false;
247}
248
249bool SystemZPassConfig::addILPOpts() {
250 addPass(&EarlyIfConverterLegacyID);
251
253 addPass(&MachineCombinerID);
254
255 return true;
256}
257
258void SystemZPassConfig::addPreRegAlloc() {
259 addPass(createSystemZCopyPhysRegsLegacyPass(getSystemZTargetMachine()));
260}
261
262void SystemZPassConfig::addPostRewrite() {
263 addPass(createSystemZPostRewriteLegacyPass(getSystemZTargetMachine()));
264}
265
266void SystemZPassConfig::addPostRegAlloc() {
267 // PostRewrite needs to be run at -O0 also (in which case addPostRewrite()
268 // is not called).
269 if (getOptLevel() == CodeGenOptLevel::None)
270 addPass(createSystemZPostRewriteLegacyPass(getSystemZTargetMachine()));
271}
272
273void SystemZPassConfig::addPreSched2() {
274 if (getOptLevel() != CodeGenOptLevel::None)
275 addPass(&IfConverterID);
276}
277
278void SystemZPassConfig::addPreEmitPass() {
279 // Do instruction shortening before compare elimination because some
280 // vector instructions will be shortened into opcodes that compare
281 // elimination recognizes.
282 if (getOptLevel() != CodeGenOptLevel::None)
283 addPass(createSystemZShortenInstLegacyPass(getSystemZTargetMachine()));
284
285 // We eliminate comparisons here rather than earlier because some
286 // transformations can change the set of available CC values and we
287 // generally want those transformations to have priority. This is
288 // especially true in the commonest case where the result of the comparison
289 // is used by a single in-range branch instruction, since we will then
290 // be able to fuse the compare and the branch instead.
291 //
292 // For example, two-address NILF can sometimes be converted into
293 // three-address RISBLG. NILF produces a CC value that indicates whether
294 // the low word is zero, but RISBLG does not modify CC at all. On the
295 // other hand, 64-bit ANDs like NILL can sometimes be converted to RISBG.
296 // The CC value produced by NILL isn't useful for our purposes, but the
297 // value produced by RISBG can be used for any comparison with zero
298 // (not just equality). So there are some transformations that lose
299 // CC values (while still being worthwhile) and others that happen to make
300 // the CC result more useful than it was originally.
301 //
302 // Another reason is that we only want to use BRANCH ON COUNT in cases
303 // where we know that the count register is not going to be spilled.
304 //
305 // Doing it so late makes it more likely that a register will be reused
306 // between the comparison and the branch, but it isn't clear whether
307 // preventing that would be a win or not.
308 if (getOptLevel() != CodeGenOptLevel::None)
309 addPass(createSystemZElimCompareLegacyPass(getSystemZTargetMachine()));
310 addPass(createSystemZLongBranchLegacyPass(getSystemZTargetMachine()));
311
312 // Do final scheduling after all other optimizations, to get an
313 // optimal input for the decoder (branch relaxation must happen
314 // after block placement).
315 if (getOptLevel() != CodeGenOptLevel::None)
316 addPass(&PostMachineSchedulerID);
317}
318
320 return new SystemZPassConfig(*this, PM);
321}
322
325 return TargetTransformInfo(std::make_unique<SystemZTTIImpl>(this, F));
326}
327
static std::unique_ptr< TargetLoweringObjectFile > createTLOF(const Triple &TT)
static Reloc::Model getEffectiveRelocModel()
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:211
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
static cl::opt< bool > EnableMachineCombinerPass("ppc-machine-combiner", cl::desc("Enable the machine combiner pass"), cl::init(true), cl::Hidden)
const GCNTargetMachine & getTM(const GCNSubtarget *STI)
static CodeModel::Model getEffectiveSystemZCodeModel(std::optional< CodeModel::Model > CM, Reloc::Model RM, bool JIT)
static cl::opt< bool > GenericSched("generic-sched", cl::Hidden, cl::init(false), cl::desc("Run the generic pre-ra scheduler instead of the SystemZ " "scheduler."))
cl::opt< bool > EnableMachineCombinerPass("systemz-machine-combiner", cl::desc("Enable the machine combiner pass"), cl::init(true), cl::Hidden)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZTarget()
Target-Independent Code Generator Pass Configuration Options pass.
This pass exposes codegen information to IR-level passes.
static std::unique_ptr< TargetLoweringObjectFile > createTLOF()
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:262
CodeGenTargetMachineImpl(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOptLevel OL)
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A ScheduleDAG for scheduling lists of MachineInstr.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
ScheduleDAGInstrs * createMachineScheduler(MachineSchedContext *C) const override
Create an instance of ScheduleDAGInstrs to be run within the standard MachineScheduler pass for this ...
const SystemZSubtarget * getSubtargetImpl() const =delete
SystemZTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOptLevel OL, bool JIT)
TargetTransformInfo getTargetTransformInfo(const Function &F) const override
Get a TargetTransformInfo implementation for the target.
MachineFunctionInfo * createMachineFunctionInfo(BumpPtrAllocator &Allocator, const Function &F, const TargetSubtargetInfo *STI) const override
Create the target's instance of MachineFunctionInfo.
TargetPassConfig * createPassConfig(PassManagerBase &PM) override
Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...
ScheduleDAGInstrs * createPostMachineScheduler(MachineSchedContext *C) const override
Similar to createMachineScheduler but used when postRA machine scheduling is enabled.
Triple TargetTriple
Triple string, CPU name, and target feature strings the TargetMachine instance is created with.
const Triple & getTargetTriple() const
std::unique_ptr< const MCSubtargetInfo > STI
TargetOptions Options
Target-Independent Code Generator Pass Configuration Options.
virtual void addIRPasses()
Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...
TargetSubtargetInfo - Generic base class for all target subtargets.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
PassManagerBase - An abstract interface to allow code to add passes to a pass manager without having ...
@ DynamicNoPIC
Definition CodeGen.h:26
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
ScheduleDAGMILive * createSchedLive(MachineSchedContext *C)
Create the standard converging machine scheduler.
Target & getTheSystemZTarget()
FunctionPass * createSystemZISelDagLegacyPass(SystemZTargetMachine &TM, CodeGenOptLevel OptLevel)
void initializeSystemZPostRewriteLegacyPass(PassRegistry &)
FunctionPass * createSystemZLDCleanupLegacyPass(SystemZTargetMachine &TM)
void initializeSystemZCopyPhysRegsLegacyPass(PassRegistry &)
LLVM_ABI char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
LLVM_ABI char & EarlyIfConverterLegacyID
EarlyIfConverter - This pass performs if-conversion on SSA form by inserting cmov instructions.
LLVM_ABI char & MachineCombinerID
This pass performs instruction combining using trace metrics to estimate critical-path and resource d...
static Reloc::Model getEffectiveRelocModel(std::optional< Reloc::Model > RM)
void initializeSystemZDAGToDAGISelLegacyPass(PassRegistry &)
void initializeSystemZTDCLegacyPass(PassRegistry &)
ScheduleDAGMI * createSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
void initializeSystemZAlignGlobalsLegacyPass(PassRegistry &)
LLVM_ABI FunctionPass * createLoopDataPrefetchPass()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
FunctionPass * createSystemZTDCLegacyPass()
FunctionPass * createSystemZCopyPhysRegsLegacyPass(SystemZTargetMachine &TM)
void initializeSystemZLDCleanupLegacyPass(PassRegistry &)
void initializeSystemZElimCompareLegacyPass(PassRegistry &)
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:280
void initializeSystemZAsmPrinterPass(PassRegistry &)
FunctionPass * createSystemZShortenInstLegacyPass(SystemZTargetMachine &TM)
ModulePass * createSystemZAlignGlobalsLegacyPass()
LLVM_ABI char & IfConverterID
IfConverter - This pass performs machine code if conversion.
LLVM_ABI FunctionPass * createAtomicExpandLegacyPass()
AtomicExpandPass - At IR level this pass replace atomic instructions with __atomic_* library calls,...
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:391
FunctionPass * createSystemZPostRewriteLegacyPass(SystemZTargetMachine &TM)
void initializeSystemZLongBranchLegacyPass(PassRegistry &)
FunctionPass * createSystemZElimCompareLegacyPass(SystemZTargetMachine &TM)
FunctionPass * createSystemZLongBranchLegacyPass(SystemZTargetMachine &TM)
void initializeSystemZShortenInstLegacyPass(PassRegistry &)
MachineFunctionInfo - This class can be derived from and used by targets to hold private target-speci...
static FuncInfoTy * create(BumpPtrAllocator &Allocator, const Function &F, const SubtargetTy *STI)
Factory function: default behavior is to call new using the supplied allocator.
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
RegisterTargetMachine - Helper template for registering a target machine implementation,...