diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-07-03 14:10:23 +0000 |
| commit | 145449b1e420787bb99721a429341fa6be3adfb6 (patch) | |
| tree | 1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp | |
| parent | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff) | |
Diffstat (limited to 'llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp')
| -rw-r--r-- | llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp new file mode 100644 index 000000000000..f7c88a5c6d4a --- /dev/null +++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp @@ -0,0 +1,186 @@ +//===- SPIRVTargetMachine.cpp - Define TargetMachine for SPIR-V -*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implements the info about SPIR-V target spec. +// +//===----------------------------------------------------------------------===// + +#include "SPIRVTargetMachine.h" +#include "SPIRV.h" +#include "SPIRVCallLowering.h" +#include "SPIRVGlobalRegistry.h" +#include "SPIRVLegalizerInfo.h" +#include "SPIRVTargetObjectFile.h" +#include "SPIRVTargetTransformInfo.h" +#include "TargetInfo/SPIRVTargetInfo.h" +#include "llvm/CodeGen/GlobalISel/IRTranslator.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" +#include "llvm/CodeGen/GlobalISel/Legalizer.h" +#include "llvm/CodeGen/GlobalISel/RegBankSelect.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/InitializePasses.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetOptions.h" + +using namespace llvm; + +extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() { + // Register the target. + RegisterTargetMachine<SPIRVTargetMachine> X(getTheSPIRV32Target()); + RegisterTargetMachine<SPIRVTargetMachine> Y(getTheSPIRV64Target()); + + PassRegistry &PR = *PassRegistry::getPassRegistry(); + initializeGlobalISel(PR); + initializeSPIRVModuleAnalysisPass(PR); +} + +static std::string computeDataLayout(const Triple &TT) { + const auto Arch = TT.getArch(); + if (Arch == Triple::spirv32) + return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-" + "v96:128-v192:256-v256:256-v512:512-v1024:1024"; + return "e-i64:64-v16:16-v24:32-v32:32-v48:64-" + "v96:128-v192:256-v256:256-v512:512-v1024:1024"; +} + +static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) { + if (!RM) + return Reloc::PIC_; + return *RM; +} + +// Pin SPIRVTargetObjectFile's vtables to this file. +SPIRVTargetObjectFile::~SPIRVTargetObjectFile() {} + +SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT, + StringRef CPU, StringRef FS, + const TargetOptions &Options, + Optional<Reloc::Model> RM, + Optional<CodeModel::Model> CM, + CodeGenOpt::Level OL, bool JIT) + : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, + getEffectiveRelocModel(RM), + getEffectiveCodeModel(CM, CodeModel::Small), OL), + TLOF(std::make_unique<TargetLoweringObjectFileELF>()), + Subtarget(TT, CPU.str(), FS.str(), *this) { + initAsmInfo(); + setGlobalISel(true); + setFastISel(false); + setO0WantsFastISel(false); + setRequiresStructuredCFG(false); +} + +namespace { +// SPIR-V Code Generator Pass Configuration Options. +class SPIRVPassConfig : public TargetPassConfig { +public: + SPIRVPassConfig(SPIRVTargetMachine &TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + SPIRVTargetMachine &getSPIRVTargetMachine() const { + return getTM<SPIRVTargetMachine>(); + } + void addIRPasses() override; + void addISelPrepare() override; + + bool addIRTranslator() override; + void addPreLegalizeMachineIR() override; + bool addLegalizeMachineIR() override; + bool addRegBankSelect() override; + bool addGlobalInstructionSelect() override; + + FunctionPass *createTargetRegisterAllocator(bool) override; + void addFastRegAlloc() override {} + void addOptimizedRegAlloc() override {} + + void addPostRegAlloc() override; +}; +} // namespace + +// We do not use physical registers, and maintain virtual registers throughout +// the entire pipeline, so return nullptr to disable register allocation. +FunctionPass *SPIRVPassConfig::createTargetRegisterAllocator(bool) { + return nullptr; +} + +// Disable passes that break from assuming no virtual registers exist. +void SPIRVPassConfig::addPostRegAlloc() { + // Do not work with vregs instead of physical regs. + disablePass(&MachineCopyPropagationID); + disablePass(&PostRAMachineSinkingID); + disablePass(&PostRASchedulerID); + disablePass(&FuncletLayoutID); + disablePass(&StackMapLivenessID); + disablePass(&PatchableFunctionID); + disablePass(&ShrinkWrapID); + disablePass(&LiveDebugValuesID); + + // Do not work with OpPhi. + disablePass(&BranchFolderPassID); + disablePass(&MachineBlockPlacementID); + + TargetPassConfig::addPostRegAlloc(); +} + +TargetTransformInfo +SPIRVTargetMachine::getTargetTransformInfo(const Function &F) const { + return TargetTransformInfo(SPIRVTTIImpl(this, F)); +} + +TargetPassConfig *SPIRVTargetMachine::createPassConfig(PassManagerBase &PM) { + return new SPIRVPassConfig(*this, PM); +} + +void SPIRVPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); } + +void SPIRVPassConfig::addISelPrepare() { + addPass(createSPIRVEmitIntrinsicsPass(&getTM<SPIRVTargetMachine>())); + TargetPassConfig::addISelPrepare(); +} + +bool SPIRVPassConfig::addIRTranslator() { + addPass(new IRTranslator(getOptLevel())); + return false; +} + +void SPIRVPassConfig::addPreLegalizeMachineIR() { + addPass(createSPIRVPreLegalizerPass()); +} + +// Use a default legalizer. +bool SPIRVPassConfig::addLegalizeMachineIR() { + addPass(new Legalizer()); + return false; +} + +// Do not add a RegBankSelect pass, as we only ever need virtual registers. +bool SPIRVPassConfig::addRegBankSelect() { + disablePass(&RegBankSelect::ID); + return false; +} + +namespace { +// A custom subclass of InstructionSelect, which is mostly the same except from +// not requiring RegBankSelect to occur previously. +class SPIRVInstructionSelect : public InstructionSelect { + // We don't use register banks, so unset the requirement for them + MachineFunctionProperties getRequiredProperties() const override { + return InstructionSelect::getRequiredProperties().reset( + MachineFunctionProperties::Property::RegBankSelected); + } +}; +} // namespace + +bool SPIRVPassConfig::addGlobalInstructionSelect() { + addPass(new SPIRVInstructionSelect()); + return false; +} |
