LLVM  15.0.0git
SPIRVUtils.cpp
Go to the documentation of this file.
1 //===--- SPIRVUtils.cpp ---- SPIR-V Utility Functions -----------*- 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 // This file contains miscellaneous utility functions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "SPIRVUtils.h"
15 #include "SPIRV.h"
16 #include "SPIRVInstrInfo.h"
17 #include "llvm/ADT/StringRef.h"
21 #include "llvm/IR/IntrinsicsSPIRV.h"
22 
23 using namespace llvm;
24 
25 // The following functions are used to add these string literals as a series of
26 // 32-bit integer operands with the correct format, and unpack them if necessary
27 // when making string comparisons in compiler passes.
28 // SPIR-V requires null-terminated UTF-8 strings padded to 32-bit alignment.
29 static uint32_t convertCharsToWord(const StringRef &Str, unsigned i) {
30  uint32_t Word = 0u; // Build up this 32-bit word from 4 8-bit chars.
31  for (unsigned WordIndex = 0; WordIndex < 4; ++WordIndex) {
32  unsigned StrIndex = i + WordIndex;
33  uint8_t CharToAdd = 0; // Initilize char as padding/null.
34  if (StrIndex < Str.size()) { // If it's within the string, get a real char.
35  CharToAdd = Str[StrIndex];
36  }
37  Word |= (CharToAdd << (WordIndex * 8));
38  }
39  return Word;
40 }
41 
42 // Get length including padding and null terminator.
43 static size_t getPaddedLen(const StringRef &Str) {
44  const size_t Len = Str.size() + 1;
45  return (Len % 4 == 0) ? Len : Len + (4 - (Len % 4));
46 }
47 
48 void addStringImm(const StringRef &Str, MachineInstrBuilder &MIB) {
49  const size_t PaddedLen = getPaddedLen(Str);
50  for (unsigned i = 0; i < PaddedLen; i += 4) {
51  // Add an operand for the 32-bits of chars or padding.
52  MIB.addImm(convertCharsToWord(Str, i));
53  }
54 }
55 
56 void addStringImm(const StringRef &Str, IRBuilder<> &B,
57  std::vector<Value *> &Args) {
58  const size_t PaddedLen = getPaddedLen(Str);
59  for (unsigned i = 0; i < PaddedLen; i += 4) {
60  // Add a vector element for the 32-bits of chars or padding.
61  Args.push_back(B.getInt32(convertCharsToWord(Str, i)));
62  }
63 }
64 
65 std::string getStringImm(const MachineInstr &MI, unsigned StartIndex) {
66  return getSPIRVStringOperand(MI, StartIndex);
67 }
68 
69 void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB) {
70  const auto Bitwidth = Imm.getBitWidth();
71  switch (Bitwidth) {
72  case 1:
73  break; // Already handled.
74  case 8:
75  case 16:
76  case 32:
77  MIB.addImm(Imm.getZExtValue());
78  break;
79  case 64: {
80  uint64_t FullImm = Imm.getZExtValue();
81  uint32_t LowBits = FullImm & 0xffffffff;
82  uint32_t HighBits = (FullImm >> 32) & 0xffffffff;
83  MIB.addImm(LowBits).addImm(HighBits);
84  break;
85  }
86  default:
87  report_fatal_error("Unsupported constant bitwidth");
88  }
89 }
90 
92  MachineIRBuilder &MIRBuilder) {
93  if (!Name.empty()) {
94  auto MIB = MIRBuilder.buildInstr(SPIRV::OpName).addUse(Target);
95  addStringImm(Name, MIB);
96  }
97 }
98 
100  const std::vector<uint32_t> &DecArgs,
101  StringRef StrImm) {
102  if (!StrImm.empty())
103  addStringImm(StrImm, MIB);
104  for (const auto &DecArg : DecArgs)
105  MIB.addImm(DecArg);
106 }
107 
110  const std::vector<uint32_t> &DecArgs, StringRef StrImm) {
111  auto MIB = MIRBuilder.buildInstr(SPIRV::OpDecorate)
112  .addUse(Reg)
113  .addImm(static_cast<uint32_t>(Dec));
114  finishBuildOpDecorate(MIB, DecArgs, StrImm);
115 }
116 
119  const std::vector<uint32_t> &DecArgs, StringRef StrImm) {
120  MachineBasicBlock &MBB = *I.getParent();
121  auto MIB = BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpDecorate))
122  .addUse(Reg)
123  .addImm(static_cast<uint32_t>(Dec));
124  finishBuildOpDecorate(MIB, DecArgs, StrImm);
125 }
126 
127 // TODO: maybe the following two functions should be handled in the subtarget
128 // to allow for different OpenCL vs Vulkan handling.
130  switch (SC) {
132  return 0;
134  return 1;
136  return 2;
138  return 3;
140  return 4;
142  return 7;
143  default:
144  llvm_unreachable("Unable to get address space id");
145  }
146 }
147 
149  switch (AddrSpace) {
150  case 0:
152  case 1:
154  case 2:
156  case 3:
158  case 4:
160  case 7:
162  default:
163  llvm_unreachable("Unknown address space");
164  }
165 }
166 
168  switch (SC) {
180  default:
182  }
183 }
184 
186  const MachineRegisterInfo *MRI) {
187  MachineInstr *ConstInstr = MRI->getVRegDef(ConstReg);
188  if (ConstInstr->getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
189  ConstInstr->getIntrinsicID() == Intrinsic::spv_track_constant) {
190  ConstReg = ConstInstr->getOperand(2).getReg();
191  ConstInstr = MRI->getVRegDef(ConstReg);
192  } else if (ConstInstr->getOpcode() == SPIRV::ASSIGN_TYPE) {
193  ConstReg = ConstInstr->getOperand(1).getReg();
194  ConstInstr = MRI->getVRegDef(ConstReg);
195  }
196  return ConstInstr;
197 }
198 
200  const MachineInstr *MI = getDefInstrMaybeConstant(ConstReg, MRI);
201  assert(MI && MI->getOpcode() == TargetOpcode::G_CONSTANT);
202  return MI->getOperand(1).getCImm()->getValue().getZExtValue();
203 }
204 
205 Type *getMDOperandAsType(const MDNode *N, unsigned I) {
206  return cast<ValueAsMetadata>(N->getOperand(I))->getType();
207 }
i
i
Definition: README.txt:29
convertCharsToWord
static uint32_t convertCharsToWord(const StringRef &Str, unsigned i)
Definition: SPIRVUtils.cpp:29
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:104
MachineInstr.h
llvm::MachineInstrBuilder::addImm
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Definition: MachineInstrBuilder.h:131
llvm::SPIRV::StorageClass::Input
@ Input
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MachineRegisterInfo
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Definition: MachineRegisterInfo.h:50
llvm::SPIRV::StorageClass::Workgroup
@ Workgroup
StringRef.h
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:145
llvm::SPIRV::StorageClass::Image
@ Image
llvm::SPIRV::StorageClass::Uniform
@ Uniform
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::IRBuilder<>
llvm::SPIRV::Decoration
Decoration
Definition: SPIRVBaseInfo.h:456
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::SPIRV::MemorySemantics::ImageMemory
@ ImageMemory
llvm::SPIRV::MemorySemantics::WorkgroupMemory
@ WorkgroupMemory
MachineIRBuilder.h
llvm::SPIRV::MemorySemantics::CrossWorkgroupMemory
@ CrossWorkgroupMemory
getDefInstrMaybeConstant
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:185
llvm::PPCISD::SC
@ SC
CHAIN = SC CHAIN, Imm128 - System call.
Definition: PPCISelLowering.h:418
llvm::SPIRV::StorageClass::Generic
@ Generic
SPIRVBaseInfo.h
llvm::MachineInstr::getOperand
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:501
TII
const HexagonInstrInfo * TII
Definition: HexagonCopyToCombine.cpp:125
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
SPIRVUtils.h
llvm::MachineInstr::getIntrinsicID
unsigned getIntrinsicID() const
Returns the Intrinsic::ID for this instruction.
Definition: MachineInstr.h:1824
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
llvm::MachineRegisterInfo::getVRegDef
MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Definition: MachineRegisterInfo.cpp:396
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
addStringImm
void addStringImm(const StringRef &Str, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:48
getMemSemanticsForStorageClass
SPIRV::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass SC)
Definition: SPIRVUtils.cpp:167
llvm::SPIRV::MemorySemantics
MemorySemantics
Definition: SPIRVBaseInfo.h:647
SPIRVInstrInfo.h
addressSpaceToStorageClass
SPIRV::StorageClass addressSpaceToStorageClass(unsigned AddrSpace)
Definition: SPIRVUtils.cpp:148
finishBuildOpDecorate
static void finishBuildOpDecorate(MachineInstrBuilder &MIB, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:99
llvm::MachineIRBuilder
Helper class to build MachineInstr.
Definition: MachineIRBuilder.h:219
llvm::StringRef::empty
constexpr LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:153
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
llvm::MachineInstrBuilder
Definition: MachineInstrBuilder.h:69
llvm::SPIRV::StorageClass
StorageClass
Definition: SPIRVBaseInfo.h:255
uint64_t
storageClassToAddressSpace
unsigned storageClassToAddressSpace(SPIRV::StorageClass SC)
Definition: SPIRVUtils.cpp:129
I
#define I(x, y, z)
Definition: MD5.cpp:58
addNumImm
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:69
SPIRV.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::SPIRV::MemorySemantics::None
@ None
getSPIRVStringOperand
std::string getSPIRVStringOperand(const InstType &MI, unsigned StartIndex)
Definition: SPIRVBaseInfo.h:715
buildOpDecorate
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, llvm::SPIRV::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:108
llvm::MachineInstrBuilder::addUse
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
Definition: MachineInstrBuilder.h:123
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:359
llvm::MDNode
Metadata node.
Definition: Metadata.h:944
llvm::irsymtab::storage::Word
support::ulittle32_t Word
Definition: IRSymtab.h:52
llvm::APInt
Class for arbitrary precision integers.
Definition: APInt.h:75
llvm::MachineIRBuilder::buildInstr
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
Definition: MachineIRBuilder.h:374
llvm::SPIRVInstrInfo
Definition: SPIRVInstrInfo.h:24
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MachineInstr::getOpcode
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:491
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::SPIRV::StorageClass::StorageBuffer
@ StorageBuffer
uint32_t
buildOpName
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
Definition: SPIRVUtils.cpp:91
MRI
unsigned const MachineRegisterInfo * MRI
Definition: AArch64AdvSIMDScalarPass.cpp:105
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::SPIRV::MemorySemantics::AtomicCounterMemory
@ AtomicCounterMemory
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
getPaddedLen
static size_t getPaddedLen(const StringRef &Str)
Definition: SPIRVUtils.cpp:43
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::SPIRV::StorageClass::UniformConstant
@ UniformConstant
getStringImm
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
Definition: SPIRVUtils.cpp:65
llvm::RISCVMatInt::Imm
@ Imm
Definition: RISCVMatInt.h:23
llvm::SPIRV::MemorySemantics::UniformMemory
@ UniformMemory
MachineInstrBuilder.h
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:328
N
#define N
llvm::SPIRV::StorageClass::Function
@ Function
llvm::SPIRV::StorageClass::AtomicCounter
@ AtomicCounter
getIConstVal
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:199
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:394
llvm::SPIRV::StorageClass::CrossWorkgroup
@ CrossWorkgroup
getMDOperandAsType
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition: SPIRVUtils.cpp:205