LLVM 22.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 "systemz-machine-combiner",
36 cl::desc("Enable the machine combiner pass"),
37 cl::init(true), cl::Hidden);
38
39// NOLINTNEXTLINE(readability-identifier-naming)
56
57static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
58 if (TT.isOSzOS())
59 return std::make_unique<TargetLoweringObjectFileGOFF>();
60
61 // Note: Some times run with -triple s390x-unknown.
62 // In this case, default to ELF unless z/OS specifically provided.
63 return std::make_unique<SystemZELFTargetObjectFile>();
64}
65
66static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
67 // Static code is suitable for use in a dynamic executable; there is no
68 // separate DynamicNoPIC model.
69 if (!RM || *RM == Reloc::DynamicNoPIC)
70 return Reloc::Static;
71 return *RM;
72}
73
74// For SystemZ we define the models as follows:
75//
76// Small: BRASL can call any function and will use a stub if necessary.
77// Locally-binding symbols will always be in range of LARL.
78//
79// Medium: BRASL can call any function and will use a stub if necessary.
80// GOT slots and locally-defined text will always be in range
81// of LARL, but other symbols might not be.
82//
83// Large: Equivalent to Medium for now.
84//
85// Kernel: Equivalent to Medium for now.
86//
87// This means that any PIC module smaller than 4GB meets the
88// requirements of Small, so Small seems like the best default there.
89//
90// All symbols bind locally in a non-PIC module, so the choice is less
91// obvious. There are two cases:
92//
93// - When creating an executable, PLTs and copy relocations allow
94// us to treat external symbols as part of the executable.
95// Any executable smaller than 4GB meets the requirements of Small,
96// so that seems like the best default.
97//
98// - When creating JIT code, stubs will be in range of BRASL if the
99// image is less than 4GB in size. GOT entries will likewise be
100// in range of LARL. However, the JIT environment has no equivalent
101// of copy relocs, so locally-binding data symbols might not be in
102// the range of LARL. We need the Medium model in that case.
103static CodeModel::Model
104getEffectiveSystemZCodeModel(std::optional<CodeModel::Model> CM,
105 Reloc::Model RM, bool JIT) {
106 if (CM) {
107 if (*CM == CodeModel::Tiny)
108 report_fatal_error("Target does not support the tiny CodeModel", false);
109 if (*CM == CodeModel::Kernel)
110 report_fatal_error("Target does not support the kernel CodeModel", false);
111 return *CM;
112 }
113 if (JIT)
115 return CodeModel::Small;
116}
117
119 StringRef CPU, StringRef FS,
120 const TargetOptions &Options,
121 std::optional<Reloc::Model> RM,
122 std::optional<CodeModel::Model> CM,
123 CodeGenOptLevel OL, bool JIT)
125 T, TT.computeDataLayout(), TT, CPU, FS, Options,
128 OL),
129 TLOF(createTLOF(getTargetTriple())) {
130 initAsmInfo();
131}
132
134
135const SystemZSubtarget *
137 Attribute CPUAttr = F.getFnAttribute("target-cpu");
138 Attribute TuneAttr = F.getFnAttribute("tune-cpu");
139 Attribute FSAttr = F.getFnAttribute("target-features");
140
141 std::string CPU =
142 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
143 std::string TuneCPU =
144 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
145 std::string FS =
146 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
147
148 // FIXME: This is related to the code below to reset the target options,
149 // we need to know whether the soft float and backchain flags are set on the
150 // function, so we can enable them as subtarget features.
151 bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
152 if (SoftFloat)
153 FS += FS.empty() ? "+soft-float" : ",+soft-float";
154 bool BackChain = F.hasFnAttribute("backchain");
155 if (BackChain)
156 FS += FS.empty() ? "+backchain" : ",+backchain";
157
158 auto &I = SubtargetMap[CPU + TuneCPU + FS];
159 if (!I) {
160 // This needs to be done before we create a new subtarget since any
161 // creation will depend on the TM and the code generation flags on the
162 // function that reside in TargetOptions.
164 I = std::make_unique<SystemZSubtarget>(TargetTriple, CPU, TuneCPU, FS,
165 *this);
166 }
167
168 return I.get();
169}
170
175
176namespace {
177
178/// SystemZ Code Generator Pass Configuration Options.
179class SystemZPassConfig : public TargetPassConfig {
180public:
181 SystemZPassConfig(SystemZTargetMachine &TM, PassManagerBase &PM)
182 : TargetPassConfig(TM, PM) {}
183
184 SystemZTargetMachine &getSystemZTargetMachine() const {
186 }
187
188 void addIRPasses() override;
189 bool addInstSelector() override;
190 bool addILPOpts() override;
191 void addPreRegAlloc() override;
192 void addPostRewrite() override;
193 void addPostRegAlloc() override;
194 void addPreSched2() override;
195 void addPreEmitPass() override;
196};
197
198} // end anonymous namespace
199
200void SystemZPassConfig::addIRPasses() {
201 if (getOptLevel() != CodeGenOptLevel::None) {
202 addPass(createSystemZTDCPass());
204 }
205
207
209}
210
211bool SystemZPassConfig::addInstSelector() {
212 addPass(createSystemZISelDag(getSystemZTargetMachine(), getOptLevel()));
213
214 if (getOptLevel() != CodeGenOptLevel::None)
215 addPass(createSystemZLDCleanupPass(getSystemZTargetMachine()));
216
217 return false;
218}
219
220bool SystemZPassConfig::addILPOpts() {
221 addPass(&EarlyIfConverterLegacyID);
222
224 addPass(&MachineCombinerID);
225
226 return true;
227}
228
229void SystemZPassConfig::addPreRegAlloc() {
230 addPass(createSystemZCopyPhysRegsPass(getSystemZTargetMachine()));
231}
232
233void SystemZPassConfig::addPostRewrite() {
234 addPass(createSystemZPostRewritePass(getSystemZTargetMachine()));
235}
236
237void SystemZPassConfig::addPostRegAlloc() {
238 // PostRewrite needs to be run at -O0 also (in which case addPostRewrite()
239 // is not called).
240 if (getOptLevel() == CodeGenOptLevel::None)
241 addPass(createSystemZPostRewritePass(getSystemZTargetMachine()));
242}
243
244void SystemZPassConfig::addPreSched2() {
245 if (getOptLevel() != CodeGenOptLevel::None)
246 addPass(&IfConverterID);
247}
248
249void SystemZPassConfig::addPreEmitPass() {
250 // Do instruction shortening before compare elimination because some
251 // vector instructions will be shortened into opcodes that compare
252 // elimination recognizes.
253 if (getOptLevel() != CodeGenOptLevel::None)
254 addPass(createSystemZShortenInstPass(getSystemZTargetMachine()));
255
256 // We eliminate comparisons here rather than earlier because some
257 // transformations can change the set of available CC values and we
258 // generally want those transformations to have priority. This is
259 // especially true in the commonest case where the result of the comparison
260 // is used by a single in-range branch instruction, since we will then
261 // be able to fuse the compare and the branch instead.
262 //
263 // For example, two-address NILF can sometimes be converted into
264 // three-address RISBLG. NILF produces a CC value that indicates whether
265 // the low word is zero, but RISBLG does not modify CC at all. On the
266 // other hand, 64-bit ANDs like NILL can sometimes be converted to RISBG.
267 // The CC value produced by NILL isn't useful for our purposes, but the
268 // value produced by RISBG can be used for any comparison with zero
269 // (not just equality). So there are some transformations that lose
270 // CC values (while still being worthwhile) and others that happen to make
271 // the CC result more useful than it was originally.
272 //
273 // Another reason is that we only want to use BRANCH ON COUNT in cases
274 // where we know that the count register is not going to be spilled.
275 //
276 // Doing it so late makes it more likely that a register will be reused
277 // between the comparison and the branch, but it isn't clear whether
278 // preventing that would be a win or not.
279 if (getOptLevel() != CodeGenOptLevel::None)
280 addPass(createSystemZElimComparePass(getSystemZTargetMachine()));
281 addPass(createSystemZLongBranchPass(getSystemZTargetMachine()));
282
283 // Do final scheduling after all other optimizations, to get an
284 // optimal input for the decoder (branch relaxation must happen
285 // after block placement).
286 if (getOptLevel() != CodeGenOptLevel::None)
287 addPass(&PostMachineSchedulerID);
288}
289
291 return new SystemZPassConfig(*this, PM);
292}
293
296 return TargetTransformInfo(std::make_unique<SystemZTTIImpl>(this, F));
297}
298
static std::unique_ptr< TargetLoweringObjectFile > createTLOF(const Triple &TT)
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
#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 > EnableMachineCombinerPass("systemz-machine-combiner", cl::desc("Enable the machine combiner pass"), cl::init(true), cl::Hidden)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZTarget()
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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:69
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:223
CodeGenTargetMachineImpl(const Target &T, StringRef DataLayoutString, 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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:233
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
void resetTargetOptions(const Function &F) const
Reset the target options based on the function's attributes.
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:47
PassManagerBase - An abstract interface to allow code to add passes to a pass manager without having ...
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ DynamicNoPIC
Definition CodeGen.h:25
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheSystemZTarget()
void initializeSystemZElimComparePass(PassRegistry &)
FunctionPass * createSystemZLongBranchPass(SystemZTargetMachine &TM)
FunctionPass * createSystemZISelDag(SystemZTargetMachine &TM, CodeGenOptLevel OptLevel)
FunctionPass * createSystemZCopyPhysRegsPass(SystemZTargetMachine &TM)
FunctionPass * createSystemZElimComparePass(SystemZTargetMachine &TM)
void initializeSystemZCopyPhysRegsPass(PassRegistry &)
LLVM_ABI char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
void initializeSystemZLongBranchPass(PassRegistry &)
void initializeSystemZShortenInstPass(PassRegistry &)
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 &)
ScheduleDAGMI * createSchedPostRA(MachineSchedContext *C)
Create a generic scheduler with no vreg liveness or DAG mutation passes.
FunctionPass * createSystemZTDCPass()
LLVM_ABI FunctionPass * createLoopDataPrefetchPass()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
FunctionPass * createSystemZShortenInstPass(SystemZTargetMachine &TM)
void initializeSystemZPostRewritePass(PassRegistry &)
BumpPtrAllocatorImpl BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:383
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
void initializeSystemZTDCPassPass(PassRegistry &)
FunctionPass * createSystemZLDCleanupPass(SystemZTargetMachine &TM)
void initializeSystemZAsmPrinterPass(PassRegistry &)
FunctionPass * createSystemZPostRewritePass(SystemZTargetMachine &TM)
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,...
void initializeSystemZLDCleanupPass(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,...