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/InitializePasses.h" 29 #include "llvm/MC/TargetRegistry.h" 30 #include "llvm/Pass.h" 31 #include "llvm/Target/TargetOptions.h" 32 #include <optional> 33 34 using namespace llvm; 35 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 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 55 static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) { 56 if (!RM) 57 return Reloc::PIC_; 58 return *RM; 59 } 60 61 // Pin SPIRVTargetObjectFile's vtables to this file. 62 SPIRVTargetObjectFile::~SPIRVTargetObjectFile() {} 63 64 SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT, 65 StringRef CPU, StringRef FS, 66 const TargetOptions &Options, 67 std::optional<Reloc::Model> RM, 68 std::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<SPIRVTargetObjectFile>()), 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: 86 SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM) 87 : TargetPassConfig(TM, PM) {} 88 89 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; 102 void addFastRegAlloc() override {} 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. 111 FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) { 112 return nullptr; 113 } 114 115 // Disable passes that break from assuming no virtual registers exist. 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 disablePass(&MachineLateInstrsCleanupID); 127 128 // Do not work with OpPhi. 129 disablePass(&BranchFolderPassID); 130 disablePass(&MachineBlockPlacementID); 131 132 TargetPassConfig::addPostRegAlloc(); 133 } 134 135 TargetTransformInfo 136 SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const { 137 return TargetTransformInfo(SPIRVTTIImpl(this, F)); 138 } 139 140 TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) { 141 return new SPIRVPassConfig(*this, PM); 142 } 143 144 void SPIRVPassConfig::addIRPasses() { 145 TargetPassConfig::addIRPasses(); 146 addPass(createSPIRVRegularizerPass()); 147 addPass(createSPIRVPrepareFunctionsPass()); 148 } 149 150 void SPIRVPassConfig::addISelPrepare() { 151 addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>())); 152 TargetPassConfig::addISelPrepare(); 153 } 154 155 bool SPIRVPassConfig::addIRTranslator() { 156 addPass(new IRTranslator(getOptLevel())); 157 return false; 158 } 159 160 void SPIRVPassConfig::addPreLegalizeMachineIR() { 161 addPass(createSPIRVPreLegalizerPass()); 162 } 163 164 // Use the default legalizer. 165 bool SPIRVPassConfig::addLegalizeMachineIR() { 166 addPass(new Legalizer()); 167 return false; 168 } 169 170 // Do not add the RegBankSelect pass, as we only ever need virtual registers. 171 bool SPIRVPassConfig::addRegBankSelect() { 172 disablePass(&RegBankSelect::ID); 173 return false; 174 } 175 176 namespace { 177 // A custom subclass of InstructionSelect, which is mostly the same except from 178 // not requiring RegBankSelect to occur previously. 179 class SPIRVInstructionSelect : public InstructionSelect { 180 // We don't use register banks, so unset the requirement for them 181 MachineFunctionProperties getRequiredProperties() const override { 182 return InstructionSelect::getRequiredProperties().reset( 183 MachineFunctionProperties::Property::RegBankSelected); 184 } 185 }; 186 } // namespace 187 188 // Add the custom SPIRVInstructionSelect from above. 189 bool SPIRVPassConfig::addGlobalInstructionSelect() { 190 addPass(new SPIRVInstructionSelect()); 191 return false; 192 } 193