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 "SPIRVTargetObjectFile.h"
16 #include "SPIRVTargetTransformInfo.h"
17 #include "TargetInfo/SPIRVTargetInfo.h"
18 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
19 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
20 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
21 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
22 #include "llvm/CodeGen/Passes.h"
23 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
24 #include "llvm/CodeGen/TargetPassConfig.h"
25 #include "llvm/IR/LegacyPassManager.h"
26 #include "llvm/InitializePasses.h"
27 #include "llvm/MC/TargetRegistry.h"
28 #include "llvm/Pass.h"
29 #include "llvm/Target/TargetOptions.h"
30 
31 using namespace llvm;
32 
33 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() {
34   // Register the target.
35   RegisterTargetMachine<SPIRVTargetMachine> X(getTheSPIRV32Target());
36   RegisterTargetMachine<SPIRVTargetMachine> Y(getTheSPIRV64Target());
37 }
38 
39 static std::string computeDataLayout(const Triple &TT) {
40   std::string DataLayout = "e-m:e";
41 
42   const auto Arch = TT.getArch();
43   if (Arch == Triple::spirv32)
44     DataLayout += "-p:32:32";
45   else if (Arch == Triple::spirv64)
46     DataLayout += "-p:64:64";
47   return DataLayout;
48 }
49 
50 static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
51   if (!RM)
52     return Reloc::PIC_;
53   return *RM;
54 }
55 
56 // Pin SPIRVTargetObjectFile's vtables to this file.
57 SPIRVTargetObjectFile::~SPIRVTargetObjectFile() {}
58 
59 SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT,
60                                        StringRef CPU, StringRef FS,
61                                        const TargetOptions &Options,
62                                        Optional<Reloc::Model> RM,
63                                        Optional<CodeModel::Model> CM,
64                                        CodeGenOpt::Level OL, bool JIT)
65     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
66                         getEffectiveRelocModel(RM),
67                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
68       TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
69       Subtarget(TT, CPU.str(), FS.str(), *this) {
70   initAsmInfo();
71   setGlobalISel(true);
72   setFastISel(false);
73   setO0WantsFastISel(false);
74   setRequiresStructuredCFG(false);
75 }
76 
77 namespace {
78 // SPIR-V Code Generator Pass Configuration Options.
79 class SPIRVPassConfig : public TargetPassConfig {
80 public:
81   SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM)
82       : TargetPassConfig(TM, PM) {}
83 
84   SPIRVTargetMachine &getSPIRVTargetMachine() const {
85     return getTM<SPIRVTargetMachine>();
86   }
87   void addIRPasses() override;
88   void addISelPrepare() override;
89 
90   bool addIRTranslator() override;
91   bool addLegalizeMachineIR() override;
92   bool addRegBankSelect() override;
93   bool addGlobalInstructionSelect() override;
94 
95   FunctionPass *createTargetRegisterAllocator(bool) override;
96   void addFastRegAlloc() override {}
97   void addOptimizedRegAlloc() override {}
98 
99   void addPostRegAlloc() override;
100 };
101 } // namespace
102 
103 // We do not use physical registers, and maintain virtual registers throughout
104 // the entire pipeline, so return nullptr to disable register allocation.
105 FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) {
106   return nullptr;
107 }
108 
109 // Disable passes that break from assuming no virtual registers exist.
110 void SPIRVPassConfig::addPostRegAlloc() {
111   // Do not work with vregs instead of physical regs.
112   disablePass(&MachineCopyPropagationID);
113   disablePass(&PostRAMachineSinkingID);
114   disablePass(&PostRASchedulerID);
115   disablePass(&FuncletLayoutID);
116   disablePass(&StackMapLivenessID);
117   disablePass(&PatchableFunctionID);
118   disablePass(&ShrinkWrapID);
119   disablePass(&LiveDebugValuesID);
120 
121   // Do not work with OpPhi.
122   disablePass(&BranchFolderPassID);
123   disablePass(&MachineBlockPlacementID);
124 
125   TargetPassConfig::addPostRegAlloc();
126 }
127 
128 TargetTransformInfo
129 SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const {
130   return TargetTransformInfo(SPIRVTTIImpl(this, F));
131 }
132 
133 TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) {
134   return new SPIRVPassConfig(*this, PM);
135 }
136 
137 void SPIRVPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); }
138 
139 void SPIRVPassConfig::addISelPrepare() { TargetPassConfig::addISelPrepare(); }
140 
141 bool SPIRVPassConfig::addIRTranslator() {
142   addPass(new IRTranslator(getOptLevel()));
143   return false;
144 }
145 
146 // Use a default legalizer.
147 bool SPIRVPassConfig::addLegalizeMachineIR() {
148   addPass(new Legalizer());
149   return false;
150 }
151 
152 // Do not add a RegBankSelect pass, as we only ever need virtual registers.
153 bool SPIRVPassConfig::addRegBankSelect() {
154   disablePass(&RegBankSelect::ID);
155   return false;
156 }
157 
158 bool SPIRVPassConfig::addGlobalInstructionSelect() {
159   addPass(new InstructionSelect(getOptLevel()));
160   return false;
161 }
162