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