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