1*81ad6265SDimitry Andric //===- SPIRVTargetMachine.cpp - Define TargetMachine for SPIR-V -*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric // 9*81ad6265SDimitry Andric // Implements the info about SPIR-V target spec. 10*81ad6265SDimitry Andric // 11*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 12*81ad6265SDimitry Andric 13*81ad6265SDimitry Andric #include "SPIRVTargetMachine.h" 14*81ad6265SDimitry Andric #include "SPIRV.h" 15*81ad6265SDimitry Andric #include "SPIRVCallLowering.h" 16*81ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h" 17*81ad6265SDimitry Andric #include "SPIRVLegalizerInfo.h" 18*81ad6265SDimitry Andric #include "SPIRVTargetObjectFile.h" 19*81ad6265SDimitry Andric #include "SPIRVTargetTransformInfo.h" 20*81ad6265SDimitry Andric #include "TargetInfo/SPIRVTargetInfo.h" 21*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/IRTranslator.h" 22*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" 23*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/Legalizer.h" 24*81ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" 25*81ad6265SDimitry Andric #include "llvm/CodeGen/Passes.h" 26*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 27*81ad6265SDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h" 28*81ad6265SDimitry Andric #include "llvm/IR/LegacyPassManager.h" 29*81ad6265SDimitry Andric #include "llvm/InitializePasses.h" 30*81ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h" 31*81ad6265SDimitry Andric #include "llvm/Pass.h" 32*81ad6265SDimitry Andric #include "llvm/Target/TargetOptions.h" 33*81ad6265SDimitry Andric 34*81ad6265SDimitry Andric using namespace llvm; 35*81ad6265SDimitry Andric 36*81ad6265SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() { 37*81ad6265SDimitry Andric // Register the target. 38*81ad6265SDimitry Andric RegisterTargetMachine<SPIRVTargetMachine> X(getTheSPIRV32Target()); 39*81ad6265SDimitry Andric RegisterTargetMachine<SPIRVTargetMachine> Y(getTheSPIRV64Target()); 40*81ad6265SDimitry Andric 41*81ad6265SDimitry Andric PassRegistry &PR = *PassRegistry::getPassRegistry(); 42*81ad6265SDimitry Andric initializeGlobalISel(PR); 43*81ad6265SDimitry Andric initializeSPIRVModuleAnalysisPass(PR); 44*81ad6265SDimitry Andric } 45*81ad6265SDimitry Andric 46*81ad6265SDimitry Andric static std::string computeDataLayout(const Triple &TT) { 47*81ad6265SDimitry Andric const auto Arch = TT.getArch(); 48*81ad6265SDimitry Andric if (Arch == Triple::spirv32) 49*81ad6265SDimitry Andric return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" 50*81ad6265SDimitry Andric "v96:128-v192:256-v256:256-v512:512-v1024:1024"; 51*81ad6265SDimitry Andric return "e-i64:64-v16:16-v24:32-v32:32-v48:64-" 52*81ad6265SDimitry Andric "v96:128-v192:256-v256:256-v512:512-v1024:1024"; 53*81ad6265SDimitry Andric } 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { 56*81ad6265SDimitry Andric if (!RM) 57*81ad6265SDimitry Andric return Reloc::PIC_; 58*81ad6265SDimitry Andric return *RM; 59*81ad6265SDimitry Andric } 60*81ad6265SDimitry Andric 61*81ad6265SDimitry Andric // Pin SPIRVTargetObjectFile's vtables to this file. 62*81ad6265SDimitry Andric SPIRVTargetObjectFile::~SPIRVTargetObjectFile() {} 63*81ad6265SDimitry Andric 64*81ad6265SDimitry Andric SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT, 65*81ad6265SDimitry Andric StringRef CPU, StringRef FS, 66*81ad6265SDimitry Andric const TargetOptions &Options, 67*81ad6265SDimitry Andric Optional<Reloc::Model> RM, 68*81ad6265SDimitry Andric Optional<CodeModel::Model> CM, 69*81ad6265SDimitry Andric CodeGenOpt::Level OL, bool JIT) 70*81ad6265SDimitry Andric : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, 71*81ad6265SDimitry Andric getEffectiveRelocModel(RM), 72*81ad6265SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Small), OL), 73*81ad6265SDimitry Andric TLOF(std::make_unique<TargetLoweringObjectFileELF>()), 74*81ad6265SDimitry Andric Subtarget(TT, CPU.str(), FS.str(), *this) { 75*81ad6265SDimitry Andric initAsmInfo(); 76*81ad6265SDimitry Andric setGlobalISel(true); 77*81ad6265SDimitry Andric setFastISel(false); 78*81ad6265SDimitry Andric setO0WantsFastISel(false); 79*81ad6265SDimitry Andric setRequiresStructuredCFG(false); 80*81ad6265SDimitry Andric } 81*81ad6265SDimitry Andric 82*81ad6265SDimitry Andric namespace { 83*81ad6265SDimitry Andric // SPIR-V Code Generator Pass Configuration Options. 84*81ad6265SDimitry Andric class SPIRVPassConfig : public TargetPassConfig { 85*81ad6265SDimitry Andric public: 86*81ad6265SDimitry Andric SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM) 87*81ad6265SDimitry Andric : TargetPassConfig(TM, PM) {} 88*81ad6265SDimitry Andric 89*81ad6265SDimitry Andric SPIRVTargetMachine &getSPIRVTargetMachine() const { 90*81ad6265SDimitry Andric return getTM<SPIRVTargetMachine>(); 91*81ad6265SDimitry Andric } 92*81ad6265SDimitry Andric void addIRPasses() override; 93*81ad6265SDimitry Andric void addISelPrepare() override; 94*81ad6265SDimitry Andric 95*81ad6265SDimitry Andric bool addIRTranslator() override; 96*81ad6265SDimitry Andric void addPreLegalizeMachineIR() override; 97*81ad6265SDimitry Andric bool addLegalizeMachineIR() override; 98*81ad6265SDimitry Andric bool addRegBankSelect() override; 99*81ad6265SDimitry Andric bool addGlobalInstructionSelect() override; 100*81ad6265SDimitry Andric 101*81ad6265SDimitry Andric FunctionPass *createTargetRegisterAllocator(bool) override; 102*81ad6265SDimitry Andric void addFastRegAlloc() override {} 103*81ad6265SDimitry Andric void addOptimizedRegAlloc() override {} 104*81ad6265SDimitry Andric 105*81ad6265SDimitry Andric void addPostRegAlloc() override; 106*81ad6265SDimitry Andric }; 107*81ad6265SDimitry Andric } // namespace 108*81ad6265SDimitry Andric 109*81ad6265SDimitry Andric // We do not use physical registers, and maintain virtual registers throughout 110*81ad6265SDimitry Andric // the entire pipeline, so return nullptr to disable register allocation. 111*81ad6265SDimitry Andric FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) { 112*81ad6265SDimitry Andric return nullptr; 113*81ad6265SDimitry Andric } 114*81ad6265SDimitry Andric 115*81ad6265SDimitry Andric // Disable passes that break from assuming no virtual registers exist. 116*81ad6265SDimitry Andric void SPIRVPassConfig::addPostRegAlloc() { 117*81ad6265SDimitry Andric // Do not work with vregs instead of physical regs. 118*81ad6265SDimitry Andric disablePass(&MachineCopyPropagationID); 119*81ad6265SDimitry Andric disablePass(&PostRAMachineSinkingID); 120*81ad6265SDimitry Andric disablePass(&PostRASchedulerID); 121*81ad6265SDimitry Andric disablePass(&FuncletLayoutID); 122*81ad6265SDimitry Andric disablePass(&StackMapLivenessID); 123*81ad6265SDimitry Andric disablePass(&PatchableFunctionID); 124*81ad6265SDimitry Andric disablePass(&ShrinkWrapID); 125*81ad6265SDimitry Andric disablePass(&LiveDebugValuesID); 126*81ad6265SDimitry Andric 127*81ad6265SDimitry Andric // Do not work with OpPhi. 128*81ad6265SDimitry Andric disablePass(&BranchFolderPassID); 129*81ad6265SDimitry Andric disablePass(&MachineBlockPlacementID); 130*81ad6265SDimitry Andric 131*81ad6265SDimitry Andric TargetPassConfig::addPostRegAlloc(); 132*81ad6265SDimitry Andric } 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric TargetTransformInfo 135*81ad6265SDimitry Andric SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const { 136*81ad6265SDimitry Andric return TargetTransformInfo(SPIRVTTIImpl(this, F)); 137*81ad6265SDimitry Andric } 138*81ad6265SDimitry Andric 139*81ad6265SDimitry Andric TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) { 140*81ad6265SDimitry Andric return new SPIRVPassConfig(*this, PM); 141*81ad6265SDimitry Andric } 142*81ad6265SDimitry Andric 143*81ad6265SDimitry Andric void SPIRVPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); } 144*81ad6265SDimitry Andric 145*81ad6265SDimitry Andric void SPIRVPassConfig::addISelPrepare() { 146*81ad6265SDimitry Andric addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>())); 147*81ad6265SDimitry Andric TargetPassConfig::addISelPrepare(); 148*81ad6265SDimitry Andric } 149*81ad6265SDimitry Andric 150*81ad6265SDimitry Andric bool SPIRVPassConfig::addIRTranslator() { 151*81ad6265SDimitry Andric addPass(new IRTranslator(getOptLevel())); 152*81ad6265SDimitry Andric return false; 153*81ad6265SDimitry Andric } 154*81ad6265SDimitry Andric 155*81ad6265SDimitry Andric void SPIRVPassConfig::addPreLegalizeMachineIR() { 156*81ad6265SDimitry Andric addPass(createSPIRVPreLegalizerPass()); 157*81ad6265SDimitry Andric } 158*81ad6265SDimitry Andric 159*81ad6265SDimitry Andric // Use a default legalizer. 160*81ad6265SDimitry Andric bool SPIRVPassConfig::addLegalizeMachineIR() { 161*81ad6265SDimitry Andric addPass(new Legalizer()); 162*81ad6265SDimitry Andric return false; 163*81ad6265SDimitry Andric } 164*81ad6265SDimitry Andric 165*81ad6265SDimitry Andric // Do not add a RegBankSelect pass, as we only ever need virtual registers. 166*81ad6265SDimitry Andric bool SPIRVPassConfig::addRegBankSelect() { 167*81ad6265SDimitry Andric disablePass(&RegBankSelect::ID); 168*81ad6265SDimitry Andric return false; 169*81ad6265SDimitry Andric } 170*81ad6265SDimitry Andric 171*81ad6265SDimitry Andric namespace { 172*81ad6265SDimitry Andric // A custom subclass of InstructionSelect, which is mostly the same except from 173*81ad6265SDimitry Andric // not requiring RegBankSelect to occur previously. 174*81ad6265SDimitry Andric class SPIRVInstructionSelect : public InstructionSelect { 175*81ad6265SDimitry Andric // We don't use register banks, so unset the requirement for them 176*81ad6265SDimitry Andric MachineFunctionProperties getRequiredProperties() const override { 177*81ad6265SDimitry Andric return InstructionSelect::getRequiredProperties().reset( 178*81ad6265SDimitry Andric MachineFunctionProperties::Property::RegBankSelected); 179*81ad6265SDimitry Andric } 180*81ad6265SDimitry Andric }; 181*81ad6265SDimitry Andric } // namespace 182*81ad6265SDimitry Andric 183*81ad6265SDimitry Andric bool SPIRVPassConfig::addGlobalInstructionSelect() { 184*81ad6265SDimitry Andric addPass(new SPIRVInstructionSelect()); 185*81ad6265SDimitry Andric return false; 186*81ad6265SDimitry Andric } 187