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