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 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 } 44 45 static std::string computeDataLayout(const Triple &TT) { 46 std::string DataLayout = "e-m:e"; 47 48 const auto Arch = TT.getArch(); 49 if (Arch == Triple::spirv32) 50 DataLayout += "-p:32:32"; 51 else if (Arch == Triple::spirv64) 52 DataLayout += "-p:64:64"; 53 return DataLayout; 54 } 55 56 static Reloc::Model getEffectiveRelocModel(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 Optional<Reloc::Model> RM, 69 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<TargetLoweringObjectFileELF>()), 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 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 127 // Do not work with OpPhi. 128 disablePass(&BranchFolderPassID); 129 disablePass(&MachineBlockPlacementID); 130 131 TargetPassConfig::addPostRegAlloc(); 132 } 133 134 TargetTransformInfo 135 SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const { 136 return TargetTransformInfo(SPIRVTTIImpl(this, F)); 137 } 138 139 TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) { 140 return new SPIRVPassConfig(*this, PM); 141 } 142 143 void SPIRVPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); } 144 145 void SPIRVPassConfig::addISelPrepare() { TargetPassConfig::addISelPrepare(); } 146 147 bool SPIRVPassConfig::addIRTranslator() { 148 addPass(new IRTranslator(getOptLevel())); 149 return false; 150 } 151 152 // Use a default legalizer. 153 bool SPIRVPassConfig::addLegalizeMachineIR() { 154 addPass(new Legalizer()); 155 return false; 156 } 157 158 // Do not add a RegBankSelect pass, as we only ever need virtual registers. 159 bool SPIRVPassConfig::addRegBankSelect() { 160 disablePass(&RegBankSelect::ID); 161 return false; 162 } 163 164 namespace { 165 // A custom subclass of InstructionSelect, which is mostly the same except from 166 // not requiring RegBankSelect to occur previously. 167 class SPIRVInstructionSelect : public InstructionSelect { 168 // We don't use register banks, so unset the requirement for them 169 MachineFunctionProperties getRequiredProperties() const override { 170 return InstructionSelect::getRequiredProperties().reset( 171 MachineFunctionProperties::Property::RegBankSelected); 172 } 173 }; 174 } // namespace 175 176 bool SPIRVPassConfig::addGlobalInstructionSelect() { 177 addPass(new SPIRVInstructionSelect()); 178 return false; 179 } 180