aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-07-03 14:10:23 +0000
commit145449b1e420787bb99721a429341fa6be3adfb6 (patch)
tree1d56ae694a6de602e348dd80165cf881a36600ed /llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
parentecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (diff)
Diffstat (limited to 'llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp')
-rw-r--r--llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp186
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;
+}