xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===- SPIRVTargetMachine.cpp - Define TargetMachine for SPIR-V -*- C++ -*-===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric //
9*81ad6265SDimitry Andric // Implements the info about SPIR-V target spec.
10*81ad6265SDimitry Andric //
11*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
12*81ad6265SDimitry Andric 
13*81ad6265SDimitry Andric #include "SPIRVTargetMachine.h"
14*81ad6265SDimitry Andric #include "SPIRV.h"
15*81ad6265SDimitry Andric #include "SPIRVCallLowering.h"
16*81ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h"
17*81ad6265SDimitry Andric #include "SPIRVLegalizerInfo.h"
18*81ad6265SDimitry Andric #include "SPIRVTargetObjectFile.h"
19*81ad6265SDimitry Andric #include "SPIRVTargetTransformInfo.h"
20*81ad6265SDimitry Andric #include "TargetInfo/SPIRVTargetInfo.h"
21*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
22*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
23*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h"
24*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
25*81ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h"
26*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
27*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
28*81ad6265SDimitry Andric #include "llvm/IR/LegacyPassManager.h"
29*81ad6265SDimitry Andric #include "llvm/InitializePasses.h"
30*81ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h"
31*81ad6265SDimitry Andric #include "llvm/Pass.h"
32*81ad6265SDimitry Andric #include "llvm/Target/TargetOptions.h"
33*81ad6265SDimitry Andric 
34*81ad6265SDimitry Andric using namespace llvm;
35*81ad6265SDimitry Andric 
36*81ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() {
37*81ad6265SDimitry Andric   // Register the target.
38*81ad6265SDimitry Andric   RegisterTargetMachine<SPIRVTargetMachine> X(getTheSPIRV32Target());
39*81ad6265SDimitry Andric   RegisterTargetMachine<SPIRVTargetMachine> Y(getTheSPIRV64Target());
40*81ad6265SDimitry Andric 
41*81ad6265SDimitry Andric   PassRegistry &PR = *PassRegistry::getPassRegistry();
42*81ad6265SDimitry Andric   initializeGlobalISel(PR);
43*81ad6265SDimitry Andric   initializeSPIRVModuleAnalysisPass(PR);
44*81ad6265SDimitry Andric }
45*81ad6265SDimitry Andric 
46*81ad6265SDimitry Andric static std::string computeDataLayout(const Triple &TT) {
47*81ad6265SDimitry Andric   const auto Arch = TT.getArch();
48*81ad6265SDimitry Andric   if (Arch == Triple::spirv32)
49*81ad6265SDimitry Andric     return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
50*81ad6265SDimitry Andric            "v96:128-v192:256-v256:256-v512:512-v1024:1024";
51*81ad6265SDimitry Andric   return "e-i64:64-v16:16-v24:32-v32:32-v48:64-"
52*81ad6265SDimitry Andric          "v96:128-v192:256-v256:256-v512:512-v1024:1024";
53*81ad6265SDimitry Andric }
54*81ad6265SDimitry Andric 
55*81ad6265SDimitry Andric static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
56*81ad6265SDimitry Andric   if (!RM)
57*81ad6265SDimitry Andric     return Reloc::PIC_;
58*81ad6265SDimitry Andric   return *RM;
59*81ad6265SDimitry Andric }
60*81ad6265SDimitry Andric 
61*81ad6265SDimitry Andric // Pin SPIRVTargetObjectFile's vtables to this file.
62*81ad6265SDimitry Andric SPIRVTargetObjectFile::~SPIRVTargetObjectFile() {}
63*81ad6265SDimitry Andric 
64*81ad6265SDimitry Andric SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT,
65*81ad6265SDimitry Andric                                        StringRef CPU, StringRef FS,
66*81ad6265SDimitry Andric                                        const TargetOptions &Options,
67*81ad6265SDimitry Andric                                        Optional<Reloc::Model> RM,
68*81ad6265SDimitry Andric                                        Optional<CodeModel::Model> CM,
69*81ad6265SDimitry Andric                                        CodeGenOpt::Level OL, bool JIT)
70*81ad6265SDimitry Andric     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
71*81ad6265SDimitry Andric                         getEffectiveRelocModel(RM),
72*81ad6265SDimitry Andric                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
73*81ad6265SDimitry Andric       TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
74*81ad6265SDimitry Andric       Subtarget(TT, CPU.str(), FS.str(), *this) {
75*81ad6265SDimitry Andric   initAsmInfo();
76*81ad6265SDimitry Andric   setGlobalISel(true);
77*81ad6265SDimitry Andric   setFastISel(false);
78*81ad6265SDimitry Andric   setO0WantsFastISel(false);
79*81ad6265SDimitry Andric   setRequiresStructuredCFG(false);
80*81ad6265SDimitry Andric }
81*81ad6265SDimitry Andric 
82*81ad6265SDimitry Andric namespace {
83*81ad6265SDimitry Andric // SPIR-V Code Generator Pass Configuration Options.
84*81ad6265SDimitry Andric class SPIRVPassConfig : public TargetPassConfig {
85*81ad6265SDimitry Andric public:
86*81ad6265SDimitry Andric   SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM)
87*81ad6265SDimitry Andric       : TargetPassConfig(TM, PM) {}
88*81ad6265SDimitry Andric 
89*81ad6265SDimitry Andric   SPIRVTargetMachine &getSPIRVTargetMachine() const {
90*81ad6265SDimitry Andric     return getTM<SPIRVTargetMachine>();
91*81ad6265SDimitry Andric   }
92*81ad6265SDimitry Andric   void addIRPasses() override;
93*81ad6265SDimitry Andric   void addISelPrepare() override;
94*81ad6265SDimitry Andric 
95*81ad6265SDimitry Andric   bool addIRTranslator() override;
96*81ad6265SDimitry Andric   void addPreLegalizeMachineIR() override;
97*81ad6265SDimitry Andric   bool addLegalizeMachineIR() override;
98*81ad6265SDimitry Andric   bool addRegBankSelect() override;
99*81ad6265SDimitry Andric   bool addGlobalInstructionSelect() override;
100*81ad6265SDimitry Andric 
101*81ad6265SDimitry Andric   FunctionPass *createTargetRegisterAllocator(bool) override;
102*81ad6265SDimitry Andric   void addFastRegAlloc() override {}
103*81ad6265SDimitry Andric   void addOptimizedRegAlloc() override {}
104*81ad6265SDimitry Andric 
105*81ad6265SDimitry Andric   void addPostRegAlloc() override;
106*81ad6265SDimitry Andric };
107*81ad6265SDimitry Andric } // namespace
108*81ad6265SDimitry Andric 
109*81ad6265SDimitry Andric // We do not use physical registers, and maintain virtual registers throughout
110*81ad6265SDimitry Andric // the entire pipeline, so return nullptr to disable register allocation.
111*81ad6265SDimitry Andric FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) {
112*81ad6265SDimitry Andric   return nullptr;
113*81ad6265SDimitry Andric }
114*81ad6265SDimitry Andric 
115*81ad6265SDimitry Andric // Disable passes that break from assuming no virtual registers exist.
116*81ad6265SDimitry Andric void SPIRVPassConfig::addPostRegAlloc() {
117*81ad6265SDimitry Andric   // Do not work with vregs instead of physical regs.
118*81ad6265SDimitry Andric   disablePass(&MachineCopyPropagationID);
119*81ad6265SDimitry Andric   disablePass(&PostRAMachineSinkingID);
120*81ad6265SDimitry Andric   disablePass(&PostRASchedulerID);
121*81ad6265SDimitry Andric   disablePass(&FuncletLayoutID);
122*81ad6265SDimitry Andric   disablePass(&StackMapLivenessID);
123*81ad6265SDimitry Andric   disablePass(&PatchableFunctionID);
124*81ad6265SDimitry Andric   disablePass(&ShrinkWrapID);
125*81ad6265SDimitry Andric   disablePass(&LiveDebugValuesID);
126*81ad6265SDimitry Andric 
127*81ad6265SDimitry Andric   // Do not work with OpPhi.
128*81ad6265SDimitry Andric   disablePass(&BranchFolderPassID);
129*81ad6265SDimitry Andric   disablePass(&MachineBlockPlacementID);
130*81ad6265SDimitry Andric 
131*81ad6265SDimitry Andric   TargetPassConfig::addPostRegAlloc();
132*81ad6265SDimitry Andric }
133*81ad6265SDimitry Andric 
134*81ad6265SDimitry Andric TargetTransformInfo
135*81ad6265SDimitry Andric SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const {
136*81ad6265SDimitry Andric   return TargetTransformInfo(SPIRVTTIImpl(this, F));
137*81ad6265SDimitry Andric }
138*81ad6265SDimitry Andric 
139*81ad6265SDimitry Andric TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) {
140*81ad6265SDimitry Andric   return new SPIRVPassConfig(*this, PM);
141*81ad6265SDimitry Andric }
142*81ad6265SDimitry Andric 
143*81ad6265SDimitry Andric void SPIRVPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); }
144*81ad6265SDimitry Andric 
145*81ad6265SDimitry Andric void SPIRVPassConfig::addISelPrepare() {
146*81ad6265SDimitry Andric   addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>()));
147*81ad6265SDimitry Andric   TargetPassConfig::addISelPrepare();
148*81ad6265SDimitry Andric }
149*81ad6265SDimitry Andric 
150*81ad6265SDimitry Andric bool SPIRVPassConfig::addIRTranslator() {
151*81ad6265SDimitry Andric   addPass(new IRTranslator(getOptLevel()));
152*81ad6265SDimitry Andric   return false;
153*81ad6265SDimitry Andric }
154*81ad6265SDimitry Andric 
155*81ad6265SDimitry Andric void SPIRVPassConfig::addPreLegalizeMachineIR() {
156*81ad6265SDimitry Andric   addPass(createSPIRVPreLegalizerPass());
157*81ad6265SDimitry Andric }
158*81ad6265SDimitry Andric 
159*81ad6265SDimitry Andric // Use a default legalizer.
160*81ad6265SDimitry Andric bool SPIRVPassConfig::addLegalizeMachineIR() {
161*81ad6265SDimitry Andric   addPass(new Legalizer());
162*81ad6265SDimitry Andric   return false;
163*81ad6265SDimitry Andric }
164*81ad6265SDimitry Andric 
165*81ad6265SDimitry Andric // Do not add a RegBankSelect pass, as we only ever need virtual registers.
166*81ad6265SDimitry Andric bool SPIRVPassConfig::addRegBankSelect() {
167*81ad6265SDimitry Andric   disablePass(&RegBankSelect::ID);
168*81ad6265SDimitry Andric   return false;
169*81ad6265SDimitry Andric }
170*81ad6265SDimitry Andric 
171*81ad6265SDimitry Andric namespace {
172*81ad6265SDimitry Andric // A custom subclass of InstructionSelect, which is mostly the same except from
173*81ad6265SDimitry Andric // not requiring RegBankSelect to occur previously.
174*81ad6265SDimitry Andric class SPIRVInstructionSelect : public InstructionSelect {
175*81ad6265SDimitry Andric   // We don't use register banks, so unset the requirement for them
176*81ad6265SDimitry Andric   MachineFunctionProperties getRequiredProperties() const override {
177*81ad6265SDimitry Andric     return InstructionSelect::getRequiredProperties().reset(
178*81ad6265SDimitry Andric         MachineFunctionProperties::Property::RegBankSelected);
179*81ad6265SDimitry Andric   }
180*81ad6265SDimitry Andric };
181*81ad6265SDimitry Andric } // namespace
182*81ad6265SDimitry Andric 
183*81ad6265SDimitry Andric bool SPIRVPassConfig::addGlobalInstructionSelect() {
184*81ad6265SDimitry Andric   addPass(new SPIRVInstructionSelect());
185*81ad6265SDimitry Andric   return false;
186*81ad6265SDimitry Andric }
187