159d6cff9SDimitry Andric //===-- SystemZTargetMachine.cpp - Define TargetMachine for SystemZ -------===//
259d6cff9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659d6cff9SDimitry Andric //
759d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
859d6cff9SDimitry Andric
97ab83427SDimitry Andric #include "SystemZTargetMachine.h"
1071d5a254SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
1171d5a254SDimitry Andric #include "SystemZ.h"
12e3b55780SDimitry Andric #include "SystemZMachineFunctionInfo.h"
1371d5a254SDimitry Andric #include "SystemZMachineScheduler.h"
14ac9a064cSDimitry Andric #include "SystemZTargetObjectFile.h"
155a5ac124SDimitry Andric #include "SystemZTargetTransformInfo.h"
16e6d15924SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h"
1771d5a254SDimitry Andric #include "llvm/ADT/StringRef.h"
1871d5a254SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
1959d6cff9SDimitry Andric #include "llvm/CodeGen/Passes.h"
2067c32a98SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
2171d5a254SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
2271d5a254SDimitry Andric #include "llvm/IR/DataLayout.h"
23c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
2471d5a254SDimitry Andric #include "llvm/Support/CodeGen.h"
25eb11fae6SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h"
2671d5a254SDimitry Andric #include "llvm/Transforms/Scalar.h"
27b1c73532SDimitry Andric #include <memory>
28e3b55780SDimitry Andric #include <optional>
2971d5a254SDimitry Andric #include <string>
3059d6cff9SDimitry Andric
3159d6cff9SDimitry Andric using namespace llvm;
3259d6cff9SDimitry Andric
33ac9a064cSDimitry Andric static cl::opt<bool> EnableMachineCombinerPass(
34ac9a064cSDimitry Andric "systemz-machine-combiner",
35ac9a064cSDimitry Andric cl::desc("Enable the machine combiner pass"),
36ac9a064cSDimitry Andric cl::init(true), cl::Hidden);
37ac9a064cSDimitry Andric
38b1c73532SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
LLVMInitializeSystemZTarget()39706b4fc4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZTarget() {
4059d6cff9SDimitry Andric // Register the target.
41b915e9e0SDimitry Andric RegisterTargetMachine<SystemZTargetMachine> X(getTheSystemZTarget());
426f8fc217SDimitry Andric auto &PR = *PassRegistry::getPassRegistry();
436f8fc217SDimitry Andric initializeSystemZElimComparePass(PR);
446f8fc217SDimitry Andric initializeSystemZShortenInstPass(PR);
456f8fc217SDimitry Andric initializeSystemZLongBranchPass(PR);
466f8fc217SDimitry Andric initializeSystemZLDCleanupPass(PR);
476f8fc217SDimitry Andric initializeSystemZShortenInstPass(PR);
486f8fc217SDimitry Andric initializeSystemZPostRewritePass(PR);
496f8fc217SDimitry Andric initializeSystemZTDCPassPass(PR);
50ac9a064cSDimitry Andric initializeSystemZDAGToDAGISelLegacyPass(PR);
5159d6cff9SDimitry Andric }
5259d6cff9SDimitry Andric
computeDataLayout(const Triple & TT)53e3b55780SDimitry Andric static std::string computeDataLayout(const Triple &TT) {
5471d5a254SDimitry Andric std::string Ret;
555a5ac124SDimitry Andric
565a5ac124SDimitry Andric // Big endian.
575a5ac124SDimitry Andric Ret += "E";
585a5ac124SDimitry Andric
595a5ac124SDimitry Andric // Data mangling.
603a0822f0SDimitry Andric Ret += DataLayout::getManglingComponent(TT);
615a5ac124SDimitry Andric
625a5ac124SDimitry Andric // Make sure that global data has at least 16 bits of alignment by
635a5ac124SDimitry Andric // default, so that we can refer to it using LARL. We don't have any
645a5ac124SDimitry Andric // special requirements for stack variables though.
655a5ac124SDimitry Andric Ret += "-i1:8:16-i8:8:16";
665a5ac124SDimitry Andric
675a5ac124SDimitry Andric // 64-bit integers are naturally aligned.
685a5ac124SDimitry Andric Ret += "-i64:64";
695a5ac124SDimitry Andric
705a5ac124SDimitry Andric // 128-bit floats are aligned only to 64 bits.
715a5ac124SDimitry Andric Ret += "-f128:64";
725a5ac124SDimitry Andric
73e3b55780SDimitry Andric // The DataLayout string always holds a vector alignment of 64 bits, see
74e3b55780SDimitry Andric // comment in clang/lib/Basic/Targets/SystemZ.h.
755a5ac124SDimitry Andric Ret += "-v128:64";
765a5ac124SDimitry Andric
775a5ac124SDimitry Andric // We prefer 16 bits of aligned for all globals; see above.
785a5ac124SDimitry Andric Ret += "-a:8:16";
795a5ac124SDimitry Andric
805a5ac124SDimitry Andric // Integer registers are 32 or 64 bits.
815a5ac124SDimitry Andric Ret += "-n32:64";
825a5ac124SDimitry Andric
835a5ac124SDimitry Andric return Ret;
845a5ac124SDimitry Andric }
855a5ac124SDimitry Andric
createTLOF(const Triple & TT)86344a3780SDimitry Andric static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
87344a3780SDimitry Andric if (TT.isOSzOS())
88344a3780SDimitry Andric return std::make_unique<TargetLoweringObjectFileGOFF>();
89344a3780SDimitry Andric
90344a3780SDimitry Andric // Note: Some times run with -triple s390x-unknown.
91344a3780SDimitry Andric // In this case, default to ELF unless z/OS specifically provided.
92ac9a064cSDimitry Andric return std::make_unique<SystemZELFTargetObjectFile>();
93344a3780SDimitry Andric }
94344a3780SDimitry Andric
getEffectiveRelocModel(std::optional<Reloc::Model> RM)95e3b55780SDimitry Andric static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
9601095a5dSDimitry Andric // Static code is suitable for use in a dynamic executable; there is no
9701095a5dSDimitry Andric // separate DynamicNoPIC model.
98145449b1SDimitry Andric if (!RM || *RM == Reloc::DynamicNoPIC)
9901095a5dSDimitry Andric return Reloc::Static;
10001095a5dSDimitry Andric return *RM;
10101095a5dSDimitry Andric }
10201095a5dSDimitry Andric
103044eb2f6SDimitry Andric // For SystemZ we define the models as follows:
104044eb2f6SDimitry Andric //
105044eb2f6SDimitry Andric // Small: BRASL can call any function and will use a stub if necessary.
106044eb2f6SDimitry Andric // Locally-binding symbols will always be in range of LARL.
107044eb2f6SDimitry Andric //
108044eb2f6SDimitry Andric // Medium: BRASL can call any function and will use a stub if necessary.
109044eb2f6SDimitry Andric // GOT slots and locally-defined text will always be in range
110044eb2f6SDimitry Andric // of LARL, but other symbols might not be.
111044eb2f6SDimitry Andric //
112044eb2f6SDimitry Andric // Large: Equivalent to Medium for now.
113044eb2f6SDimitry Andric //
114044eb2f6SDimitry Andric // Kernel: Equivalent to Medium for now.
115044eb2f6SDimitry Andric //
116044eb2f6SDimitry Andric // This means that any PIC module smaller than 4GB meets the
117044eb2f6SDimitry Andric // requirements of Small, so Small seems like the best default there.
118044eb2f6SDimitry Andric //
119044eb2f6SDimitry Andric // All symbols bind locally in a non-PIC module, so the choice is less
120044eb2f6SDimitry Andric // obvious. There are two cases:
121044eb2f6SDimitry Andric //
122044eb2f6SDimitry Andric // - When creating an executable, PLTs and copy relocations allow
123044eb2f6SDimitry Andric // us to treat external symbols as part of the executable.
124044eb2f6SDimitry Andric // Any executable smaller than 4GB meets the requirements of Small,
125044eb2f6SDimitry Andric // so that seems like the best default.
126044eb2f6SDimitry Andric //
127044eb2f6SDimitry Andric // - When creating JIT code, stubs will be in range of BRASL if the
128044eb2f6SDimitry Andric // image is less than 4GB in size. GOT entries will likewise be
129044eb2f6SDimitry Andric // in range of LARL. However, the JIT environment has no equivalent
130044eb2f6SDimitry Andric // of copy relocs, so locally-binding data symbols might not be in
131044eb2f6SDimitry Andric // the range of LARL. We need the Medium model in that case.
132d8e91e46SDimitry Andric static CodeModel::Model
getEffectiveSystemZCodeModel(std::optional<CodeModel::Model> CM,Reloc::Model RM,bool JIT)133e3b55780SDimitry Andric getEffectiveSystemZCodeModel(std::optional<CodeModel::Model> CM,
134e3b55780SDimitry Andric Reloc::Model RM, bool JIT) {
135d8e91e46SDimitry Andric if (CM) {
136d8e91e46SDimitry Andric if (*CM == CodeModel::Tiny)
137e6d15924SDimitry Andric report_fatal_error("Target does not support the tiny CodeModel", false);
138d8e91e46SDimitry Andric if (*CM == CodeModel::Kernel)
139e6d15924SDimitry Andric report_fatal_error("Target does not support the kernel CodeModel", false);
140044eb2f6SDimitry Andric return *CM;
141d8e91e46SDimitry Andric }
142044eb2f6SDimitry Andric if (JIT)
143044eb2f6SDimitry Andric return RM == Reloc::PIC_ ? CodeModel::Small : CodeModel::Medium;
144044eb2f6SDimitry Andric return CodeModel::Small;
145044eb2f6SDimitry Andric }
146044eb2f6SDimitry Andric
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)1473a0822f0SDimitry Andric SystemZTargetMachine::SystemZTargetMachine(const Target &T, const Triple &TT,
14859d6cff9SDimitry Andric StringRef CPU, StringRef FS,
14959d6cff9SDimitry Andric const TargetOptions &Options,
150e3b55780SDimitry Andric std::optional<Reloc::Model> RM,
151e3b55780SDimitry Andric std::optional<CodeModel::Model> CM,
152b1c73532SDimitry Andric CodeGenOptLevel OL, bool JIT)
153044eb2f6SDimitry Andric : LLVMTargetMachine(
154e3b55780SDimitry Andric T, computeDataLayout(TT), TT, CPU, FS, Options,
155044eb2f6SDimitry Andric getEffectiveRelocModel(RM),
156d8e91e46SDimitry Andric getEffectiveSystemZCodeModel(CM, getEffectiveRelocModel(RM), JIT),
157d8e91e46SDimitry Andric OL),
158344a3780SDimitry Andric TLOF(createTLOF(getTargetTriple())) {
159f8af5cf6SDimitry Andric initAsmInfo();
16059d6cff9SDimitry Andric }
16159d6cff9SDimitry Andric
16271d5a254SDimitry Andric SystemZTargetMachine::~SystemZTargetMachine() = default;
16367c32a98SDimitry Andric
164cfca06d7SDimitry Andric const SystemZSubtarget *
getSubtargetImpl(const Function & F) const165cfca06d7SDimitry Andric SystemZTargetMachine::getSubtargetImpl(const Function &F) const {
166cfca06d7SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu");
167145449b1SDimitry Andric Attribute TuneAttr = F.getFnAttribute("tune-cpu");
168cfca06d7SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features");
169cfca06d7SDimitry Andric
170b60736ecSDimitry Andric std::string CPU =
171b60736ecSDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
172145449b1SDimitry Andric std::string TuneCPU =
173145449b1SDimitry Andric TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
174b60736ecSDimitry Andric std::string FS =
175b60736ecSDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
176cfca06d7SDimitry Andric
177cfca06d7SDimitry Andric // FIXME: This is related to the code below to reset the target options,
178b1c73532SDimitry Andric // we need to know whether the soft float and backchain flags are set on the
179b1c73532SDimitry Andric // function, so we can enable them as subtarget features.
180b1c73532SDimitry Andric bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
181b1c73532SDimitry Andric if (SoftFloat)
182cfca06d7SDimitry Andric FS += FS.empty() ? "+soft-float" : ",+soft-float";
183b1c73532SDimitry Andric bool BackChain = F.hasFnAttribute("backchain");
184b1c73532SDimitry Andric if (BackChain)
185b1c73532SDimitry Andric FS += FS.empty() ? "+backchain" : ",+backchain";
186cfca06d7SDimitry Andric
187145449b1SDimitry Andric auto &I = SubtargetMap[CPU + TuneCPU + FS];
188cfca06d7SDimitry Andric if (!I) {
189cfca06d7SDimitry Andric // This needs to be done before we create a new subtarget since any
190cfca06d7SDimitry Andric // creation will depend on the TM and the code generation flags on the
191cfca06d7SDimitry Andric // function that reside in TargetOptions.
192cfca06d7SDimitry Andric resetTargetOptions(F);
193145449b1SDimitry Andric I = std::make_unique<SystemZSubtarget>(TargetTriple, CPU, TuneCPU, FS,
194145449b1SDimitry Andric *this);
195cfca06d7SDimitry Andric }
196cfca06d7SDimitry Andric
197cfca06d7SDimitry Andric return I.get();
198cfca06d7SDimitry Andric }
199cfca06d7SDimitry Andric
20059d6cff9SDimitry Andric namespace {
20171d5a254SDimitry Andric
20259d6cff9SDimitry Andric /// SystemZ Code Generator Pass Configuration Options.
20359d6cff9SDimitry Andric class SystemZPassConfig : public TargetPassConfig {
20459d6cff9SDimitry Andric public:
SystemZPassConfig(SystemZTargetMachine & TM,PassManagerBase & PM)205f382538dSDimitry Andric SystemZPassConfig(SystemZTargetMachine &TM, PassManagerBase &PM)
20659d6cff9SDimitry Andric : TargetPassConfig(TM, PM) {}
20759d6cff9SDimitry Andric
getSystemZTargetMachine() const20859d6cff9SDimitry Andric SystemZTargetMachine &getSystemZTargetMachine() const {
20959d6cff9SDimitry Andric return getTM<SystemZTargetMachine>();
21059d6cff9SDimitry Andric }
21159d6cff9SDimitry Andric
212b915e9e0SDimitry Andric ScheduleDAGInstrs *
createPostMachineScheduler(MachineSchedContext * C) const213b915e9e0SDimitry Andric createPostMachineScheduler(MachineSchedContext *C) const override {
21471d5a254SDimitry Andric return new ScheduleDAGMI(C,
2151d5ae102SDimitry Andric std::make_unique<SystemZPostRASchedStrategy>(C),
216b915e9e0SDimitry Andric /*RemoveKillFlags=*/true);
217b915e9e0SDimitry Andric }
218b915e9e0SDimitry Andric
2195ca98fd9SDimitry Andric void addIRPasses() override;
2205ca98fd9SDimitry Andric bool addInstSelector() override;
221b915e9e0SDimitry Andric bool addILPOpts() override;
222cfca06d7SDimitry Andric void addPreRegAlloc() override;
223e6d15924SDimitry Andric void addPostRewrite() override;
2241d5ae102SDimitry Andric void addPostRegAlloc() override;
22567c32a98SDimitry Andric void addPreSched2() override;
22667c32a98SDimitry Andric void addPreEmitPass() override;
22759d6cff9SDimitry Andric };
22871d5a254SDimitry Andric
22959d6cff9SDimitry Andric } // end anonymous namespace
23059d6cff9SDimitry Andric
addIRPasses()231f8af5cf6SDimitry Andric void SystemZPassConfig::addIRPasses() {
232b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) {
23301095a5dSDimitry Andric addPass(createSystemZTDCPass());
23493c91e39SDimitry Andric addPass(createLoopDataPrefetchPass());
23593c91e39SDimitry Andric }
23601095a5dSDimitry Andric
237ac9a064cSDimitry Andric addPass(createAtomicExpandLegacyPass());
238b1c73532SDimitry Andric
239f8af5cf6SDimitry Andric TargetPassConfig::addIRPasses();
240f8af5cf6SDimitry Andric }
241f8af5cf6SDimitry Andric
addInstSelector()24259d6cff9SDimitry Andric bool SystemZPassConfig::addInstSelector() {
24359d6cff9SDimitry Andric addPass(createSystemZISelDag(getSystemZTargetMachine(), getOptLevel()));
2445a5ac124SDimitry Andric
245b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
2465a5ac124SDimitry Andric addPass(createSystemZLDCleanupPass(getSystemZTargetMachine()));
2475a5ac124SDimitry Andric
24859d6cff9SDimitry Andric return false;
24959d6cff9SDimitry Andric }
25059d6cff9SDimitry Andric
addILPOpts()251b915e9e0SDimitry Andric bool SystemZPassConfig::addILPOpts() {
252b915e9e0SDimitry Andric addPass(&EarlyIfConverterID);
253ac9a064cSDimitry Andric
254ac9a064cSDimitry Andric if (EnableMachineCombinerPass)
255ac9a064cSDimitry Andric addPass(&MachineCombinerID);
256ac9a064cSDimitry Andric
257b915e9e0SDimitry Andric return true;
258b915e9e0SDimitry Andric }
259b915e9e0SDimitry Andric
addPreRegAlloc()260cfca06d7SDimitry Andric void SystemZPassConfig::addPreRegAlloc() {
261cfca06d7SDimitry Andric addPass(createSystemZCopyPhysRegsPass(getSystemZTargetMachine()));
262cfca06d7SDimitry Andric }
263cfca06d7SDimitry Andric
addPostRewrite()264e6d15924SDimitry Andric void SystemZPassConfig::addPostRewrite() {
265e6d15924SDimitry Andric addPass(createSystemZPostRewritePass(getSystemZTargetMachine()));
266e6d15924SDimitry Andric }
267e6d15924SDimitry Andric
addPostRegAlloc()2681d5ae102SDimitry Andric void SystemZPassConfig::addPostRegAlloc() {
269e6d15924SDimitry Andric // PostRewrite needs to be run at -O0 also (in which case addPostRewrite()
270e6d15924SDimitry Andric // is not called).
271b1c73532SDimitry Andric if (getOptLevel() == CodeGenOptLevel::None)
272e6d15924SDimitry Andric addPass(createSystemZPostRewritePass(getSystemZTargetMachine()));
2731d5ae102SDimitry Andric }
274e6d15924SDimitry Andric
addPreSched2()2751d5ae102SDimitry Andric void SystemZPassConfig::addPreSched2() {
276b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
277f8af5cf6SDimitry Andric addPass(&IfConverterID);
278f8af5cf6SDimitry Andric }
279f8af5cf6SDimitry Andric
addPreEmitPass()28067c32a98SDimitry Andric void SystemZPassConfig::addPreEmitPass() {
281dd58ef01SDimitry Andric // Do instruction shortening before compare elimination because some
282dd58ef01SDimitry Andric // vector instructions will be shortened into opcodes that compare
283dd58ef01SDimitry Andric // elimination recognizes.
284b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
285c0981da4SDimitry Andric addPass(createSystemZShortenInstPass(getSystemZTargetMachine()));
286dd58ef01SDimitry Andric
287f8af5cf6SDimitry Andric // We eliminate comparisons here rather than earlier because some
288f8af5cf6SDimitry Andric // transformations can change the set of available CC values and we
289f8af5cf6SDimitry Andric // generally want those transformations to have priority. This is
290f8af5cf6SDimitry Andric // especially true in the commonest case where the result of the comparison
291f8af5cf6SDimitry Andric // is used by a single in-range branch instruction, since we will then
292f8af5cf6SDimitry Andric // be able to fuse the compare and the branch instead.
293f8af5cf6SDimitry Andric //
294f8af5cf6SDimitry Andric // For example, two-address NILF can sometimes be converted into
295f8af5cf6SDimitry Andric // three-address RISBLG. NILF produces a CC value that indicates whether
296f8af5cf6SDimitry Andric // the low word is zero, but RISBLG does not modify CC at all. On the
297f8af5cf6SDimitry Andric // other hand, 64-bit ANDs like NILL can sometimes be converted to RISBG.
298f8af5cf6SDimitry Andric // The CC value produced by NILL isn't useful for our purposes, but the
299f8af5cf6SDimitry Andric // value produced by RISBG can be used for any comparison with zero
300f8af5cf6SDimitry Andric // (not just equality). So there are some transformations that lose
301f8af5cf6SDimitry Andric // CC values (while still being worthwhile) and others that happen to make
302f8af5cf6SDimitry Andric // the CC result more useful than it was originally.
303f8af5cf6SDimitry Andric //
304f8af5cf6SDimitry Andric // Another reason is that we only want to use BRANCH ON COUNT in cases
305f8af5cf6SDimitry Andric // where we know that the count register is not going to be spilled.
306f8af5cf6SDimitry Andric //
307f8af5cf6SDimitry Andric // Doing it so late makes it more likely that a register will be reused
308f8af5cf6SDimitry Andric // between the comparison and the branch, but it isn't clear whether
309f8af5cf6SDimitry Andric // preventing that would be a win or not.
310b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
311c0981da4SDimitry Andric addPass(createSystemZElimComparePass(getSystemZTargetMachine()));
312f8af5cf6SDimitry Andric addPass(createSystemZLongBranchPass(getSystemZTargetMachine()));
313dd58ef01SDimitry Andric
314dd58ef01SDimitry Andric // Do final scheduling after all other optimizations, to get an
315dd58ef01SDimitry Andric // optimal input for the decoder (branch relaxation must happen
316dd58ef01SDimitry Andric // after block placement).
317b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
318dd58ef01SDimitry Andric addPass(&PostMachineSchedulerID);
319f8af5cf6SDimitry Andric }
320f8af5cf6SDimitry Andric
createPassConfig(PassManagerBase & PM)32159d6cff9SDimitry Andric TargetPassConfig *SystemZTargetMachine::createPassConfig(PassManagerBase &PM) {
322f382538dSDimitry Andric return new SystemZPassConfig(*this, PM);
32359d6cff9SDimitry Andric }
3245a5ac124SDimitry Andric
325c7dac04cSDimitry Andric TargetTransformInfo
getTargetTransformInfo(const Function & F) const326145449b1SDimitry Andric SystemZTargetMachine::getTargetTransformInfo(const Function &F) const {
3275a5ac124SDimitry Andric return TargetTransformInfo(SystemZTTIImpl(this, F));
3285a5ac124SDimitry Andric }
329e3b55780SDimitry Andric
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const330e3b55780SDimitry Andric MachineFunctionInfo *SystemZTargetMachine::createMachineFunctionInfo(
331e3b55780SDimitry Andric BumpPtrAllocator &Allocator, const Function &F,
332e3b55780SDimitry Andric const TargetSubtargetInfo *STI) const {
333e3b55780SDimitry Andric return SystemZMachineFunctionInfo::create<SystemZMachineFunctionInfo>(
334e3b55780SDimitry Andric Allocator, F, STI);
335e3b55780SDimitry Andric }
336