17fd4622dSIlia Diachkov //===- SPIRVTargetMachine.cpp - Define TargetMachine for SPIR-V -*- C++ -*-===//
27fd4622dSIlia Diachkov //
37fd4622dSIlia Diachkov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fd4622dSIlia Diachkov // See https://llvm.org/LICENSE.txt for license information.
57fd4622dSIlia Diachkov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fd4622dSIlia Diachkov //
77fd4622dSIlia Diachkov //===----------------------------------------------------------------------===//
87fd4622dSIlia Diachkov //
97fd4622dSIlia Diachkov // Implements the info about SPIR-V target spec.
107fd4622dSIlia Diachkov //
117fd4622dSIlia Diachkov //===----------------------------------------------------------------------===//
127fd4622dSIlia Diachkov
137fd4622dSIlia Diachkov #include "SPIRVTargetMachine.h"
14ec259036SIlia Diachkov #include "SPIRV.h"
15eab7d363SIlia Diachkov #include "SPIRVCallLowering.h"
16eab7d363SIlia Diachkov #include "SPIRVGlobalRegistry.h"
17eab7d363SIlia Diachkov #include "SPIRVLegalizerInfo.h"
18ec259036SIlia Diachkov #include "SPIRVTargetObjectFile.h"
19ec259036SIlia Diachkov #include "SPIRVTargetTransformInfo.h"
207fd4622dSIlia Diachkov #include "TargetInfo/SPIRVTargetInfo.h"
21ec259036SIlia Diachkov #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
22ec259036SIlia Diachkov #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
23ec259036SIlia Diachkov #include "llvm/CodeGen/GlobalISel/Legalizer.h"
24ec259036SIlia Diachkov #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
25ec259036SIlia Diachkov #include "llvm/CodeGen/Passes.h"
267fd4622dSIlia Diachkov #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
277fd4622dSIlia Diachkov #include "llvm/CodeGen/TargetPassConfig.h"
28ec259036SIlia Diachkov #include "llvm/IR/LegacyPassManager.h"
29ec259036SIlia Diachkov #include "llvm/InitializePasses.h"
307fd4622dSIlia Diachkov #include "llvm/MC/TargetRegistry.h"
31ec259036SIlia Diachkov #include "llvm/Pass.h"
32ec259036SIlia Diachkov #include "llvm/Target/TargetOptions.h"
337fd4622dSIlia Diachkov
347fd4622dSIlia Diachkov using namespace llvm;
357fd4622dSIlia Diachkov
LLVMInitializeSPIRVTarget()367fd4622dSIlia Diachkov extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() {
377fd4622dSIlia Diachkov // Register the target.
387fd4622dSIlia Diachkov RegisterTargetMachine<SPIRVTargetMachine> X(getTheSPIRV32Target());
397fd4622dSIlia Diachkov RegisterTargetMachine<SPIRVTargetMachine> Y(getTheSPIRV64Target());
40eab7d363SIlia Diachkov
41eab7d363SIlia Diachkov PassRegistry &PR = *PassRegistry::getPassRegistry();
42eab7d363SIlia Diachkov initializeGlobalISel(PR);
43153dee34SIlia Diachkov initializeSPIRVModuleAnalysisPass(PR);
447fd4622dSIlia Diachkov }
457fd4622dSIlia Diachkov
computeDataLayout(const Triple & TT)467fd4622dSIlia Diachkov static std::string computeDataLayout(const Triple &TT) {
477fd4622dSIlia Diachkov const auto Arch = TT.getArch();
487fd4622dSIlia Diachkov if (Arch == Triple::spirv32)
490098f2aeSIlia Diachkov return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
500098f2aeSIlia Diachkov "v96:128-v192:256-v256:256-v512:512-v1024:1024";
510098f2aeSIlia Diachkov return "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
520098f2aeSIlia Diachkov "v96:128-v192:256-v256:256-v512:512-v1024:1024";
537fd4622dSIlia Diachkov }
547fd4622dSIlia Diachkov
getEffectiveRelocModel(Optional<Reloc::Model> RM)557fd4622dSIlia Diachkov static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
567fd4622dSIlia Diachkov if (!RM)
577fd4622dSIlia Diachkov return Reloc::PIC_;
587fd4622dSIlia Diachkov return *RM;
597fd4622dSIlia Diachkov }
607fd4622dSIlia Diachkov
61ec259036SIlia Diachkov // Pin SPIRVTargetObjectFile's vtables to this file.
~SPIRVTargetObjectFile()62ec259036SIlia Diachkov SPIRVTargetObjectFile::~SPIRVTargetObjectFile() {}
63ec259036SIlia Diachkov
SPIRVTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,Optional<Reloc::Model> RM,Optional<CodeModel::Model> CM,CodeGenOpt::Level OL,bool JIT)647fd4622dSIlia Diachkov SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT,
657fd4622dSIlia Diachkov StringRef CPU, StringRef FS,
667fd4622dSIlia Diachkov const TargetOptions &Options,
677fd4622dSIlia Diachkov Optional<Reloc::Model> RM,
687fd4622dSIlia Diachkov Optional<CodeModel::Model> CM,
697fd4622dSIlia Diachkov CodeGenOpt::Level OL, bool JIT)
707fd4622dSIlia Diachkov : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
717fd4622dSIlia Diachkov getEffectiveRelocModel(RM),
727fd4622dSIlia Diachkov getEffectiveCodeModel(CM, CodeModel::Small), OL),
73ec259036SIlia Diachkov TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
74ec259036SIlia Diachkov Subtarget(TT, CPU.str(), FS.str(), *this) {
757fd4622dSIlia Diachkov initAsmInfo();
76ec259036SIlia Diachkov setGlobalISel(true);
77ec259036SIlia Diachkov setFastISel(false);
78ec259036SIlia Diachkov setO0WantsFastISel(false);
79ec259036SIlia Diachkov setRequiresStructuredCFG(false);
807fd4622dSIlia Diachkov }
817fd4622dSIlia Diachkov
827fd4622dSIlia Diachkov namespace {
837fd4622dSIlia Diachkov // SPIR-V Code Generator Pass Configuration Options.
847fd4622dSIlia Diachkov class SPIRVPassConfig : public TargetPassConfig {
857fd4622dSIlia Diachkov public:
SPIRVPassConfig(SPIRVTargetMachine & TM,PassManagerBase & PM)867fd4622dSIlia Diachkov SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM)
877fd4622dSIlia Diachkov : TargetPassConfig(TM, PM) {}
887fd4622dSIlia Diachkov
getSPIRVTargetMachine() const897fd4622dSIlia Diachkov SPIRVTargetMachine &getSPIRVTargetMachine() const {
907fd4622dSIlia Diachkov return getTM<SPIRVTargetMachine>();
917fd4622dSIlia Diachkov }
92ec259036SIlia Diachkov void addIRPasses() override;
93ec259036SIlia Diachkov void addISelPrepare() override;
94ec259036SIlia Diachkov
95ec259036SIlia Diachkov bool addIRTranslator() override;
960098f2aeSIlia Diachkov void addPreLegalizeMachineIR() override;
97ec259036SIlia Diachkov bool addLegalizeMachineIR() override;
98ec259036SIlia Diachkov bool addRegBankSelect() override;
99ec259036SIlia Diachkov bool addGlobalInstructionSelect() override;
100ec259036SIlia Diachkov
101ec259036SIlia Diachkov FunctionPass *createTargetRegisterAllocator(bool) override;
addFastRegAlloc()102ec259036SIlia Diachkov void addFastRegAlloc() override {}
addOptimizedRegAlloc()103ec259036SIlia Diachkov void addOptimizedRegAlloc() override {}
104ec259036SIlia Diachkov
105ec259036SIlia Diachkov void addPostRegAlloc() override;
1067fd4622dSIlia Diachkov };
1077fd4622dSIlia Diachkov } // namespace
1087fd4622dSIlia Diachkov
109ec259036SIlia Diachkov // We do not use physical registers, and maintain virtual registers throughout
110ec259036SIlia Diachkov // the entire pipeline, so return nullptr to disable register allocation.
createTargetRegisterAllocator(bool)111ec259036SIlia Diachkov FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) {
112ec259036SIlia Diachkov return nullptr;
113ec259036SIlia Diachkov }
114ec259036SIlia Diachkov
115ec259036SIlia Diachkov // Disable passes that break from assuming no virtual registers exist.
addPostRegAlloc()116ec259036SIlia Diachkov void SPIRVPassConfig::addPostRegAlloc() {
117ec259036SIlia Diachkov // Do not work with vregs instead of physical regs.
118ec259036SIlia Diachkov disablePass(&MachineCopyPropagationID);
119ec259036SIlia Diachkov disablePass(&PostRAMachineSinkingID);
120ec259036SIlia Diachkov disablePass(&PostRASchedulerID);
121ec259036SIlia Diachkov disablePass(&FuncletLayoutID);
122ec259036SIlia Diachkov disablePass(&StackMapLivenessID);
123ec259036SIlia Diachkov disablePass(&PatchableFunctionID);
124ec259036SIlia Diachkov disablePass(&ShrinkWrapID);
125ec259036SIlia Diachkov disablePass(&LiveDebugValuesID);
126ec259036SIlia Diachkov
127ec259036SIlia Diachkov // Do not work with OpPhi.
128ec259036SIlia Diachkov disablePass(&BranchFolderPassID);
129ec259036SIlia Diachkov disablePass(&MachineBlockPlacementID);
130ec259036SIlia Diachkov
131ec259036SIlia Diachkov TargetPassConfig::addPostRegAlloc();
132ec259036SIlia Diachkov }
133ec259036SIlia Diachkov
134ec259036SIlia Diachkov TargetTransformInfo
getTargetTransformInfo(const Function & F) const135ec259036SIlia Diachkov SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const {
136ec259036SIlia Diachkov return TargetTransformInfo(SPIRVTTIImpl(this, F));
137ec259036SIlia Diachkov }
138ec259036SIlia Diachkov
createPassConfig(PassManagerBase & PM)1397fd4622dSIlia Diachkov TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) {
1407fd4622dSIlia Diachkov return new SPIRVPassConfig(*this, PM);
1417fd4622dSIlia Diachkov }
142ec259036SIlia Diachkov
addIRPasses()143*b8e1544bSIlia Diachkov void SPIRVPassConfig::addIRPasses() {
144*b8e1544bSIlia Diachkov TargetPassConfig::addIRPasses();
145*b8e1544bSIlia Diachkov addPass(createSPIRVPrepareFunctionsPass());
146*b8e1544bSIlia Diachkov }
147ec259036SIlia Diachkov
addISelPrepare()1480098f2aeSIlia Diachkov void SPIRVPassConfig::addISelPrepare() {
1490098f2aeSIlia Diachkov addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>()));
1500098f2aeSIlia Diachkov TargetPassConfig::addISelPrepare();
1510098f2aeSIlia Diachkov }
152ec259036SIlia Diachkov
addIRTranslator()153ec259036SIlia Diachkov bool SPIRVPassConfig::addIRTranslator() {
154ec259036SIlia Diachkov addPass(new IRTranslator(getOptLevel()));
155ec259036SIlia Diachkov return false;
156ec259036SIlia Diachkov }
157ec259036SIlia Diachkov
addPreLegalizeMachineIR()1580098f2aeSIlia Diachkov void SPIRVPassConfig::addPreLegalizeMachineIR() {
1590098f2aeSIlia Diachkov addPass(createSPIRVPreLegalizerPass());
1600098f2aeSIlia Diachkov }
1610098f2aeSIlia Diachkov
162ec259036SIlia Diachkov // Use a default legalizer.
addLegalizeMachineIR()163ec259036SIlia Diachkov bool SPIRVPassConfig::addLegalizeMachineIR() {
164ec259036SIlia Diachkov addPass(new Legalizer());
165ec259036SIlia Diachkov return false;
166ec259036SIlia Diachkov }
167ec259036SIlia Diachkov
168ec259036SIlia Diachkov // Do not add a RegBankSelect pass, as we only ever need virtual registers.
addRegBankSelect()169ec259036SIlia Diachkov bool SPIRVPassConfig::addRegBankSelect() {
170ec259036SIlia Diachkov disablePass(&RegBankSelect::ID);
171ec259036SIlia Diachkov return false;
172ec259036SIlia Diachkov }
173ec259036SIlia Diachkov
174eab7d363SIlia Diachkov namespace {
175eab7d363SIlia Diachkov // A custom subclass of InstructionSelect, which is mostly the same except from
176eab7d363SIlia Diachkov // not requiring RegBankSelect to occur previously.
177eab7d363SIlia Diachkov class SPIRVInstructionSelect : public InstructionSelect {
178eab7d363SIlia Diachkov // We don't use register banks, so unset the requirement for them
getRequiredProperties() const179eab7d363SIlia Diachkov MachineFunctionProperties getRequiredProperties() const override {
180eab7d363SIlia Diachkov return InstructionSelect::getRequiredProperties().reset(
181eab7d363SIlia Diachkov MachineFunctionProperties::Property::RegBankSelected);
182eab7d363SIlia Diachkov }
183eab7d363SIlia Diachkov };
184eab7d363SIlia Diachkov } // namespace
185eab7d363SIlia Diachkov
addGlobalInstructionSelect()186ec259036SIlia Diachkov bool SPIRVPassConfig::addGlobalInstructionSelect() {
187eab7d363SIlia Diachkov addPass(new SPIRVInstructionSelect());
188ec259036SIlia Diachkov return false;
189ec259036SIlia Diachkov }
190