LLVM 17.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"
16#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/StringRef.h"
20#include "llvm/CodeGen/Passes.h"
23#include "llvm/IR/DataLayout.h"
28#include <optional>
29#include <string>
30
31using namespace llvm;
32
34 // Register the target.
45}
46
47static std::string computeDataLayout(const Triple &TT) {
48 std::string Ret;
49
50 // Big endian.
51 Ret += "E";
52
53 // Data mangling.
55
56 // Make sure that global data has at least 16 bits of alignment by
57 // default, so that we can refer to it using LARL. We don't have any
58 // special requirements for stack variables though.
59 Ret += "-i1:8:16-i8:8:16";
60
61 // 64-bit integers are naturally aligned.
62 Ret += "-i64:64";
63
64 // 128-bit floats are aligned only to 64 bits.
65 Ret += "-f128:64";
66
67 // The DataLayout string always holds a vector alignment of 64 bits, see
68 // comment in clang/lib/Basic/Targets/SystemZ.h.
69 Ret += "-v128:64";
70
71 // We prefer 16 bits of aligned for all globals; see above.
72 Ret += "-a:8:16";
73
74 // Integer registers are 32 or 64 bits.
75 Ret += "-n32:64";
76
77 return Ret;
78}
79
80static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
81 if (TT.isOSzOS())
82 return std::make_unique<TargetLoweringObjectFileGOFF>();
83
84 // Note: Some times run with -triple s390x-unknown.
85 // In this case, default to ELF unless z/OS specifically provided.
86 return std::make_unique<TargetLoweringObjectFileELF>();
87}
88
89static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
90 // Static code is suitable for use in a dynamic executable; there is no
91 // separate DynamicNoPIC model.
92 if (!RM || *RM == Reloc::DynamicNoPIC)
93 return Reloc::Static;
94 return *RM;
95}
96
97// For SystemZ we define the models as follows:
98//
99// Small: BRASL can call any function and will use a stub if necessary.
100// Locally-binding symbols will always be in range of LARL.
101//
102// Medium: BRASL can call any function and will use a stub if necessary.
103// GOT slots and locally-defined text will always be in range
104// of LARL, but other symbols might not be.
105//
106// Large: Equivalent to Medium for now.
107//
108// Kernel: Equivalent to Medium for now.
109//
110// This means that any PIC module smaller than 4GB meets the
111// requirements of Small, so Small seems like the best default there.
112//
113// All symbols bind locally in a non-PIC module, so the choice is less
114// obvious. There are two cases:
115//
116// - When creating an executable, PLTs and copy relocations allow
117// us to treat external symbols as part of the executable.
118// Any executable smaller than 4GB meets the requirements of Small,
119// so that seems like the best default.
120//
121// - When creating JIT code, stubs will be in range of BRASL if the
122// image is less than 4GB in size. GOT entries will likewise be
123// in range of LARL. However, the JIT environment has no equivalent
124// of copy relocs, so locally-binding data symbols might not be in
125// the range of LARL. We need the Medium model in that case.
126static CodeModel::Model
127getEffectiveSystemZCodeModel(std::optional<CodeModel::Model> CM,
128 Reloc::Model RM, bool JIT) {
129 if (CM) {
130 if (*CM == CodeModel::Tiny)
131 report_fatal_error("Target does not support the tiny CodeModel", false);
132 if (*CM == CodeModel::Kernel)
133 report_fatal_error("Target does not support the kernel CodeModel", false);
134 return *CM;
135 }
136 if (JIT)
138 return CodeModel::Small;
139}
140
142 StringRef CPU, StringRef FS,
143 const TargetOptions &Options,
144 std::optional<Reloc::Model> RM,
145 std::optional<CodeModel::Model> CM,
146 CodeGenOpt::Level OL, bool JIT)
148 T, computeDataLayout(TT), TT, CPU, FS, Options,
151 OL),
152 TLOF(createTLOF(getTargetTriple())) {
153 initAsmInfo();
154}
155
157
158const SystemZSubtarget *
160 Attribute CPUAttr = F.getFnAttribute("target-cpu");
161 Attribute TuneAttr = F.getFnAttribute("tune-cpu");
162 Attribute FSAttr = F.getFnAttribute("target-features");
163
164 std::string CPU =
165 CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
166 std::string TuneCPU =
167 TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
168 std::string FS =
169 FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
170
171 // FIXME: This is related to the code below to reset the target options,
172 // we need to know whether or not the soft float flag is set on the
173 // function, so we can enable it as a subtarget feature.
174 bool softFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
175
176 if (softFloat)
177 FS += FS.empty() ? "+soft-float" : ",+soft-float";
178
179 auto &I = SubtargetMap[CPU + TuneCPU + FS];
180 if (!I) {
181 // This needs to be done before we create a new subtarget since any
182 // creation will depend on the TM and the code generation flags on the
183 // function that reside in TargetOptions.
185 I = std::make_unique<SystemZSubtarget>(TargetTriple, CPU, TuneCPU, FS,
186 *this);
187 }
188
189 return I.get();
190}
191
192namespace {
193
194/// SystemZ Code Generator Pass Configuration Options.
195class SystemZPassConfig : public TargetPassConfig {
196public:
197 SystemZPassConfig(SystemZTargetMachine &TM, PassManagerBase &PM)
198 : TargetPassConfig(TM, PM) {}
199
200 SystemZTargetMachine &getSystemZTargetMachine() const {
201 return getTM<SystemZTargetMachine>();
202 }
203
205 createPostMachineScheduler(MachineSchedContext *C) const override {
206 return new ScheduleDAGMI(C,
207 std::make_unique<SystemZPostRASchedStrategy>(C),
208 /*RemoveKillFlags=*/true);
209 }
210
211 void addIRPasses() override;
212 bool addInstSelector() override;
213 bool addILPOpts() override;
214 void addPreRegAlloc() override;
215 void addPostRewrite() override;
216 void addPostRegAlloc() override;
217 void addPreSched2() override;
218 void addPreEmitPass() override;
219};
220
221} // end anonymous namespace
222
223void SystemZPassConfig::addIRPasses() {
224 if (getOptLevel() != CodeGenOpt::None) {
225 addPass(createSystemZTDCPass());
227 }
228
230}
231
232bool SystemZPassConfig::addInstSelector() {
233 addPass(createSystemZISelDag(getSystemZTargetMachine(), getOptLevel()));
234
235 if (getOptLevel() != CodeGenOpt::None)
236 addPass(createSystemZLDCleanupPass(getSystemZTargetMachine()));
237
238 return false;
239}
240
241bool SystemZPassConfig::addILPOpts() {
242 addPass(&EarlyIfConverterID);
243 return true;
244}
245
246void SystemZPassConfig::addPreRegAlloc() {
247 addPass(createSystemZCopyPhysRegsPass(getSystemZTargetMachine()));
248}
249
250void SystemZPassConfig::addPostRewrite() {
251 addPass(createSystemZPostRewritePass(getSystemZTargetMachine()));
252}
253
254void SystemZPassConfig::addPostRegAlloc() {
255 // PostRewrite needs to be run at -O0 also (in which case addPostRewrite()
256 // is not called).
257 if (getOptLevel() == CodeGenOpt::None)
258 addPass(createSystemZPostRewritePass(getSystemZTargetMachine()));
259}
260
261void SystemZPassConfig::addPreSched2() {
262 if (getOptLevel() != CodeGenOpt::None)
263 addPass(&IfConverterID);
264}
265
266void SystemZPassConfig::addPreEmitPass() {
267 // Do instruction shortening before compare elimination because some
268 // vector instructions will be shortened into opcodes that compare
269 // elimination recognizes.
270 if (getOptLevel() != CodeGenOpt::None)
271 addPass(createSystemZShortenInstPass(getSystemZTargetMachine()));
272
273 // We eliminate comparisons here rather than earlier because some
274 // transformations can change the set of available CC values and we
275 // generally want those transformations to have priority. This is
276 // especially true in the commonest case where the result of the comparison
277 // is used by a single in-range branch instruction, since we will then
278 // be able to fuse the compare and the branch instead.
279 //
280 // For example, two-address NILF can sometimes be converted into
281 // three-address RISBLG. NILF produces a CC value that indicates whether
282 // the low word is zero, but RISBLG does not modify CC at all. On the
283 // other hand, 64-bit ANDs like NILL can sometimes be converted to RISBG.
284 // The CC value produced by NILL isn't useful for our purposes, but the
285 // value produced by RISBG can be used for any comparison with zero
286 // (not just equality). So there are some transformations that lose
287 // CC values (while still being worthwhile) and others that happen to make
288 // the CC result more useful than it was originally.
289 //
290 // Another reason is that we only want to use BRANCH ON COUNT in cases
291 // where we know that the count register is not going to be spilled.
292 //
293 // Doing it so late makes it more likely that a register will be reused
294 // between the comparison and the branch, but it isn't clear whether
295 // preventing that would be a win or not.
296 if (getOptLevel() != CodeGenOpt::None)
297 addPass(createSystemZElimComparePass(getSystemZTargetMachine()));
298 addPass(createSystemZLongBranchPass(getSystemZTargetMachine()));
299
300 // Do final scheduling after all other optimizations, to get an
301 // optimal input for the decoder (branch relaxation must happen
302 // after block placement).
303 if (getOptLevel() != CodeGenOpt::None)
304 addPass(&PostMachineSchedulerID);
305}
306
308 return new SystemZPassConfig(*this, PM);
309}
310
313 return TargetTransformInfo(SystemZTTIImpl(this, F));
314}
315
317 BumpPtrAllocator &Allocator, const Function &F,
318 const TargetSubtargetInfo *STI) const {
319 return SystemZMachineFunctionInfo::create<SystemZMachineFunctionInfo>(
320 Allocator, F, STI);
321}
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:127
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static LVOptions Options
Definition: LVOptions.cpp:25
static std::string computeDataLayout()
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
const char LLVMTargetMachineRef TM
Basic Register Allocator
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static CodeModel::Model getEffectiveSystemZCodeModel(std::optional< CodeModel::Model > CM, Reloc::Model RM, bool JIT)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZTarget()
static Reloc::Model getEffectiveRelocModel(std::optional< Reloc::Model > RM)
Target-Independent Code Generator Pass Configuration Options pass.
This pass exposes codegen information to IR-level passes.
static std::unique_ptr< TargetLoweringObjectFile > createTLOF()
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:317
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition: Attributes.h:187
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:66
static const char * getManglingComponent(const Triple &T)
Definition: DataLayout.cpp:169
This class describes a target machine that is implemented with the LLVM target-independent code gener...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A ScheduleDAG for scheduling lists of MachineInstr.
ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
const SystemZSubtarget * getSubtargetImpl() const =delete
TargetTransformInfo getTargetTransformInfo(const Function &F) const override
Get a TargetTransformInfo implementation for the target.
SystemZTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM, CodeGenOpt::Level OL, bool JIT)
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 ...
Triple TargetTriple
Triple string, CPU name, and target feature strings the TargetMachine instance is created with.
Definition: TargetMachine.h:97
std::string TargetFS
Definition: TargetMachine.h:99
std::string TargetCPU
Definition: TargetMachine.h:98
std::unique_ptr< const MCSubtargetInfo > STI
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:44
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
Level
Code generation optimization level.
Definition: CodeGen.h:57
@ DynamicNoPIC
Definition: CodeGen.h:25
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheSystemZTarget()
void initializeSystemZElimComparePass(PassRegistry &)
FunctionPass * createSystemZLongBranchPass(SystemZTargetMachine &TM)
FunctionPass * createSystemZCopyPhysRegsPass(SystemZTargetMachine &TM)
FunctionPass * createSystemZElimComparePass(SystemZTargetMachine &TM)
void initializeSystemZDAGToDAGISelPass(PassRegistry &)
char & PostMachineSchedulerID
PostMachineScheduler - This pass schedules machine instructions postRA.
void initializeSystemZLongBranchPass(PassRegistry &)
void initializeSystemZShortenInstPass(PassRegistry &)
FunctionPass * createSystemZTDCPass()
FunctionPass * createSystemZISelDag(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
FunctionPass * createLoopDataPrefetchPass()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
FunctionPass * createSystemZShortenInstPass(SystemZTargetMachine &TM)
void initializeSystemZPostRewritePass(PassRegistry &)
void initializeSystemZTDCPassPass(PassRegistry &)
FunctionPass * createSystemZLDCleanupPass(SystemZTargetMachine &TM)
char & EarlyIfConverterID
EarlyIfConverter - This pass performs if-conversion on SSA form by inserting cmov instructions.
FunctionPass * createSystemZPostRewritePass(SystemZTargetMachine &TM)
char & IfConverterID
IfConverter - This pass performs machine code if conversion.
void initializeSystemZLDCleanupPass(PassRegistry &)
MachineFunctionInfo - This class can be derived from and used by targets to hold private target-speci...
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
RegisterTargetMachine - Helper template for registering a target machine implementation,...