[llvm] ec25903 - [SPIR-V](4/6) Add target lowering, TargetMachine and AsmPrinter
Michal Paszkowski via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 19 16:28:12 PDT 2022
Author: Ilia Diachkov
Date: 2022-04-20T01:10:25+02:00
New Revision: ec2590362e155b32c3b767b9dc9bbe5e3296583a
URL: https://github.com/llvm/llvm-project/commit/ec2590362e155b32c3b767b9dc9bbe5e3296583a
DIFF: https://github.com/llvm/llvm-project/commit/ec2590362e155b32c3b767b9dc9bbe5e3296583a.diff
LOG: [SPIR-V](4/6) Add target lowering, TargetMachine and AsmPrinter
The patch contains target lowering for SPIRV. Also it implements
TargetMachine and AsmPrinter.
Differential Revision: https://reviews.llvm.org/D116463
Authors: Aleksandr Bezzubikov, Lewis Crawford, Ilia Diachkov,
Michal Paszkowski, Andrey Tretyakov, Konrad Trifunovic
Co-authored-by: Aleksandr Bezzubikov <zuban32s at gmail.com>
Co-authored-by: Ilia Diachkov <iliya.diyachkov at intel.com>
Co-authored-by: Michal Paszkowski <michal.paszkowski at outlook.com>
Co-authored-by: Andrey Tretyakov <andrey1.tretyakov at intel.com>
Co-authored-by: Konrad Trifunovic <konrad.trifunovic at intel.com>
Added:
llvm/lib/Target/SPIRV/SPIRV.h
llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
llvm/lib/Target/SPIRV/SPIRVCallLowering.h
llvm/lib/Target/SPIRV/SPIRVFrameLowering.h
llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
llvm/lib/Target/SPIRV/SPIRVISelLowering.h
llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp
llvm/lib/Target/SPIRV/SPIRVMCInstLower.h
llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.cpp
llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.h
llvm/lib/Target/SPIRV/SPIRVRegisterInfo.cpp
llvm/lib/Target/SPIRV/SPIRVRegisterInfo.h
llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
llvm/lib/Target/SPIRV/SPIRVSubtarget.h
llvm/lib/Target/SPIRV/SPIRVTargetObjectFile.h
llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h
Modified:
llvm/lib/Target/SPIRV/CMakeLists.txt
llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
llvm/lib/Target/SPIRV/SPIRVTargetMachine.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt
index a6bef10bd4743..31dca146d18fb 100644
--- a/llvm/lib/Target/SPIRV/CMakeLists.txt
+++ b/llvm/lib/Target/SPIRV/CMakeLists.txt
@@ -13,14 +13,26 @@ tablegen(LLVM SPIRVGenSubtargetInfo.inc -gen-subtarget)
add_public_tablegen_target(SPIRVCommonTableGen)
add_llvm_target(SPIRVCodeGen
+ SPIRVAsmPrinter.cpp
+ SPIRVCallLowering.cpp
+ SPIRVInstrInfo.cpp
+ SPIRVISelLowering.cpp
+ SPIRVMCInstLower.cpp
+ SPIRVRegisterBankInfo.cpp
+ SPIRVRegisterInfo.cpp
+ SPIRVSubtarget.cpp
SPIRVTargetMachine.cpp
LINK_COMPONENTS
+ Analysis
+ AsmPrinter
CodeGen
Core
+ GlobalISel
MC
SPIRVDesc
SPIRVInfo
+ SelectionDAG
Support
Target
diff --git a/llvm/lib/Target/SPIRV/SPIRV.h b/llvm/lib/Target/SPIRV/SPIRV.h
new file mode 100644
index 0000000000000..30b6995d4f702
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRV.h
@@ -0,0 +1,21 @@
+//===-- SPIRV.h - Top-level interface for SPIR-V representation -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRV_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRV_H
+
+#include "MCTargetDesc/SPIRVMCTargetDesc.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+class SPIRVTargetMachine;
+class SPIRVSubtarget;
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRV_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
new file mode 100644
index 0000000000000..64a1be2f980e0
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp
@@ -0,0 +1,137 @@
+//===-- SPIRVAsmPrinter.cpp - SPIR-V LLVM assembly writer ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to the SPIR-V assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/SPIRVInstPrinter.h"
+#include "SPIRV.h"
+#include "SPIRVInstrInfo.h"
+#include "SPIRVMCInstLower.h"
+#include "SPIRVTargetMachine.h"
+#include "TargetInfo/SPIRVTargetInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+namespace {
+class SPIRVAsmPrinter : public AsmPrinter {
+
+public:
+ explicit SPIRVAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer)
+ : AsmPrinter(TM, std::move(Streamer)) {}
+
+ StringRef getPassName() const override { return "SPIRV Assembly Printer"; }
+ void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
+
+ bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ const char *ExtraCode, raw_ostream &O) override;
+
+ void emitInstruction(const MachineInstr *MI) override;
+
+ void emitFunctionEntryLabel() override {}
+ void emitFunctionHeader() override;
+ void emitFunctionBodyStart() override {}
+ void emitBasicBlockStart(const MachineBasicBlock &MBB) override {}
+ void emitBasicBlockEnd(const MachineBasicBlock &MBB) override {}
+ void emitGlobalVariable(const GlobalVariable *GV) override {}
+};
+} // namespace
+
+void SPIRVAsmPrinter::emitFunctionHeader() {
+ const Function &F = MF->getFunction();
+
+ if (isVerbose()) {
+ OutStreamer->GetCommentOS()
+ << "-- Begin function "
+ << GlobalValue::dropLLVMManglingEscape(F.getName()) << '\n';
+ }
+
+ auto Section = getObjFileLowering().SectionForGlobal(&F, TM);
+ MF->setSection(Section);
+}
+
+void SPIRVAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
+ raw_ostream &O) {
+ const MachineOperand &MO = MI->getOperand(OpNum);
+
+ switch (MO.getType()) {
+ case MachineOperand::MO_Register:
+ O << SPIRVInstPrinter::getRegisterName(MO.getReg());
+ break;
+
+ case MachineOperand::MO_Immediate:
+ O << MO.getImm();
+ break;
+
+ case MachineOperand::MO_FPImmediate:
+ O << MO.getFPImm();
+ break;
+
+ case MachineOperand::MO_MachineBasicBlock:
+ O << *MO.getMBB()->getSymbol();
+ break;
+
+ case MachineOperand::MO_GlobalAddress:
+ O << *getSymbol(MO.getGlobal());
+ break;
+
+ case MachineOperand::MO_BlockAddress: {
+ MCSymbol *BA = GetBlockAddressSymbol(MO.getBlockAddress());
+ O << BA->getName();
+ break;
+ }
+
+ case MachineOperand::MO_ExternalSymbol:
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
+ break;
+
+ case MachineOperand::MO_JumpTableIndex:
+ case MachineOperand::MO_ConstantPoolIndex:
+ default:
+ llvm_unreachable("<unknown operand type>");
+ }
+}
+
+bool SPIRVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ const char *ExtraCode, raw_ostream &O) {
+ if (ExtraCode && ExtraCode[0])
+ return true; // Invalid instruction - SPIR-V does not have special modifiers
+
+ printOperand(MI, OpNo, O);
+ return false;
+}
+
+void SPIRVAsmPrinter::emitInstruction(const MachineInstr *MI) {
+
+ SPIRVMCInstLower MCInstLowering;
+ MCInst TmpInst;
+ MCInstLowering.lower(MI, TmpInst);
+ EmitToStreamer(*OutStreamer, TmpInst);
+}
+
+// Force static initialization.
+extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVAsmPrinter() {
+ RegisterAsmPrinter<SPIRVAsmPrinter> X(getTheSPIRV32Target());
+ RegisterAsmPrinter<SPIRVAsmPrinter> Y(getTheSPIRV64Target());
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
new file mode 100644
index 0000000000000..3f57ca0f02c75
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.cpp
@@ -0,0 +1,112 @@
+//===--- SPIRVCallLowering.cpp - Call lowering ------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the lowering of LLVM calls to machine code calls for
+// GlobalISel.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVCallLowering.h"
+#include "SPIRV.h"
+#include "SPIRVISelLowering.h"
+#include "SPIRVRegisterInfo.h"
+#include "SPIRVSubtarget.h"
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+
+using namespace llvm;
+
+SPIRVCallLowering::SPIRVCallLowering(const SPIRVTargetLowering &TLI)
+ : CallLowering(&TLI) {}
+
+bool SPIRVCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
+ const Value *Val, ArrayRef<Register> VRegs,
+ FunctionLoweringInfo &FLI,
+ Register SwiftErrorVReg) const {
+ // Currently all return types should use a single register.
+ // TODO: handle the case of multiple registers.
+ if (VRegs.size() > 1)
+ return false;
+ if (Val) {
+ MIRBuilder.buildInstr(SPIRV::OpReturnValue).addUse(VRegs[0]);
+ return true;
+ }
+ MIRBuilder.buildInstr(SPIRV::OpReturn);
+ return true;
+}
+
+bool SPIRVCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
+ const Function &F,
+ ArrayRef<ArrayRef<Register>> VRegs,
+ FunctionLoweringInfo &FLI) const {
+ auto MRI = MIRBuilder.getMRI();
+ // Assign types and names to all args, and store their types for later.
+ SmallVector<Register, 4> ArgTypeVRegs;
+ if (VRegs.size() > 0) {
+ unsigned i = 0;
+ for (const auto &Arg : F.args()) {
+ // Currently formal args should use single registers.
+ // TODO: handle the case of multiple registers.
+ if (VRegs[i].size() > 1)
+ return false;
+ ArgTypeVRegs.push_back(
+ MRI->createGenericVirtualRegister(LLT::scalar(32)));
+ ++i;
+ }
+ }
+
+ // Generate a SPIR-V type for the function.
+ Register FuncVReg = MRI->createGenericVirtualRegister(LLT::scalar(32));
+ MRI->setRegClass(FuncVReg, &SPIRV::IDRegClass);
+
+ MIRBuilder.buildInstr(SPIRV::OpFunction)
+ .addDef(FuncVReg)
+ .addUse(MRI->createGenericVirtualRegister(LLT::scalar(32)))
+ .addImm(0)
+ .addUse(MRI->createGenericVirtualRegister(LLT::scalar(32)));
+
+ // Add OpFunctionParameters.
+ const unsigned NumArgs = ArgTypeVRegs.size();
+ for (unsigned i = 0; i < NumArgs; ++i) {
+ assert(VRegs[i].size() == 1 && "Formal arg has multiple vregs");
+ MRI->setRegClass(VRegs[i][0], &SPIRV::IDRegClass);
+ MIRBuilder.buildInstr(SPIRV::OpFunctionParameter)
+ .addDef(VRegs[i][0])
+ .addUse(ArgTypeVRegs[i]);
+ }
+ return true;
+}
+
+bool SPIRVCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
+ CallLoweringInfo &Info) const {
+ // Currently call returns should have single vregs.
+ // TODO: handle the case of multiple registers.
+ if (Info.OrigRet.Regs.size() > 1)
+ return false;
+
+ Register ResVReg =
+ Info.OrigRet.Regs.empty() ? Register(0) : Info.OrigRet.Regs[0];
+ // Make sure there's a valid return reg, even for functions returning void.
+ if (!ResVReg.isValid()) {
+ ResVReg = MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::IDRegClass);
+ }
+ // Emit the OpFunctionCall and its args.
+ auto MIB = MIRBuilder.buildInstr(SPIRV::OpFunctionCall)
+ .addDef(ResVReg)
+ .addUse(MIRBuilder.getMRI()->createVirtualRegister(
+ &SPIRV::IDRegClass))
+ .add(Info.Callee);
+
+ for (const auto &Arg : Info.OrigArgs) {
+ // Currently call args should have single vregs.
+ if (Arg.Regs.size() > 1)
+ return false;
+ MIB.addUse(Arg.Regs[0]);
+ }
+ return true;
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVCallLowering.h b/llvm/lib/Target/SPIRV/SPIRVCallLowering.h
new file mode 100644
index 0000000000000..702198e3225a3
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVCallLowering.h
@@ -0,0 +1,43 @@
+//===--- SPIRVCallLowering.h - Call lowering --------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes how to lower LLVM calls to machine code calls.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVCALLLOWERING_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVCALLLOWERING_H
+
+#include "llvm/CodeGen/GlobalISel/CallLowering.h"
+
+namespace llvm {
+
+class SPIRVTargetLowering;
+
+class SPIRVCallLowering : public CallLowering {
+private:
+public:
+ SPIRVCallLowering(const SPIRVTargetLowering &TLI);
+
+ // Built OpReturn or OpReturnValue.
+ bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val,
+ ArrayRef<Register> VRegs, FunctionLoweringInfo &FLI,
+ Register SwiftErrorVReg) const override;
+
+ // Build OpFunction, OpFunctionParameter, and any EntryPoint or Linkage data.
+ bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F,
+ ArrayRef<ArrayRef<Register>> VRegs,
+ FunctionLoweringInfo &FLI) const override;
+
+ // Build OpCall, or replace with a builtin function.
+ bool lowerCall(MachineIRBuilder &MIRBuilder,
+ CallLoweringInfo &Info) const override;
+};
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVCALLLOWERING_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVFrameLowering.h b/llvm/lib/Target/SPIRV/SPIRVFrameLowering.h
new file mode 100644
index 0000000000000..b98f8d0928e5b
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVFrameLowering.h
@@ -0,0 +1,39 @@
+//===-- SPIRVFrameLowering.h - Define frame lowering 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements SPIRV-specific bits of TargetFrameLowering class.
+// The target uses only virtual registers. It does not operate with stack frame
+// explicitly and does not generate prologues/epilogues of functions.
+// As a result, we are not required to implemented the frame lowering
+// functionality substantially.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVFRAMELOWERING_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVFRAMELOWERING_H
+
+#include "llvm/CodeGen/TargetFrameLowering.h"
+#include "llvm/Support/Alignment.h"
+
+namespace llvm {
+class SPIRVSubtarget;
+
+class SPIRVFrameLowering : public TargetFrameLowering {
+public:
+ explicit SPIRVFrameLowering(const SPIRVSubtarget &sti)
+ : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(8), 0) {}
+
+ void emitPrologue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const override {}
+ void emitEpilogue(MachineFunction &MF,
+ MachineBasicBlock &MBB) const override {}
+
+ bool hasFP(const MachineFunction &MF) const override { return false; }
+};
+} // namespace llvm
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVFRAMELOWERING_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
new file mode 100644
index 0000000000000..66ff51c912b0a
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -0,0 +1,45 @@
+//===- SPIRVISelLowering.cpp - SPIR-V DAG Lowering Impl ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SPIRVTargetLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVISelLowering.h"
+#include "SPIRV.h"
+
+#define DEBUG_TYPE "spirv-lower"
+
+using namespace llvm;
+
+unsigned SPIRVTargetLowering::getNumRegistersForCallingConv(
+ LLVMContext &Context, CallingConv::ID CC, EVT VT) const {
+ // This code avoids CallLowering fail inside getVectorTypeBreakdown
+ // on v3i1 arguments. Maybe we need to return 1 for all types.
+ // TODO: remove it once this case is supported by the default implementation.
+ if (VT.isVector() && VT.getVectorNumElements() == 3 &&
+ (VT.getVectorElementType() == MVT::i1 ||
+ VT.getVectorElementType() == MVT::i8))
+ return 1;
+ return getNumRegisters(Context, VT);
+}
+
+MVT SPIRVTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context,
+ CallingConv::ID CC,
+ EVT VT) const {
+ // This code avoids CallLowering fail inside getVectorTypeBreakdown
+ // on v3i1 arguments. Maybe we need to return i32 for all types.
+ // TODO: remove it once this case is supported by the default implementation.
+ if (VT.isVector() && VT.getVectorNumElements() == 3) {
+ if (VT.getVectorElementType() == MVT::i1)
+ return MVT::v4i1;
+ else if (VT.getVectorElementType() == MVT::i8)
+ return MVT::v4i8;
+ }
+ return getRegisterType(Context, VT);
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.h b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
new file mode 100644
index 0000000000000..bee9220f52486
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.h
@@ -0,0 +1,47 @@
+//===-- SPIRVISelLowering.h - SPIR-V DAG Lowering Interface -----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that SPIR-V uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVISELLOWERING_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVISELLOWERING_H
+
+#include "llvm/CodeGen/TargetLowering.h"
+
+namespace llvm {
+class SPIRVSubtarget;
+
+class SPIRVTargetLowering : public TargetLowering {
+public:
+ explicit SPIRVTargetLowering(const TargetMachine &TM,
+ const SPIRVSubtarget &STI)
+ : TargetLowering(TM) {}
+
+ // Stop IRTranslator breaking up FMA instrs to preserve types information.
+ bool isFMAFasterThanFMulAndFAdd(const MachineFunction &MF,
+ EVT) const override {
+ return true;
+ }
+
+ // This is to prevent sexts of non-i64 vector indices which are generated
+ // within general IRTranslator hence type generation for it is omitted.
+ MVT getVectorIdxTy(const DataLayout &DL) const override {
+ return MVT::getIntegerVT(32);
+ }
+ unsigned getNumRegistersForCallingConv(LLVMContext &Context,
+ CallingConv::ID CC,
+ EVT VT) const override;
+ MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC,
+ EVT VT) const override;
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVISELLOWERING_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
new file mode 100644
index 0000000000000..7549063081148
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
@@ -0,0 +1,195 @@
+//===-- SPIRVInstrInfo.cpp - SPIR-V Instruction Information ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SPIR-V implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVInstrInfo.h"
+#include "SPIRV.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#define GET_INSTRINFO_CTOR_DTOR
+#include "SPIRVGenInstrInfo.inc"
+
+using namespace llvm;
+
+SPIRVInstrInfo::SPIRVInstrInfo() : SPIRVGenInstrInfo() {}
+
+bool SPIRVInstrInfo::isConstantInstr(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ case SPIRV::OpConstantTrue:
+ case SPIRV::OpConstantFalse:
+ case SPIRV::OpConstantI:
+ case SPIRV::OpConstantF:
+ case SPIRV::OpConstantComposite:
+ case SPIRV::OpConstantSampler:
+ case SPIRV::OpConstantNull:
+ case SPIRV::OpSpecConstantTrue:
+ case SPIRV::OpSpecConstantFalse:
+ case SPIRV::OpSpecConstant:
+ case SPIRV::OpSpecConstantComposite:
+ case SPIRV::OpSpecConstantOp:
+ case SPIRV::OpUndef:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool SPIRVInstrInfo::isTypeDeclInstr(const MachineInstr &MI) const {
+ auto &MRI = MI.getMF()->getRegInfo();
+ if (MI.getNumDefs() >= 1 && MI.getOperand(0).isReg()) {
+ auto DefRegClass = MRI.getRegClassOrNull(MI.getOperand(0).getReg());
+ return DefRegClass && DefRegClass->getID() == SPIRV::TYPERegClass.getID();
+ } else {
+ return false;
+ }
+}
+
+bool SPIRVInstrInfo::isDecorationInstr(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ case SPIRV::OpDecorate:
+ case SPIRV::OpDecorateId:
+ case SPIRV::OpDecorateString:
+ case SPIRV::OpMemberDecorate:
+ case SPIRV::OpMemberDecorateString:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool SPIRVInstrInfo::isHeaderInstr(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
+ case SPIRV::OpCapability:
+ case SPIRV::OpExtension:
+ case SPIRV::OpExtInstImport:
+ case SPIRV::OpMemoryModel:
+ case SPIRV::OpEntryPoint:
+ case SPIRV::OpExecutionMode:
+ case SPIRV::OpExecutionModeId:
+ case SPIRV::OpString:
+ case SPIRV::OpSourceExtension:
+ case SPIRV::OpSource:
+ case SPIRV::OpSourceContinued:
+ case SPIRV::OpName:
+ case SPIRV::OpMemberName:
+ case SPIRV::OpModuleProcessed:
+ return true;
+ default:
+ return isTypeDeclInstr(MI) || isConstantInstr(MI) || isDecorationInstr(MI);
+ }
+}
+
+// Analyze the branching code at the end of MBB, returning
+// true if it cannot be understood (e.g. it's a switch dispatch or isn't
+// implemented for a target). Upon success, this returns false and returns
+// with the following information in various cases:
+//
+// 1. If this block ends with no branches (it just falls through to its succ)
+// just return false, leaving TBB/FBB null.
+// 2. If this block ends with only an unconditional branch, it sets TBB to be
+// the destination block.
+// 3. If this block ends with a conditional branch and it falls through to a
+// successor block, it sets TBB to be the branch destination block and a
+// list of operands that evaluate the condition. These operands can be
+// passed to other TargetInstrInfo methods to create new branches.
+// 4. If this block ends with a conditional branch followed by an
+// unconditional branch, it returns the 'true' destination in TBB, the
+// 'false' destination in FBB, and a list of operands that evaluate the
+// condition. These operands can be passed to other TargetInstrInfo
+// methods to create new branches.
+//
+// Note that removeBranch and insertBranch must be implemented to support
+// cases where this method returns success.
+//
+// If AllowModify is true, then this routine is allowed to modify the basic
+// block (e.g. delete instructions after the unconditional branch).
+//
+// The CFG information in MBB.Predecessors and MBB.Successors must be valid
+// before calling this function.
+bool SPIRVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const {
+ TBB = nullptr;
+ FBB = nullptr;
+ if (MBB.empty())
+ return false;
+ auto MI = MBB.getLastNonDebugInstr();
+ if (!MI.isValid())
+ return false;
+ if (MI->getOpcode() == SPIRV::OpBranch) {
+ TBB = MI->getOperand(0).getMBB();
+ return false;
+ } else if (MI->getOpcode() == SPIRV::OpBranchConditional) {
+ Cond.push_back(MI->getOperand(0));
+ TBB = MI->getOperand(1).getMBB();
+ if (MI->getNumOperands() == 3) {
+ FBB = MI->getOperand(2).getMBB();
+ }
+ return false;
+ } else {
+ return true;
+ }
+}
+
+// Remove the branching code at the end of the specific MBB.
+// This is only invoked in cases where analyzeBranch returns success. It
+// returns the number of instructions that were removed.
+// If \p BytesRemoved is non-null, report the change in code size from the
+// removed instructions.
+unsigned SPIRVInstrInfo::removeBranch(MachineBasicBlock &MBB,
+ int *BytesRemoved) const {
+ report_fatal_error("Branch removal not supported, as MBB info not propagated"
+ " to OpPhi instructions. Try using -O0 instead.");
+}
+
+// Insert branch code into the end of the specified MachineBasicBlock. The
+// operands to this method are the same as those returned by analyzeBranch.
+// This is only invoked in cases where analyzeBranch returns success. It
+// returns the number of instructions inserted. If \p BytesAdded is non-null,
+// report the change in code size from the added instructions.
+//
+// It is also invoked by tail merging to add unconditional branches in
+// cases where analyzeBranch doesn't apply because there was no original
+// branch to analyze. At least this much must be implemented, else tail
+// merging needs to be disabled.
+//
+// The CFG information in MBB.Predecessors and MBB.Successors must be valid
+// before calling this function.
+unsigned SPIRVInstrInfo::insertBranch(
+ MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+ ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
+ report_fatal_error("Branch insertion not supported, as MBB info not "
+ "propagated to OpPhi instructions. Try using "
+ "-O0 instead.");
+}
+
+void SPIRVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, MCRegister DestReg,
+ MCRegister SrcReg, bool KillSrc) const {
+ // Actually we don't need this COPY instruction. However if we do nothing with
+ // it, post RA pseudo instrs expansion just removes it and we get the code
+ // with undef registers. Therefore, we need to replace all uses of dst with
+ // the src register. COPY instr itself will be safely removed later.
+ assert(I->isCopy() && "Copy instruction is expected");
+ auto DstOp = I->getOperand(0);
+ auto SrcOp = I->getOperand(1);
+ assert(DstOp.isReg() && SrcOp.isReg() &&
+ "Register operands are expected in COPY");
+ auto &MRI = I->getMF()->getRegInfo();
+ MRI.replaceRegWith(DstOp.getReg(), SrcOp.getReg());
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
new file mode 100644
index 0000000000000..2600d9cfca2e1
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
@@ -0,0 +1,54 @@
+//===-- SPIRVInstrInfo.h - SPIR-V Instruction Information -------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SPIR-V implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVINSTRINFO_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVINSTRINFO_H
+
+#include "SPIRVRegisterInfo.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+
+#define GET_INSTRINFO_HEADER
+#include "SPIRVGenInstrInfo.inc"
+
+namespace llvm {
+
+class SPIRVInstrInfo : public SPIRVGenInstrInfo {
+ const SPIRVRegisterInfo RI;
+
+public:
+ SPIRVInstrInfo();
+
+ const SPIRVRegisterInfo &getRegisterInfo() const { return RI; }
+ bool isHeaderInstr(const MachineInstr &MI) const;
+ bool isConstantInstr(const MachineInstr &MI) const;
+ bool isTypeDeclInstr(const MachineInstr &MI) const;
+ bool isDecorationInstr(const MachineInstr &MI) const;
+
+ bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify = false) const override;
+
+ unsigned removeBranch(MachineBasicBlock &MBB,
+ int *BytesRemoved = nullptr) const override;
+
+ unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
+ const DebugLoc &DL,
+ int *BytesAdded = nullptr) const override;
+ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
+ bool KillSrc) const override;
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVINSTRINFO_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp
new file mode 100644
index 0000000000000..b5a053c624d81
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.cpp
@@ -0,0 +1,44 @@
+//=- SPIRVMCInstLower.cpp - Convert SPIR-V MachineInstr to MCInst -*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to lower SPIR-V MachineInstrs to their corresponding
+// MCInst records.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVMCInstLower.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/IR/Constants.h"
+
+using namespace llvm;
+
+void SPIRVMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
+ OutMI.setOpcode(MI->getOpcode());
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ const MachineOperand &MO = MI->getOperand(i);
+
+ MCOperand MCOp;
+ switch (MO.getType()) {
+ default:
+ llvm_unreachable("unknown operand type");
+ case MachineOperand::MO_Register:
+ MCOp = MCOperand::createReg(MO.getReg());
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::createImm(MO.getImm());
+ break;
+ case MachineOperand::MO_FPImmediate:
+ MCOp = MCOperand::createDFPImm(
+ MO.getFPImm()->getValueAPF().convertToFloat());
+ break;
+ }
+
+ OutMI.addOperand(MCOp);
+ }
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVMCInstLower.h b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.h
new file mode 100644
index 0000000000000..3ea6f2a882d42
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVMCInstLower.h
@@ -0,0 +1,25 @@
+//=- SPIRVMCInstLower.h -- Convert SPIR-V MachineInstr to MCInst --*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVMCINSTLOWER_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVMCINSTLOWER_H
+
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+class MCInst;
+class MachineInstr;
+
+// This class is used to lower a MachineInstr into an MCInst.
+class LLVM_LIBRARY_VISIBILITY SPIRVMCInstLower {
+public:
+ void lower(const MachineInstr *MI, MCInst &OutMI) const;
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVMCINSTLOWER_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.cpp
new file mode 100644
index 0000000000000..9bf9d7fe5b39e
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.cpp
@@ -0,0 +1,47 @@
+//===- SPIRVRegisterBankInfo.cpp ------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the targeting of the RegisterBankInfo class for SPIR-V.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVRegisterBankInfo.h"
+#include "SPIRVRegisterInfo.h"
+#include "llvm/CodeGen/RegisterBank.h"
+
+#define GET_REGINFO_ENUM
+#include "SPIRVGenRegisterInfo.inc"
+
+#define GET_TARGET_REGBANK_IMPL
+#include "SPIRVGenRegisterBank.inc"
+
+using namespace llvm;
+
+// This required for .td selection patterns to work or we'd end up with RegClass
+// checks being redundant as all the classes would be mapped to the same bank.
+const RegisterBank &
+SPIRVRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
+ LLT Ty) const {
+ switch (RC.getID()) {
+ case SPIRV::TYPERegClassID:
+ return SPIRV::TYPERegBank;
+ case SPIRV::pIDRegClassID:
+ case SPIRV::IDRegClassID:
+ return SPIRV::IDRegBank;
+ case SPIRV::fIDRegClassID:
+ return SPIRV::fIDRegBank;
+ case SPIRV::vIDRegClassID:
+ return SPIRV::vIDRegBank;
+ case SPIRV::vfIDRegClassID:
+ return SPIRV::vfIDRegBank;
+ case SPIRV::ANYIDRegClassID:
+ case SPIRV::ANYRegClassID:
+ return SPIRV::IDRegBank;
+ }
+ llvm_unreachable("Unknown register class");
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.h b/llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.h
new file mode 100644
index 0000000000000..67ddcdefb7ddc
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVRegisterBankInfo.h
@@ -0,0 +1,38 @@
+//===- SPIRVRegisterBankInfo.h -----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the targeting of the RegisterBankInfo class for SPIR-V.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVREGISTERBANKINFO_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVREGISTERBANKINFO_H
+
+#include "llvm/CodeGen/RegisterBankInfo.h"
+
+#define GET_REGBANK_DECLARATIONS
+#include "SPIRVGenRegisterBank.inc"
+
+namespace llvm {
+
+class TargetRegisterInfo;
+
+class SPIRVGenRegisterBankInfo : public RegisterBankInfo {
+protected:
+#define GET_TARGET_REGBANK_CLASS
+#include "SPIRVGenRegisterBank.inc"
+};
+
+// This class provides the information for the target register banks.
+class SPIRVRegisterBankInfo final : public SPIRVGenRegisterBankInfo {
+public:
+ const RegisterBank &getRegBankFromRegClass(const TargetRegisterClass &RC,
+ LLT Ty) const override;
+};
+} // namespace llvm
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVREGISTERBANKINFO_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVRegisterInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVRegisterInfo.cpp
new file mode 100644
index 0000000000000..cf8a967d59c4f
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVRegisterInfo.cpp
@@ -0,0 +1,32 @@
+//===-- SPIRVRegisterInfo.cpp - SPIR-V Register Information -----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SPIR-V implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVRegisterInfo.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "llvm/CodeGen/MachineFunction.h"
+
+#define GET_REGINFO_TARGET_DESC
+#include "SPIRVGenRegisterInfo.inc"
+using namespace llvm;
+
+SPIRVRegisterInfo::SPIRVRegisterInfo() : SPIRVGenRegisterInfo(SPIRV::ID0) {}
+
+BitVector SPIRVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+ return BitVector(getNumRegs());
+}
+
+const MCPhysReg *
+SPIRVRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
+ static const MCPhysReg CalleeSavedReg = {0};
+ return &CalleeSavedReg;
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVRegisterInfo.h b/llvm/lib/Target/SPIRV/SPIRVRegisterInfo.h
new file mode 100644
index 0000000000000..f6f22b81e0bc0
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVRegisterInfo.h
@@ -0,0 +1,36 @@
+//===-- SPIRVRegisterInfo.h - SPIR-V Register Information -------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the SPIR-V implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVREGISTERINFO_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVREGISTERINFO_H
+
+#include "llvm/CodeGen/TargetRegisterInfo.h"
+
+#define GET_REGINFO_HEADER
+#include "SPIRVGenRegisterInfo.inc"
+
+namespace llvm {
+
+struct SPIRVRegisterInfo : public SPIRVGenRegisterInfo {
+ SPIRVRegisterInfo();
+ const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+ BitVector getReservedRegs(const MachineFunction &MF) const override;
+ void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj,
+ unsigned FIOperandNum,
+ RegScavenger *RS = nullptr) const override {}
+ Register getFrameRegister(const MachineFunction &MF) const override {
+ return 0;
+ }
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVREGISTERINFO_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
new file mode 100644
index 0000000000000..152af7b9c9c86
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp
@@ -0,0 +1,61 @@
+//===-- SPIRVSubtarget.cpp - SPIR-V Subtarget Information ------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the SPIR-V specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVSubtarget.h"
+#include "SPIRV.h"
+#include "SPIRVRegisterBankInfo.h"
+#include "SPIRVTargetMachine.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Host.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "spirv-subtarget"
+
+#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
+#include "SPIRVGenSubtargetInfo.inc"
+
+// Compare version numbers, but allow 0 to mean unspecified.
+static bool isAtLeastVer(uint32_t Target, uint32_t VerToCompareTo) {
+ return Target == 0 || Target >= VerToCompareTo;
+}
+
+static unsigned computePointerSize(const Triple &TT) {
+ const auto Arch = TT.getArch();
+ // TODO: unify this with pointers legalization.
+ assert(TT.isSPIRV());
+ return Arch == Triple::spirv32 ? 32 : 64;
+}
+
+SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU,
+ const std::string &FS,
+ const SPIRVTargetMachine &TM)
+ : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS),
+ PointerSize(computePointerSize(TT)), SPIRVVersion(0), InstrInfo(),
+ FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this) {
+ CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo);
+ RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>();
+}
+
+SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU,
+ StringRef FS) {
+ ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS);
+ if (SPIRVVersion == 0)
+ SPIRVVersion = 14;
+ return *this;
+}
+
+// If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual.
+bool SPIRVSubtarget::canDirectlyComparePointers() const {
+ return isAtLeastVer(SPIRVVersion, 14);
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVSubtarget.h b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
new file mode 100644
index 0000000000000..208fb11e3f95c
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
@@ -0,0 +1,82 @@
+//===-- SPIRVSubtarget.h - SPIR-V Subtarget Information --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SPIR-V specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVSUBTARGET_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVSUBTARGET_H
+
+#include "SPIRVCallLowering.h"
+#include "SPIRVFrameLowering.h"
+#include "SPIRVISelLowering.h"
+#include "SPIRVInstrInfo.h"
+#include "llvm/CodeGen/GlobalISel/CallLowering.h"
+#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define GET_SUBTARGETINFO_HEADER
+#include "SPIRVGenSubtargetInfo.inc"
+
+namespace llvm {
+class StringRef;
+
+class SPIRVTargetMachine;
+
+class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
+private:
+ const unsigned PointerSize;
+ uint32_t SPIRVVersion;
+
+ SPIRVInstrInfo InstrInfo;
+ SPIRVFrameLowering FrameLowering;
+ SPIRVTargetLowering TLInfo;
+
+ // GlobalISel related APIs.
+ std::unique_ptr<CallLowering> CallLoweringInfo;
+ std::unique_ptr<RegisterBankInfo> RegBankInfo;
+
+public:
+ // This constructor initializes the data members to match that
+ // of the specified triple.
+ SPIRVSubtarget(const Triple &TT, const std::string &CPU,
+ const std::string &FS, const SPIRVTargetMachine &TM);
+ SPIRVSubtarget &initSubtargetDependencies(StringRef CPU, StringRef FS);
+
+ // Parses features string setting specified subtarget options.
+ // The definition of this function is auto generated by tblgen.
+ void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
+ unsigned getPointerSize() const { return PointerSize; }
+ bool canDirectlyComparePointers() const;
+ uint32_t getSPIRVVersion() const { return SPIRVVersion; };
+
+ const CallLowering *getCallLowering() const override {
+ return CallLoweringInfo.get();
+ }
+ const RegisterBankInfo *getRegBankInfo() const override {
+ return RegBankInfo.get();
+ }
+ const SPIRVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
+ const SPIRVFrameLowering *getFrameLowering() const override {
+ return &FrameLowering;
+ }
+ const SPIRVTargetLowering *getTargetLowering() const override {
+ return &TLInfo;
+ }
+ const SPIRVRegisterInfo *getRegisterInfo() const override {
+ return &InstrInfo.getRegisterInfo();
+ }
+};
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVSUBTARGET_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
index baf6d68d22e41..a6ce001ff04f8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp
@@ -11,10 +11,22 @@
//===----------------------------------------------------------------------===//
#include "SPIRVTargetMachine.h"
+#include "SPIRV.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;
@@ -41,6 +53,9 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
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,
@@ -50,8 +65,13 @@ SPIRVTargetMachine::SPIRVTargetMachine(const Target &T, const Triple &TT,
: LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options,
getEffectiveRelocModel(RM),
getEffectiveCodeModel(CM, CodeModel::Small), OL),
- TLOF(std::make_unique<TargetLoweringObjectFileELF>()) {
+ TLOF(std::make_unique<TargetLoweringObjectFileELF>()),
+ Subtarget(TT, CPU.str(), FS.str(), *this) {
initAsmInfo();
+ setGlobalISel(true);
+ setFastISel(false);
+ setO0WantsFastISel(false);
+ setRequiresStructuredCFG(false);
}
namespace {
@@ -64,9 +84,78 @@ class SPIRVPassConfig : public TargetPassConfig {
SPIRVTargetMachine &getSPIRVTargetMachine() const {
return getTM<SPIRVTargetMachine>();
}
+ void addIRPasses() override;
+ void addISelPrepare() override;
+
+ bool addIRTranslator() 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() { TargetPassConfig::addISelPrepare(); }
+
+bool SPIRVPassConfig::addIRTranslator() {
+ addPass(new IRTranslator(getOptLevel()));
+ return false;
+}
+
+// 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;
+}
+
+bool SPIRVPassConfig::addGlobalInstructionSelect() {
+ addPass(new InstructionSelect(getOptLevel()));
+ return false;
+}
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.h b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.h
index 91b294d4ecebf..f3597971bc955 100644
--- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.h
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.h
@@ -13,12 +13,13 @@
#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTARGETMACHINE_H
#define LLVM_LIB_TARGET_SPIRV_SPIRVTARGETMACHINE_H
-#include "llvm/IR/DataLayout.h"
+#include "SPIRVSubtarget.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
class SPIRVTargetMachine : public LLVMTargetMachine {
std::unique_ptr<TargetLoweringObjectFile> TLOF;
+ SPIRVSubtarget Subtarget;
public:
SPIRVTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
@@ -26,7 +27,16 @@ class SPIRVTargetMachine : public LLVMTargetMachine {
Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM,
CodeGenOpt::Level OL, bool JIT);
+ const SPIRVSubtarget *getSubtargetImpl() const { return &Subtarget; }
+
+ const SPIRVSubtarget *getSubtargetImpl(const Function &) const override {
+ return &Subtarget;
+ }
+
+ TargetTransformInfo getTargetTransformInfo(const Function &F) const override;
+
TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+ bool usesPhysRegsForValues() const override { return false; }
TargetLoweringObjectFile *getObjFileLowering() const override {
return TLOF.get();
@@ -34,4 +44,4 @@ class SPIRVTargetMachine : public LLVMTargetMachine {
};
} // namespace llvm
-#endif
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVTARGETMACHINE_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetObjectFile.h b/llvm/lib/Target/SPIRV/SPIRVTargetObjectFile.h
new file mode 100644
index 0000000000000..00c456971ef10
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetObjectFile.h
@@ -0,0 +1,45 @@
+//===-- SPIRVTargetObjectFile.h - SPIRV Object Info -------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTARGETOBJECTFILE_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVTARGETOBJECTFILE_H
+
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+namespace llvm {
+
+class SPIRVTargetObjectFile : public TargetLoweringObjectFile {
+public:
+ ~SPIRVTargetObjectFile() override;
+
+ void Initialize(MCContext &ctx, const TargetMachine &TM) override {
+ TargetLoweringObjectFile::Initialize(ctx, TM);
+ }
+ // All words in a SPIR-V module (excepting the first 5 ones) are a linear
+ // sequence of instructions in a specific order. We put all the instructions
+ // in the single text section.
+ MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
+ const Constant *C,
+ Align &Alignment) const override {
+ return TextSection;
+ }
+ MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
+ const TargetMachine &TM) const override {
+ return TextSection;
+ }
+ MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
+ const TargetMachine &TM) const override {
+ return TextSection;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVTARGETOBJECTFILE_H
diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h b/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h
new file mode 100644
index 0000000000000..ac351cf42f5ca
--- /dev/null
+++ b/llvm/lib/Target/SPIRV/SPIRVTargetTransformInfo.h
@@ -0,0 +1,44 @@
+//===- SPIRVTargetTransformInfo.h - SPIR-V specific TTI ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+// \file
+// This file contains a TargetTransformInfo::Concept conforming object specific
+// to the SPIRV target machine. It uses the target's detailed information to
+// provide more precise answers to certain TTI queries, while letting the
+// target independent and default TTI implementations handle the rest.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTARGETTRANSFORMINFO_H
+#define LLVM_LIB_TARGET_SPIRV_SPIRVTARGETTRANSFORMINFO_H
+
+#include "SPIRV.h"
+#include "SPIRVTargetMachine.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
+
+namespace llvm {
+class SPIRVTTIImpl : public BasicTTIImplBase<SPIRVTTIImpl> {
+ using BaseT = BasicTTIImplBase<SPIRVTTIImpl>;
+
+ friend BaseT;
+
+ const SPIRVSubtarget *ST;
+ const SPIRVTargetLowering *TLI;
+
+ const TargetSubtargetInfo *getST() const { return ST; }
+ const SPIRVTargetLowering *getTLI() const { return TLI; }
+
+public:
+ explicit SPIRVTTIImpl(const SPIRVTargetMachine *TM, const Function &F)
+ : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl(F)),
+ TLI(ST->getTargetLowering()) {}
+};
+
+} // namespace llvm
+
+#endif // LLVM_LIB_TARGET_SPIRV_SPIRVTARGETTRANSFORMINFO_H
More information about the llvm-commits
mailing list