blob: f906aaa3da2e319b56a61db715f0aaefa954171d [file] [log] [blame]
David Neto22f144c2017-06-12 14:26:21 -04001// Copyright 2017 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifdef _MSC_VER
16#pragma warning(push, 0)
17#endif
18
David Neto156783e2017-07-05 15:39:41 -040019#include <cassert>
David Neto22f144c2017-06-12 14:26:21 -040020#include <clspv/Passes.h>
21
22#include <llvm/ADT/StringSwitch.h>
23#include <llvm/ADT/UniqueVector.h>
24#include <llvm/Analysis/LoopInfo.h>
25#include <llvm/IR/Constants.h>
26#include <llvm/IR/Dominators.h>
27#include <llvm/IR/Instructions.h>
28#include <llvm/IR/Metadata.h>
29#include <llvm/IR/Module.h>
30#include <llvm/Pass.h>
31#include <llvm/Support/raw_ostream.h>
32#include <llvm/Transforms/Utils/Cloning.h>
33
34#include <spirv/1.0/spirv.hpp>
35#include <clspv/AddressSpace.h>
36#include <clspv/spirv_c_strings.hpp>
37#include <clspv/spirv_glsl.hpp>
38
39#include <list>
David Neto0676e6f2017-07-11 18:47:44 -040040#include <iomanip>
41#include <sstream>
David Neto44795152017-07-13 15:45:28 -040042#include <utility>
David Neto22f144c2017-06-12 14:26:21 -040043
44#if defined(_MSC_VER)
45#pragma warning(pop)
46#endif
47
48using namespace llvm;
49using namespace clspv;
David Neto156783e2017-07-05 15:39:41 -040050using namespace mdconst;
David Neto22f144c2017-06-12 14:26:21 -040051
52namespace {
53enum SPIRVOperandType {
54 NUMBERID,
55 LITERAL_INTEGER,
56 LITERAL_STRING,
57 LITERAL_FLOAT
58};
59
60struct SPIRVOperand {
61 explicit SPIRVOperand(SPIRVOperandType Ty, uint32_t Num)
62 : Type(Ty), LiteralNum(1, Num) {}
63 explicit SPIRVOperand(SPIRVOperandType Ty, const char *Str)
64 : Type(Ty), LiteralStr(Str) {}
65 explicit SPIRVOperand(SPIRVOperandType Ty, StringRef Str)
66 : Type(Ty), LiteralStr(Str) {}
67 explicit SPIRVOperand(SPIRVOperandType Ty, ArrayRef<uint32_t> NumVec)
68 : Type(Ty), LiteralNum(NumVec.begin(), NumVec.end()) {}
69
70 SPIRVOperandType getType() { return Type; };
71 uint32_t getNumID() { return LiteralNum[0]; };
72 std::string getLiteralStr() { return LiteralStr; };
73 ArrayRef<uint32_t> getLiteralNum() { return LiteralNum; };
74
75private:
76 SPIRVOperandType Type;
77 std::string LiteralStr;
78 SmallVector<uint32_t, 4> LiteralNum;
79};
80
81struct SPIRVInstruction {
82 explicit SPIRVInstruction(uint16_t WCount, spv::Op Opc, uint32_t ResID,
83 ArrayRef<SPIRVOperand *> Ops)
84 : WordCount(WCount), Opcode(static_cast<uint16_t>(Opc)), ResultID(ResID),
85 Operands(Ops.begin(), Ops.end()) {}
86
87 uint16_t getWordCount() const { return WordCount; }
88 uint16_t getOpcode() const { return Opcode; }
89 uint32_t getResultID() const { return ResultID; }
90 ArrayRef<SPIRVOperand *> getOperands() const { return Operands; }
91
92private:
93 uint16_t WordCount;
94 uint16_t Opcode;
95 uint32_t ResultID;
96 SmallVector<SPIRVOperand *, 4> Operands;
97};
98
99struct SPIRVProducerPass final : public ModulePass {
100 typedef std::vector<SPIRVOperand *> SPIRVOperandList;
101 typedef DenseMap<Type *, uint32_t> TypeMapType;
102 typedef UniqueVector<Type *> TypeList;
103 typedef DenseMap<Value *, uint32_t> ValueMapType;
104 typedef std::vector<Value *> ValueList;
105 typedef std::vector<std::pair<Value *, uint32_t>> EntryPointVecType;
106 typedef std::list<SPIRVInstruction *> SPIRVInstructionList;
107 typedef std::vector<
108 std::tuple<Value *, SPIRVInstructionList::iterator, uint32_t>>
109 DeferredInstVecType;
110 typedef DenseMap<FunctionType *, std::pair<FunctionType *, uint32_t>>
111 GlobalConstFuncMapType;
112
David Neto44795152017-07-13 15:45:28 -0400113 explicit SPIRVProducerPass(
114 raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
115 ArrayRef<std::pair<unsigned, std::string>> samplerMap, bool outputAsm,
116 bool outputCInitList)
David Netoc2c368d2017-06-30 16:50:17 -0400117 : ModulePass(ID), samplerMap(samplerMap), out(out),
David Neto0676e6f2017-07-11 18:47:44 -0400118 binaryTempOut(binaryTempUnderlyingVector), binaryOut(&out),
David Netoc2c368d2017-06-30 16:50:17 -0400119 descriptorMapOut(descriptor_map_out), outputAsm(outputAsm),
David Neto0676e6f2017-07-11 18:47:44 -0400120 outputCInitList(outputCInitList), patchBoundOffset(0), nextID(1),
121 OpExtInstImportID(0), HasVariablePointers(false), SamplerTy(nullptr) {}
David Neto22f144c2017-06-12 14:26:21 -0400122
123 void getAnalysisUsage(AnalysisUsage &AU) const override {
124 AU.addRequired<DominatorTreeWrapperPass>();
125 AU.addRequired<LoopInfoWrapperPass>();
126 }
127
128 virtual bool runOnModule(Module &module) override;
129
130 // output the SPIR-V header block
131 void outputHeader();
132
133 // patch the SPIR-V header block
134 void patchHeader();
135
136 uint32_t lookupType(Type *Ty) {
137 if (Ty->isPointerTy() &&
138 (Ty->getPointerAddressSpace() != AddressSpace::UniformConstant)) {
139 auto PointeeTy = Ty->getPointerElementType();
140 if (PointeeTy->isStructTy() &&
141 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
142 Ty = PointeeTy;
143 }
144 }
145
146 if (0 == TypeMap.count(Ty)) {
147 Ty->print(errs());
148 llvm_unreachable("Unhandled type!");
149 }
150
151 return TypeMap[Ty];
152 }
153 TypeMapType &getImageTypeMap() { return ImageTypeMap; }
154 TypeList &getTypeList() { return Types; };
155 ValueList &getConstantList() { return Constants; };
156 ValueMapType &getValueMap() { return ValueMap; }
157 ValueMapType &getAllocatedValueMap() { return AllocatedValueMap; }
158 SPIRVInstructionList &getSPIRVInstList() { return SPIRVInsts; };
159 ValueToValueMapTy &getArgumentGVMap() { return ArgumentGVMap; };
160 ValueMapType &getArgumentGVIDMap() { return ArgumentGVIDMap; };
161 EntryPointVecType &getEntryPointVec() { return EntryPointVec; };
162 DeferredInstVecType &getDeferredInstVec() { return DeferredInstVec; };
163 ValueList &getEntryPointInterfacesVec() { return EntryPointInterfacesVec; };
164 uint32_t &getOpExtInstImportID() { return OpExtInstImportID; };
165 std::vector<uint32_t> &getBuiltinDimVec() { return BuiltinDimensionVec; };
166 bool hasVariablePointers() { return true; /* We use StorageBuffer everywhere */ };
167 void setVariablePointers(bool Val) { HasVariablePointers = Val; };
David Neto44795152017-07-13 15:45:28 -0400168 ArrayRef<std::pair<unsigned, std::string>> &getSamplerMap() { return samplerMap; }
David Neto22f144c2017-06-12 14:26:21 -0400169 GlobalConstFuncMapType &getGlobalConstFuncTypeMap() {
170 return GlobalConstFuncTypeMap;
171 }
172 SmallPtrSet<Value *, 16> &getGlobalConstArgSet() {
173 return GlobalConstArgumentSet;
174 }
David Neto1a1a0582017-07-07 12:01:44 -0400175 TypeList &getPointerTypesNeedingArrayStride() {
176 return PointerTypesNeedingArrayStride;
177 }
David Neto22f144c2017-06-12 14:26:21 -0400178
179 void GenerateLLVMIRInfo(Module &M);
180 bool FindExtInst(Module &M);
181 void FindTypePerGlobalVar(GlobalVariable &GV);
182 void FindTypePerFunc(Function &F);
David Neto19a1bad2017-08-25 15:01:41 -0400183 // Inserts |Ty| and relevant sub-types into the |Types| member, indicating that
184 // |Ty| and its subtypes will need a corresponding SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400185 void FindType(Type *Ty);
186 void FindConstantPerGlobalVar(GlobalVariable &GV);
187 void FindConstantPerFunc(Function &F);
188 void FindConstant(Value *V);
189 void GenerateExtInstImport();
David Neto19a1bad2017-08-25 15:01:41 -0400190 // Generates instructions for SPIR-V types corresponding to the LLVM types
191 // saved in the |Types| member. A type follows its subtypes. IDs are
192 // allocated sequentially starting with the current value of nextID, and
193 // with a type following its subtypes. Also updates nextID to just beyond
194 // the last generated ID.
David Neto22f144c2017-06-12 14:26:21 -0400195 void GenerateSPIRVTypes(const DataLayout &DL);
196 void GenerateSPIRVConstants();
197 void GenerateModuleInfo();
198 void GenerateGlobalVar(GlobalVariable &GV);
199 void GenerateSamplers(Module &M);
200 void GenerateFuncPrologue(Function &F);
201 void GenerateFuncBody(Function &F);
202 void GenerateInstForArg(Function &F);
203 spv::Op GetSPIRVCmpOpcode(CmpInst *CmpI);
204 spv::Op GetSPIRVCastOpcode(Instruction &I);
205 spv::Op GetSPIRVBinaryOpcode(Instruction &I);
206 void GenerateInstruction(Instruction &I);
207 void GenerateFuncEpilogue();
208 void HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400209 void HandleDeferredDecorations(const DataLayout& DL);
David Neto22f144c2017-06-12 14:26:21 -0400210 bool is4xi8vec(Type *Ty) const;
211 spv::StorageClass GetStorageClass(unsigned AddrSpace) const;
212 spv::BuiltIn GetBuiltin(StringRef globalVarName) const;
213 glsl::ExtInst getExtInstEnum(StringRef Name);
214 void PrintResID(SPIRVInstruction *Inst);
215 void PrintOpcode(SPIRVInstruction *Inst);
216 void PrintOperand(SPIRVOperand *Op);
217 void PrintCapability(SPIRVOperand *Op);
218 void PrintExtInst(SPIRVOperand *Op);
219 void PrintAddrModel(SPIRVOperand *Op);
220 void PrintMemModel(SPIRVOperand *Op);
221 void PrintExecModel(SPIRVOperand *Op);
222 void PrintExecMode(SPIRVOperand *Op);
223 void PrintSourceLanguage(SPIRVOperand *Op);
224 void PrintFuncCtrl(SPIRVOperand *Op);
225 void PrintStorageClass(SPIRVOperand *Op);
226 void PrintDecoration(SPIRVOperand *Op);
227 void PrintBuiltIn(SPIRVOperand *Op);
228 void PrintSelectionControl(SPIRVOperand *Op);
229 void PrintLoopControl(SPIRVOperand *Op);
230 void PrintDimensionality(SPIRVOperand *Op);
231 void PrintImageFormat(SPIRVOperand *Op);
232 void PrintMemoryAccess(SPIRVOperand *Op);
233 void PrintImageOperandsType(SPIRVOperand *Op);
234 void WriteSPIRVAssembly();
235 void WriteOneWord(uint32_t Word);
236 void WriteResultID(SPIRVInstruction *Inst);
237 void WriteWordCountAndOpcode(SPIRVInstruction *Inst);
238 void WriteOperand(SPIRVOperand *Op);
239 void WriteSPIRVBinary();
240
241private:
242 static char ID;
David Neto44795152017-07-13 15:45:28 -0400243 ArrayRef<std::pair<unsigned, std::string>> samplerMap;
David Neto22f144c2017-06-12 14:26:21 -0400244 raw_pwrite_stream &out;
David Neto0676e6f2017-07-11 18:47:44 -0400245
246 // TODO(dneto): Wouldn't it be better to always just emit a binary, and then
247 // convert to other formats on demand?
248
249 // When emitting a C initialization list, the WriteSPIRVBinary method
250 // will actually write its words to this vector via binaryTempOut.
251 SmallVector<char, 100> binaryTempUnderlyingVector;
252 raw_svector_ostream binaryTempOut;
253
254 // Binary output writes to this stream, which might be |out| or
255 // |binaryTempOut|. It's the latter when we really want to write a C
256 // initializer list.
257 raw_pwrite_stream* binaryOut;
David Netoc2c368d2017-06-30 16:50:17 -0400258 raw_ostream &descriptorMapOut;
David Neto22f144c2017-06-12 14:26:21 -0400259 const bool outputAsm;
David Neto0676e6f2017-07-11 18:47:44 -0400260 const bool outputCInitList; // If true, output look like {0x7023, ... , 5}
David Neto22f144c2017-06-12 14:26:21 -0400261 uint64_t patchBoundOffset;
262 uint32_t nextID;
263
David Neto19a1bad2017-08-25 15:01:41 -0400264 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400265 TypeMapType TypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400266 // Maps an LLVM image type to its SPIR-V ID.
David Neto22f144c2017-06-12 14:26:21 -0400267 TypeMapType ImageTypeMap;
David Neto19a1bad2017-08-25 15:01:41 -0400268 // A unique-vector of LLVM types that map to a SPIR-V type.
David Neto22f144c2017-06-12 14:26:21 -0400269 TypeList Types;
270 ValueList Constants;
David Neto19a1bad2017-08-25 15:01:41 -0400271 // Maps an LLVM Value pointer to the corresponding SPIR-V Id.
David Neto22f144c2017-06-12 14:26:21 -0400272 ValueMapType ValueMap;
273 ValueMapType AllocatedValueMap;
274 SPIRVInstructionList SPIRVInsts;
275 ValueToValueMapTy ArgumentGVMap;
276 ValueMapType ArgumentGVIDMap;
277 EntryPointVecType EntryPointVec;
278 DeferredInstVecType DeferredInstVec;
279 ValueList EntryPointInterfacesVec;
280 uint32_t OpExtInstImportID;
281 std::vector<uint32_t> BuiltinDimensionVec;
282 bool HasVariablePointers;
283 Type *SamplerTy;
284 GlobalConstFuncMapType GlobalConstFuncTypeMap;
285 SmallPtrSet<Value *, 16> GlobalConstArgumentSet;
David Neto1a1a0582017-07-07 12:01:44 -0400286 // An ordered set of pointer types of Base arguments to OpPtrAccessChain,
287 // and which point into transparent memory (StorageBuffer storage class).
288 // These will require an ArrayStride decoration.
289 // See SPV_KHR_variable_pointers rev 13.
290 TypeList PointerTypesNeedingArrayStride;
David Neto22f144c2017-06-12 14:26:21 -0400291};
292
293char SPIRVProducerPass::ID;
294}
295
296namespace clspv {
David Neto44795152017-07-13 15:45:28 -0400297ModulePass *
298createSPIRVProducerPass(raw_pwrite_stream &out, raw_ostream &descriptor_map_out,
299 ArrayRef<std::pair<unsigned, std::string>> samplerMap,
300 bool outputAsm, bool outputCInitList) {
301 return new SPIRVProducerPass(out, descriptor_map_out, samplerMap, outputAsm,
302 outputCInitList);
David Neto22f144c2017-06-12 14:26:21 -0400303}
David Netoc2c368d2017-06-30 16:50:17 -0400304} // namespace clspv
David Neto22f144c2017-06-12 14:26:21 -0400305
306bool SPIRVProducerPass::runOnModule(Module &module) {
David Neto0676e6f2017-07-11 18:47:44 -0400307 binaryOut = outputCInitList ? &binaryTempOut : &out;
308
David Neto22f144c2017-06-12 14:26:21 -0400309 // SPIR-V always begins with its header information
310 outputHeader();
311
312 // Gather information from the LLVM IR that we require.
313 GenerateLLVMIRInfo(module);
314
315 // If we are using a sampler map, find the type of the sampler.
316 if (0 < getSamplerMap().size()) {
317 auto SamplerStructTy = module.getTypeByName("opencl.sampler_t");
318 if (!SamplerStructTy) {
319 SamplerStructTy =
320 StructType::create(module.getContext(), "opencl.sampler_t");
321 }
322
323 SamplerTy = SamplerStructTy->getPointerTo(AddressSpace::UniformConstant);
324
325 FindType(SamplerTy);
326 }
327
328 // Collect information on global variables too.
329 for (GlobalVariable &GV : module.globals()) {
330 // If the GV is one of our special __spirv_* variables, remove the
331 // initializer as it was only placed there to force LLVM to not throw the
332 // value away.
333 if (GV.getName().startswith("__spirv_")) {
334 GV.setInitializer(nullptr);
335 }
336
337 // Collect types' information from global variable.
338 FindTypePerGlobalVar(GV);
339
340 // Collect constant information from global variable.
341 FindConstantPerGlobalVar(GV);
342
343 // If the variable is an input, entry points need to know about it.
344 if (AddressSpace::Input == GV.getType()->getPointerAddressSpace()) {
345 getEntryPointInterfacesVec().push_back(&GV);
346 }
347 }
348
349 // If there are extended instructions, generate OpExtInstImport.
350 if (FindExtInst(module)) {
351 GenerateExtInstImport();
352 }
353
354 // Generate SPIRV instructions for types.
355 const DataLayout &DL = module.getDataLayout();
356 GenerateSPIRVTypes(DL);
357
358 // Generate SPIRV constants.
359 GenerateSPIRVConstants();
360
361 // If we have a sampler map, we might have literal samplers to generate.
362 if (0 < getSamplerMap().size()) {
363 GenerateSamplers(module);
364 }
365
366 // Generate SPIRV variables.
367 for (GlobalVariable &GV : module.globals()) {
368 GenerateGlobalVar(GV);
369 }
370
371 // Generate SPIRV instructions for each function.
372 for (Function &F : module) {
373 if (F.isDeclaration()) {
374 continue;
375 }
376
377 // Generate Function Prologue.
378 GenerateFuncPrologue(F);
379
380 // Generate SPIRV instructions for function body.
381 GenerateFuncBody(F);
382
383 // Generate Function Epilogue.
384 GenerateFuncEpilogue();
385 }
386
387 HandleDeferredInstruction();
David Neto1a1a0582017-07-07 12:01:44 -0400388 HandleDeferredDecorations(DL);
David Neto22f144c2017-06-12 14:26:21 -0400389
390 // Generate SPIRV module information.
391 GenerateModuleInfo();
392
393 if (outputAsm) {
394 WriteSPIRVAssembly();
395 } else {
396 WriteSPIRVBinary();
397 }
398
399 // We need to patch the SPIR-V header to set bound correctly.
400 patchHeader();
David Neto0676e6f2017-07-11 18:47:44 -0400401
402 if (outputCInitList) {
403 bool first = true;
David Neto0676e6f2017-07-11 18:47:44 -0400404 std::ostringstream os;
405
David Neto57fb0b92017-08-04 15:35:09 -0400406 auto emit_word = [&os, &first](uint32_t word) {
David Neto0676e6f2017-07-11 18:47:44 -0400407 if (!first)
David Neto57fb0b92017-08-04 15:35:09 -0400408 os << ",\n";
409 os << word;
David Neto0676e6f2017-07-11 18:47:44 -0400410 first = false;
411 };
412
413 os << "{";
David Neto57fb0b92017-08-04 15:35:09 -0400414 const std::string str(binaryTempOut.str());
415 for (unsigned i = 0; i < str.size(); i += 4) {
416 const uint32_t a = static_cast<unsigned char>(str[i]);
417 const uint32_t b = static_cast<unsigned char>(str[i + 1]);
418 const uint32_t c = static_cast<unsigned char>(str[i + 2]);
419 const uint32_t d = static_cast<unsigned char>(str[i + 3]);
420 emit_word(a | (b << 8) | (c << 16) | (d << 24));
David Neto0676e6f2017-07-11 18:47:44 -0400421 }
422 os << "}\n";
423 out << os.str();
424 }
425
David Neto22f144c2017-06-12 14:26:21 -0400426 return false;
427}
428
429void SPIRVProducerPass::outputHeader() {
430 if (outputAsm) {
431 // for ASM output the header goes into 5 comments at the beginning of the
432 // file
433 out << "; SPIR-V\n";
434
435 // the major version number is in the 2nd highest byte
436 const uint32_t major = (spv::Version >> 16) & 0xFF;
437
438 // the minor version number is in the 2nd lowest byte
439 const uint32_t minor = (spv::Version >> 8) & 0xFF;
440 out << "; Version: " << major << "." << minor << "\n";
441
442 // use Codeplay's vendor ID
443 out << "; Generator: Codeplay; 0\n";
444
445 out << "; Bound: ";
446
447 // we record where we need to come back to and patch in the bound value
448 patchBoundOffset = out.tell();
449
450 // output one space per digit for the max size of a 32 bit unsigned integer
451 // (which is the maximum ID we could possibly be using)
452 for (uint32_t i = std::numeric_limits<uint32_t>::max(); 0 != i; i /= 10) {
453 out << " ";
454 }
455
456 out << "\n";
457
458 out << "; Schema: 0\n";
459 } else {
David Neto0676e6f2017-07-11 18:47:44 -0400460 binaryOut->write(reinterpret_cast<const char *>(&spv::MagicNumber),
David Neto22f144c2017-06-12 14:26:21 -0400461 sizeof(spv::MagicNumber));
David Neto0676e6f2017-07-11 18:47:44 -0400462 binaryOut->write(reinterpret_cast<const char *>(&spv::Version),
David Neto22f144c2017-06-12 14:26:21 -0400463 sizeof(spv::Version));
464
465 // use Codeplay's vendor ID
466 const uint32_t vendor = 3 << 16;
David Neto0676e6f2017-07-11 18:47:44 -0400467 binaryOut->write(reinterpret_cast<const char *>(&vendor), sizeof(vendor));
David Neto22f144c2017-06-12 14:26:21 -0400468
469 // we record where we need to come back to and patch in the bound value
David Neto0676e6f2017-07-11 18:47:44 -0400470 patchBoundOffset = binaryOut->tell();
David Neto22f144c2017-06-12 14:26:21 -0400471
472 // output a bad bound for now
David Neto0676e6f2017-07-11 18:47:44 -0400473 binaryOut->write(reinterpret_cast<const char *>(&nextID), sizeof(nextID));
David Neto22f144c2017-06-12 14:26:21 -0400474
475 // output the schema (reserved for use and must be 0)
476 const uint32_t schema = 0;
David Neto0676e6f2017-07-11 18:47:44 -0400477 binaryOut->write(reinterpret_cast<const char *>(&schema), sizeof(schema));
David Neto22f144c2017-06-12 14:26:21 -0400478 }
479}
480
481void SPIRVProducerPass::patchHeader() {
482 if (outputAsm) {
483 // get the string representation of the max bound used (nextID will be the
484 // max ID used)
485 auto asString = std::to_string(nextID);
486 out.pwrite(asString.c_str(), asString.size(), patchBoundOffset);
487 } else {
488 // for a binary we just write the value of nextID over bound
David Neto0676e6f2017-07-11 18:47:44 -0400489 binaryOut->pwrite(reinterpret_cast<char *>(&nextID), sizeof(nextID),
490 patchBoundOffset);
David Neto22f144c2017-06-12 14:26:21 -0400491 }
492}
493
494void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M) {
495 // This function generates LLVM IR for function such as global variable for
496 // argument, constant and pointer type for argument access. These information
497 // is artificial one because we need Vulkan SPIR-V output. This function is
498 // executed ahead of FindType and FindConstant.
499 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
500 LLVMContext &Context = M.getContext();
501
502 // Map for avoiding to generate struct type with same fields.
503 DenseMap<Type *, Type *> ArgTyMap;
504
505 // Collect global constant variables.
506 SmallVector<GlobalVariable *, 8> GVList;
507 for (GlobalVariable &GV : M.globals()) {
508 if (GV.getType()->getAddressSpace() == AddressSpace::Constant) {
509 GVList.push_back(&GV);
510 }
511 }
512
513 // Change global constant variable's address space to ModuleScopePrivate.
514 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
515 for (auto GV : GVList) {
516 // If there is no user of gv, delete gv.
517 if (GV->use_empty()) {
518 GV->eraseFromParent();
519 continue;
520 }
521
522 // Create new gv with ModuleScopePrivate address space.
523 Type *NewGVTy = GV->getType()->getPointerElementType();
524 GlobalVariable *NewGV = new GlobalVariable(
525 M, NewGVTy, false, GV->getLinkage(), GV->getInitializer(), "", nullptr,
526 GV->getThreadLocalMode(), AddressSpace::ModuleScopePrivate);
527 NewGV->takeName(GV);
528
529 const SmallVector<User *, 8> GVUsers(GV->user_begin(), GV->user_end());
530 SmallVector<User*, 8> CandidateUsers;
531
532 for (User *GVU : GVUsers) {
533 if (CallInst *Call = dyn_cast<CallInst>(GVU)) {
534 // Find argument index.
535 unsigned GVCstArgIdx = 0;
536 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
537 if (GV == Call->getOperand(i)) {
538 GVCstArgIdx = i;
539 }
540 }
541
542 // Record function with global constant.
543 GlobalConstFuncTyMap[Call->getFunctionType()] =
544 std::make_pair(Call->getFunctionType(), GVCstArgIdx);
545 } else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(GVU)) {
546 // Check GEP users.
547 for (User *GEPU : GEP->users()) {
548 if (CallInst *GEPCall = dyn_cast<CallInst>(GEPU)) {
549 // Find argument index.
550 unsigned GVCstArgIdx = 0;
551 for (unsigned i = 0; i < GEPCall->getNumArgOperands(); i++) {
552 if (GEP == GEPCall->getOperand(i)) {
553 GVCstArgIdx = i;
554 }
555 }
556
557 // Record function with global constant.
558 GlobalConstFuncTyMap[GEPCall->getFunctionType()] =
559 std::make_pair(GEPCall->getFunctionType(), GVCstArgIdx);
560 }
561 }
562 }
563
564 CandidateUsers.push_back(GVU);
565 }
566
567 for (User *U : CandidateUsers) {
568 // Update users of gv with new gv.
569 U->replaceUsesOfWith(GV, NewGV);
570 }
571
572 // Delete original gv.
573 GV->eraseFromParent();
574 }
575
576 bool HasWorkGroupBuiltin = false;
577 for (GlobalVariable &GV : M.globals()) {
578 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
579 if (spv::BuiltInWorkgroupSize == BuiltinType) {
580 HasWorkGroupBuiltin = true;
581 }
582 }
583
584
585 for (Function &F : M) {
586 // Handle kernel function first.
587 if (F.isDeclaration() || F.getCallingConv() != CallingConv::SPIR_KERNEL) {
588 continue;
589 }
590
591 for (BasicBlock &BB : F) {
592 for (Instruction &I : BB) {
593 if (I.getOpcode() == Instruction::ZExt ||
594 I.getOpcode() == Instruction::SExt ||
595 I.getOpcode() == Instruction::UIToFP) {
596 // If there is zext with i1 type, it will be changed to OpSelect. The
597 // OpSelect needs constant 0 and 1 so the constants are added here.
598
599 auto OpTy = I.getOperand(0)->getType();
600
601 if (OpTy->isIntegerTy(1) ||
602 (OpTy->isVectorTy() &&
603 OpTy->getVectorElementType()->isIntegerTy(1))) {
604 if (I.getOpcode() == Instruction::ZExt) {
605 APInt One(32, 1);
606 FindConstant(Constant::getNullValue(I.getType()));
607 FindConstant(Constant::getIntegerValue(I.getType(), One));
608 } else if (I.getOpcode() == Instruction::SExt) {
609 APInt MinusOne(32, UINT64_MAX, true);
610 FindConstant(Constant::getNullValue(I.getType()));
611 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
612 } else {
613 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
614 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
615 }
616 }
617 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
618 Function *Callee = Call->getCalledFunction();
619
620 // Handle image type specially.
621 if (Callee->getName().equals(
622 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
623 Callee->getName().equals(
624 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
625 TypeMapType &OpImageTypeMap = getImageTypeMap();
626 Type *ImageTy =
627 Call->getArgOperand(0)->getType()->getPointerElementType();
628 OpImageTypeMap[ImageTy] = 0;
629
630 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
631 }
632 }
633 }
634 }
635
636 if (M.getTypeByName("opencl.image2d_ro_t") ||
637 M.getTypeByName("opencl.image2d_wo_t") ||
638 M.getTypeByName("opencl.image3d_ro_t") ||
639 M.getTypeByName("opencl.image3d_wo_t")) {
640 // Assume Image type's sampled type is float type.
641 FindType(Type::getFloatTy(Context));
642 }
643
644 if (const MDNode *MD =
645 dyn_cast<Function>(&F)->getMetadata("reqd_work_group_size")) {
646 // We generate constants if the WorkgroupSize builtin is being used.
647 if (HasWorkGroupBuiltin) {
648 // Collect constant information for work group size.
649 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(0)));
650 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(1)));
651 FindConstant(mdconst::extract<ConstantInt>(MD->getOperand(2)));
652 }
653 }
654
655 // Wrap up all argument types with struct type and create global variables
656 // with them.
657 bool HasArgUser = false;
658 unsigned Idx = 0;
659
660 for (const Argument &Arg : F.args()) {
661 Type *ArgTy = Arg.getType();
662 Type *GVTy = nullptr;
663
664 // Check argument type whether it is pointer type or not. If it is
665 // pointer type, add its address space to new global variable for
666 // argument.
667 unsigned AddrSpace = AddressSpace::Global;
668 if (PointerType *ArgPTy = dyn_cast<PointerType>(ArgTy)) {
669 AddrSpace = ArgPTy->getAddressSpace();
670 }
671
672 Type *TmpArgTy = ArgTy;
673
674 // sampler_t and image types have pointer type of struct type with
675 // opaque
676 // type as field. Extract the struct type. It will be used by global
677 // variable for argument.
678 bool IsSamplerType = false;
679 bool IsImageType = false;
680 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
681 if (StructType *STy =
682 dyn_cast<StructType>(TmpArgPTy->getElementType())) {
683 if (STy->isOpaque()) {
684 if (STy->getName().equals("opencl.sampler_t")) {
685 AddrSpace = AddressSpace::UniformConstant;
686 IsSamplerType = true;
687 TmpArgTy = STy;
688 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
689 STy->getName().equals("opencl.image2d_wo_t") ||
690 STy->getName().equals("opencl.image3d_ro_t") ||
691 STy->getName().equals("opencl.image3d_wo_t")) {
692 AddrSpace = AddressSpace::UniformConstant;
693 IsImageType = true;
694 TmpArgTy = STy;
695 } else {
696 llvm_unreachable("Argument has opaque type unsupported???");
697 }
698 }
699 }
700 }
701
702 // LLVM's pointer type is distinguished by address space but we need to
703 // regard constant and global address space as same here. If pointer
704 // type has constant address space, generate new pointer type
705 // temporarily to check previous struct type for argument.
706 if (PointerType *TmpArgPTy = dyn_cast<PointerType>(TmpArgTy)) {
707 AddrSpace = TmpArgPTy->getAddressSpace();
708 if (AddrSpace == AddressSpace::Constant) {
709 TmpArgTy = PointerType::get(TmpArgPTy->getElementType(),
710 AddressSpace::Global);
711 }
712 }
713
714 if (IsSamplerType || IsImageType) {
715 GVTy = TmpArgTy;
716 } else if (ArgTyMap.count(TmpArgTy)) {
717 // If there are arguments handled previously, use its type.
718 GVTy = ArgTyMap[TmpArgTy];
719 } else {
720 // Wrap up argument type with struct type.
721 StructType *STy = StructType::create(Context);
722
723 SmallVector<Type *, 8> EltTys;
724 EltTys.push_back(ArgTy);
725
726 STy->setBody(EltTys, false);
727
728 GVTy = STy;
729 ArgTyMap[TmpArgTy] = STy;
730 }
731
732 // In order to build type map between llvm type and spirv id, LLVM
733 // global variable is needed. It has llvm type and other instructions
734 // can access it with its type.
735 GlobalVariable *NewGV = new GlobalVariable(
736 M, GVTy, false, GlobalValue::ExternalLinkage, UndefValue::get(GVTy),
737 F.getName() + ".arg." + std::to_string(Idx++), nullptr,
738 GlobalValue::ThreadLocalMode::NotThreadLocal, AddrSpace);
739
740 // Generate type info for argument global variable.
741 FindType(NewGV->getType());
742
743 ArgGVMap[&Arg] = NewGV;
744
745 // Generate pointer type of argument type for OpAccessChain of argument.
746 if (!Arg.use_empty()) {
747 if (!isa<PointerType>(ArgTy)) {
748 FindType(PointerType::get(ArgTy, AddrSpace));
749 }
750 HasArgUser = true;
751 }
752 }
753
754 if (HasArgUser) {
755 // Generate constant 0 for OpAccessChain of argument.
756 Type *IdxTy = Type::getInt32Ty(Context);
757 FindConstant(ConstantInt::get(IdxTy, 0));
758 FindType(IdxTy);
759 }
760
761 // Collect types' information from function.
762 FindTypePerFunc(F);
763
764 // Collect constant information from function.
765 FindConstantPerFunc(F);
766 }
767
768 for (Function &F : M) {
769 // Handle non-kernel functions.
770 if (F.isDeclaration() || F.getCallingConv() == CallingConv::SPIR_KERNEL) {
771 continue;
772 }
773
774 for (BasicBlock &BB : F) {
775 for (Instruction &I : BB) {
776 if (I.getOpcode() == Instruction::ZExt ||
777 I.getOpcode() == Instruction::SExt ||
778 I.getOpcode() == Instruction::UIToFP) {
779 // If there is zext with i1 type, it will be changed to OpSelect. The
780 // OpSelect needs constant 0 and 1 so the constants are added here.
781
782 auto OpTy = I.getOperand(0)->getType();
783
784 if (OpTy->isIntegerTy(1) ||
785 (OpTy->isVectorTy() &&
786 OpTy->getVectorElementType()->isIntegerTy(1))) {
787 if (I.getOpcode() == Instruction::ZExt) {
788 APInt One(32, 1);
789 FindConstant(Constant::getNullValue(I.getType()));
790 FindConstant(Constant::getIntegerValue(I.getType(), One));
791 } else if (I.getOpcode() == Instruction::SExt) {
792 APInt MinusOne(32, UINT64_MAX, true);
793 FindConstant(Constant::getNullValue(I.getType()));
794 FindConstant(Constant::getIntegerValue(I.getType(), MinusOne));
795 } else {
796 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
797 FindConstant(ConstantFP::get(Context, APFloat(1.0f)));
798 }
799 }
800 } else if (CallInst *Call = dyn_cast<CallInst>(&I)) {
801 Function *Callee = Call->getCalledFunction();
802
803 // Handle image type specially.
804 if (Callee->getName().equals(
805 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
806 Callee->getName().equals(
807 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
808 TypeMapType &OpImageTypeMap = getImageTypeMap();
809 Type *ImageTy =
810 Call->getArgOperand(0)->getType()->getPointerElementType();
811 OpImageTypeMap[ImageTy] = 0;
812
813 FindConstant(ConstantFP::get(Context, APFloat(0.0f)));
814 }
815 }
816 }
817 }
818
819 if (M.getTypeByName("opencl.image2d_ro_t") ||
820 M.getTypeByName("opencl.image2d_wo_t") ||
821 M.getTypeByName("opencl.image3d_ro_t") ||
822 M.getTypeByName("opencl.image3d_wo_t")) {
823 // Assume Image type's sampled type is float type.
824 FindType(Type::getFloatTy(Context));
825 }
826
827 // Collect types' information from function.
828 FindTypePerFunc(F);
829
830 // Collect constant information from function.
831 FindConstantPerFunc(F);
832 }
833}
834
835bool SPIRVProducerPass::FindExtInst(Module &M) {
836 LLVMContext &Context = M.getContext();
837 bool HasExtInst = false;
838
839 for (Function &F : M) {
840 for (BasicBlock &BB : F) {
841 for (Instruction &I : BB) {
842 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
843 Function *Callee = Call->getCalledFunction();
844 // Check whether this call is for extend instructions.
845 glsl::ExtInst EInst = getExtInstEnum(Callee->getName());
846 if (EInst) {
847 // clz needs OpExtInst and OpISub with constant 31. Add constant 31
848 // to constant list here.
849 if (EInst == glsl::ExtInstFindUMsb) {
850 Type *IdxTy = Type::getInt32Ty(Context);
851 FindConstant(ConstantInt::get(IdxTy, 31));
852 FindType(IdxTy);
853 }
854
855 HasExtInst = true;
856 }
857 }
858 }
859 }
860 }
861
862 return HasExtInst;
863}
864
865void SPIRVProducerPass::FindTypePerGlobalVar(GlobalVariable &GV) {
866 // Investigate global variable's type.
867 FindType(GV.getType());
868}
869
870void SPIRVProducerPass::FindTypePerFunc(Function &F) {
871 // Investigate function's type.
872 FunctionType *FTy = F.getFunctionType();
873
874 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
875 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
876 // Handle function with global constant parameters.
877 if (GlobalConstFuncTyMap.count(FTy)) {
878 uint32_t GVCstArgIdx = GlobalConstFuncTypeMap[FTy].second;
879 SmallVector<Type *, 4> NewFuncParamTys;
880 for (unsigned i = 0; i < FTy->getNumParams(); i++) {
881 Type *ParamTy = FTy->getParamType(i);
882 if (i == GVCstArgIdx) {
883 Type *EleTy = ParamTy->getPointerElementType();
884 ParamTy = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
885 }
886
887 NewFuncParamTys.push_back(ParamTy);
888 }
889
890 FunctionType *NewFTy =
891 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
892 GlobalConstFuncTyMap[FTy] = std::make_pair(NewFTy, GVCstArgIdx);
893 FTy = NewFTy;
894 }
895
896 FindType(FTy);
897 } else {
898 // As kernel functions do not have parameters, create new function type and
899 // add it to type map.
900 SmallVector<Type *, 4> NewFuncParamTys;
901 FunctionType *NewFTy =
902 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
903 FindType(NewFTy);
904 }
905
906 // Investigate instructions' type in function body.
907 for (BasicBlock &BB : F) {
908 for (Instruction &I : BB) {
909 if (isa<ShuffleVectorInst>(I)) {
910 for (unsigned i = 0; i < I.getNumOperands(); i++) {
911 // Ignore type for mask of shuffle vector instruction.
912 if (i == 2) {
913 continue;
914 }
915
916 Value *Op = I.getOperand(i);
917 if (!isa<MetadataAsValue>(Op)) {
918 FindType(Op->getType());
919 }
920 }
921
922 FindType(I.getType());
923 continue;
924 }
925
926 // Work through the operands of the instruction.
927 for (unsigned i = 0; i < I.getNumOperands(); i++) {
928 Value *const Op = I.getOperand(i);
929 // If any of the operands is a constant, find the type!
930 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
931 FindType(Op->getType());
932 }
933 }
934
935 for (Use &Op : I.operands()) {
936 if (CallInst *Call = dyn_cast<CallInst>(&I)) {
937 // Avoid to check call instruction's type.
938 break;
939 }
940 if (!isa<MetadataAsValue>(&Op)) {
941 FindType(Op->getType());
942 continue;
943 }
944 }
945
946 CallInst *Call = dyn_cast<CallInst>(&I);
947
948 // We don't want to track the type of this call as we are going to replace
949 // it.
950 if (Call && ("__translate_sampler_initializer" ==
951 Call->getCalledFunction()->getName())) {
952 continue;
953 }
954
955 if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
956 // If gep's base operand has ModuleScopePrivate address space, make gep
957 // return ModuleScopePrivate address space.
958 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate) {
959 // Add pointer type with private address space for global constant to
960 // type list.
961 Type *EleTy = I.getType()->getPointerElementType();
962 Type *NewPTy =
963 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
964
965 FindType(NewPTy);
966 continue;
967 }
968 }
969
970 FindType(I.getType());
971 }
972 }
973}
974
975void SPIRVProducerPass::FindType(Type *Ty) {
976 TypeList &TyList = getTypeList();
977
978 if (0 != TyList.idFor(Ty)) {
979 return;
980 }
981
982 if (Ty->isPointerTy()) {
983 auto AddrSpace = Ty->getPointerAddressSpace();
984 if ((AddressSpace::Constant == AddrSpace) ||
985 (AddressSpace::Global == AddrSpace)) {
986 auto PointeeTy = Ty->getPointerElementType();
987
988 if (PointeeTy->isStructTy() &&
989 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
990 FindType(PointeeTy);
991 auto ActualPointerTy =
992 PointeeTy->getPointerTo(AddressSpace::UniformConstant);
993 FindType(ActualPointerTy);
994 return;
995 }
996 }
997 }
998
999 // OpTypeArray has constant and we need to support type of the constant.
1000 if (isa<ArrayType>(Ty)) {
1001 LLVMContext &Context = Ty->getContext();
1002 FindType(Type::getInt32Ty(Context));
1003 }
1004
1005 for (Type *SubTy : Ty->subtypes()) {
1006 FindType(SubTy);
1007 }
1008
1009 TyList.insert(Ty);
1010}
1011
1012void SPIRVProducerPass::FindConstantPerGlobalVar(GlobalVariable &GV) {
1013 // If the global variable has a (non undef) initializer.
1014 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
1015 FindConstant(GV.getInitializer());
1016 }
1017}
1018
1019void SPIRVProducerPass::FindConstantPerFunc(Function &F) {
1020 // Investigate constants in function body.
1021 for (BasicBlock &BB : F) {
1022 for (Instruction &I : BB) {
1023 CallInst *Call = dyn_cast<CallInst>(&I);
1024
1025 if (Call && ("__translate_sampler_initializer" ==
1026 Call->getCalledFunction()->getName())) {
1027 // We've handled these constants elsewhere, so skip it.
1028 continue;
1029 }
1030
1031 if (isa<AllocaInst>(I)) {
1032 // Alloca instruction has constant for the number of element. Ignore it.
1033 continue;
1034 } else if (isa<ShuffleVectorInst>(I)) {
1035 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1036 // Ignore constant for mask of shuffle vector instruction.
1037 if (i == 2) {
1038 continue;
1039 }
1040
1041 if (isa<Constant>(I.getOperand(i)) &&
1042 !isa<GlobalValue>(I.getOperand(i))) {
1043 FindConstant(I.getOperand(i));
1044 }
1045 }
1046
1047 continue;
1048 } else if (isa<InsertElementInst>(I)) {
1049 // Handle InsertElement with <4 x i8> specially.
1050 Type *CompositeTy = I.getOperand(0)->getType();
1051 if (is4xi8vec(CompositeTy)) {
1052 LLVMContext &Context = CompositeTy->getContext();
1053 if (isa<Constant>(I.getOperand(0))) {
1054 FindConstant(I.getOperand(0));
1055 }
1056
1057 if (isa<Constant>(I.getOperand(1))) {
1058 FindConstant(I.getOperand(1));
1059 }
1060
1061 // Add mask constant 0xFF.
1062 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1063 FindConstant(CstFF);
1064
1065 // Add shift amount constant.
1066 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
1067 uint64_t Idx = CI->getZExtValue();
1068 Constant *CstShiftAmount =
1069 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1070 FindConstant(CstShiftAmount);
1071 }
1072
1073 continue;
1074 }
1075
1076 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1077 // Ignore constant for index of InsertElement instruction.
1078 if (i == 2) {
1079 continue;
1080 }
1081
1082 if (isa<Constant>(I.getOperand(i)) &&
1083 !isa<GlobalValue>(I.getOperand(i))) {
1084 FindConstant(I.getOperand(i));
1085 }
1086 }
1087
1088 continue;
1089 } else if (isa<ExtractElementInst>(I)) {
1090 // Handle ExtractElement with <4 x i8> specially.
1091 Type *CompositeTy = I.getOperand(0)->getType();
1092 if (is4xi8vec(CompositeTy)) {
1093 LLVMContext &Context = CompositeTy->getContext();
1094 if (isa<Constant>(I.getOperand(0))) {
1095 FindConstant(I.getOperand(0));
1096 }
1097
1098 // Add mask constant 0xFF.
1099 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
1100 FindConstant(CstFF);
1101
1102 // Add shift amount constant.
1103 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
1104 uint64_t Idx = CI->getZExtValue();
1105 Constant *CstShiftAmount =
1106 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
1107 FindConstant(CstShiftAmount);
1108 } else {
1109 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
1110 FindConstant(Cst8);
1111 }
1112
1113 continue;
1114 }
1115
1116 for (unsigned i = 0; i < I.getNumOperands(); i++) {
1117 // Ignore constant for index of ExtractElement instruction.
1118 if (i == 1) {
1119 continue;
1120 }
1121
1122 if (isa<Constant>(I.getOperand(i)) &&
1123 !isa<GlobalValue>(I.getOperand(i))) {
1124 FindConstant(I.getOperand(i));
1125 }
1126 }
1127
1128 continue;
1129 } else if ((Instruction::Xor == I.getOpcode()) && I.getType()->isIntegerTy(1)) {
1130 // We special case for Xor where the type is i1 and one of the arguments is a constant 1 (true), this is an OpLogicalNot in SPIR-V, and we don't need the constant
1131 bool foundConstantTrue = false;
1132 for (Use &Op : I.operands()) {
1133 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1134 auto CI = cast<ConstantInt>(Op);
1135
1136 if (CI->isZero() || foundConstantTrue) {
1137 // If we already found the true constant, we might (probably only on -O0) have an OpLogicalNot which is taking a constant argument, so discover it anyway.
1138 FindConstant(Op);
1139 } else {
1140 foundConstantTrue = true;
1141 }
1142 }
1143 }
1144
1145 continue;
1146 }
1147
1148 for (Use &Op : I.operands()) {
1149 if (isa<Constant>(Op) && !isa<GlobalValue>(Op)) {
1150 FindConstant(Op);
1151 }
1152 }
1153 }
1154 }
1155}
1156
1157void SPIRVProducerPass::FindConstant(Value *V) {
1158 ValueMapType &VMap = getValueMap();
1159 ValueList &CstList = getConstantList();
1160
1161 // If V is already in VMap, ignore it.
1162 if (VMap.find_as(V) != VMap.end()) {
1163 return;
1164 }
1165
1166 Constant *Cst = cast<Constant>(V);
1167
1168 // Handle constant with <4 x i8> type specially.
1169 Type *CstTy = Cst->getType();
1170 if (is4xi8vec(CstTy)) {
1171 if (!isa<GlobalValue>(V)) {
1172 CstList.push_back(V);
1173 VMap[V] = static_cast<uint32_t>(CstList.size());
1174 }
1175 }
1176
1177 if (Cst->getNumOperands()) {
1178 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end(); I != E;
1179 ++I) {
1180 FindConstant(*I);
1181 }
1182
1183 CstList.push_back(Cst);
1184 VMap[V] = static_cast<uint32_t>(CstList.size());
1185 return;
1186 } else if (const ConstantDataSequential *CDS =
1187 dyn_cast<ConstantDataSequential>(Cst)) {
1188 // Add constants for each element to constant list.
1189 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
1190 Constant *EleCst = CDS->getElementAsConstant(i);
1191 FindConstant(EleCst);
1192 }
1193 }
1194
1195 if (!isa<GlobalValue>(V)) {
1196 CstList.push_back(V);
1197 VMap[V] = static_cast<uint32_t>(CstList.size());
1198 }
1199}
1200
1201spv::StorageClass SPIRVProducerPass::GetStorageClass(unsigned AddrSpace) const {
1202 switch (AddrSpace) {
1203 default:
1204 llvm_unreachable("Unsupported OpenCL address space");
1205 case AddressSpace::Private:
1206 return spv::StorageClassFunction;
1207 case AddressSpace::Global:
1208 case AddressSpace::Constant:
1209 return spv::StorageClassStorageBuffer;
1210 case AddressSpace::Input:
1211 return spv::StorageClassInput;
1212 case AddressSpace::Local:
1213 return spv::StorageClassWorkgroup;
1214 case AddressSpace::UniformConstant:
1215 return spv::StorageClassUniformConstant;
1216 case AddressSpace::ModuleScopePrivate:
1217 return spv::StorageClassPrivate;
1218 }
1219}
1220
1221spv::BuiltIn SPIRVProducerPass::GetBuiltin(StringRef Name) const {
1222 return StringSwitch<spv::BuiltIn>(Name)
1223 .Case("__spirv_GlobalInvocationId", spv::BuiltInGlobalInvocationId)
1224 .Case("__spirv_LocalInvocationId", spv::BuiltInLocalInvocationId)
1225 .Case("__spirv_WorkgroupSize", spv::BuiltInWorkgroupSize)
1226 .Case("__spirv_NumWorkgroups", spv::BuiltInNumWorkgroups)
1227 .Case("__spirv_WorkgroupId", spv::BuiltInWorkgroupId)
1228 .Default(spv::BuiltInMax);
1229}
1230
1231void SPIRVProducerPass::GenerateExtInstImport() {
1232 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1233 uint32_t &ExtInstImportID = getOpExtInstImportID();
1234
1235 //
1236 // Generate OpExtInstImport.
1237 //
1238 // Ops[0] ... Ops[n] = Name (Literal String)
1239 SPIRVOperandList Ops;
1240
1241 SPIRVOperand *Name =
1242 new SPIRVOperand(SPIRVOperandType::LITERAL_STRING, "GLSL.std.450");
1243 Ops.push_back(Name);
1244
1245 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
1246 assert(NameWordSize < (UINT16_MAX - 2));
1247 if ((Name->getLiteralStr().size() + 1) % 4) {
1248 NameWordSize += 1;
1249 }
1250
1251 uint16_t WordCount = static_cast<uint16_t>(2 + NameWordSize);
1252 ExtInstImportID = nextID;
1253
1254 SPIRVInstruction *Inst =
1255 new SPIRVInstruction(WordCount, spv::OpExtInstImport, nextID++, Ops);
1256 SPIRVInstList.push_back(Inst);
1257}
1258
1259void SPIRVProducerPass::GenerateSPIRVTypes(const DataLayout &DL) {
1260 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1261 ValueMapType &VMap = getValueMap();
1262 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1263 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
1264
1265 // Map for OpTypeRuntimeArray. If argument has pointer type, 2 spirv type
1266 // instructions are generated. They are OpTypePointer and OpTypeRuntimeArray.
1267 DenseMap<Type *, uint32_t> OpRuntimeTyMap;
1268
1269 for (Type *Ty : getTypeList()) {
1270 // Update TypeMap with nextID for reference later.
1271 TypeMap[Ty] = nextID;
1272
1273 switch (Ty->getTypeID()) {
1274 default: {
1275 Ty->print(errs());
1276 llvm_unreachable("Unsupported type???");
1277 break;
1278 }
1279 case Type::MetadataTyID:
1280 case Type::LabelTyID: {
1281 // Ignore these types.
1282 break;
1283 }
1284 case Type::PointerTyID: {
1285 PointerType *PTy = cast<PointerType>(Ty);
1286 unsigned AddrSpace = PTy->getAddressSpace();
1287
1288 // For the purposes of our Vulkan SPIR-V type system, constant and global
1289 // are conflated.
1290 bool UseExistingOpTypePointer = false;
1291 if (AddressSpace::Constant == AddrSpace) {
1292 AddrSpace = AddressSpace::Global;
1293
1294 // Check to see if we already created this type (for instance, if we had
1295 // a constant <type>* and a global <type>*, the type would be created by
1296 // one of these types, and shared by both).
1297 auto GlobalTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1298 if (0 < TypeMap.count(GlobalTy)) {
1299 TypeMap[PTy] = TypeMap[GlobalTy];
1300 break;
1301 }
1302 } else if (AddressSpace::Global == AddrSpace) {
1303 AddrSpace = AddressSpace::Constant;
1304
1305 // Check to see if we already created this type (for instance, if we had
1306 // a constant <type>* and a global <type>*, the type would be created by
1307 // one of these types, and shared by both).
1308 auto ConstantTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1309 if (0 < TypeMap.count(ConstantTy)) {
1310 TypeMap[PTy] = TypeMap[ConstantTy];
1311 UseExistingOpTypePointer = true;
1312 }
1313 }
1314
1315 bool IsOpTypeRuntimeArray = false;
1316 bool HasArgUser = false;
1317
1318 for (auto ArgGV : ArgGVMap) {
1319 auto Arg = ArgGV.first;
1320
1321 Type *ArgTy = Arg->getType();
1322 if (ArgTy == PTy) {
1323 if (AddrSpace != AddressSpace::UniformConstant) {
1324 IsOpTypeRuntimeArray = true;
1325 }
1326
1327 for (auto U : Arg->users()) {
1328 if (!isa<GetElementPtrInst>(U) || (U->getType() == PTy)) {
1329 HasArgUser = true;
1330 break;
1331 }
1332 }
1333 }
1334 }
1335
1336 if ((!IsOpTypeRuntimeArray || HasArgUser) && !UseExistingOpTypePointer) {
1337 //
1338 // Generate OpTypePointer.
1339 //
1340
1341 // OpTypePointer
1342 // Ops[0] = Storage Class
1343 // Ops[1] = Element Type ID
1344 SPIRVOperandList Ops;
1345
1346 spv::StorageClass StorageClass = GetStorageClass(AddrSpace);
1347
1348 SPIRVOperand *StorageClassOp =
1349 new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass);
1350 Ops.push_back(StorageClassOp);
1351
1352 uint32_t EleTyID = lookupType(PTy->getElementType());
1353 SPIRVOperand *EleTyOp =
1354 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1355 Ops.push_back(EleTyOp);
1356
1357 spv::Op Opcode = spv::OpTypePointer;
1358 uint16_t WordCount = 4;
1359
1360 SPIRVInstruction *Inst =
1361 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
1362 SPIRVInstList.push_back(Inst);
1363 }
1364
1365 if (IsOpTypeRuntimeArray) {
1366 //
1367 // Generate OpTypeRuntimeArray.
1368 //
1369
1370 // OpTypeRuntimeArray
1371 // Ops[0] = Element Type ID
1372 SPIRVOperandList Ops;
1373
1374 uint32_t EleTyID = lookupType(PTy->getElementType());
1375 SPIRVOperand *EleTyOp =
1376 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1377 Ops.push_back(EleTyOp);
1378
1379 spv::Op Opcode = spv::OpTypeRuntimeArray;
1380 uint16_t WordCount = 3;
1381
1382 uint32_t OpTypeRuntimeArrayID = nextID;
1383 assert(0 == OpRuntimeTyMap.count(Ty));
1384 OpRuntimeTyMap[Ty] = nextID;
1385
1386 SPIRVInstruction *Inst =
1387 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
1388 SPIRVInstList.push_back(Inst);
1389
1390 // Generate OpDecorate.
1391 auto DecoInsertPoint =
1392 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1393 [](SPIRVInstruction *Inst) -> bool {
1394 return Inst->getOpcode() != spv::OpDecorate &&
1395 Inst->getOpcode() != spv::OpMemberDecorate &&
1396 Inst->getOpcode() != spv::OpExtInstImport;
1397 });
1398
1399 // Ops[0] = Target ID
1400 // Ops[1] = Decoration (ArrayStride)
1401 // Ops[2] = Stride Number(Literal Number)
1402 Ops.clear();
1403
1404 SPIRVOperand *PTyIDOp =
1405 new SPIRVOperand(SPIRVOperandType::NUMBERID, OpTypeRuntimeArrayID);
1406 Ops.push_back(PTyIDOp);
1407
1408 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID,
1409 spv::DecorationArrayStride);
1410 Ops.push_back(DecoOp);
1411
1412 std::vector<uint32_t> LiteralNum;
1413 Type *EleTy = PTy->getElementType();
David Neto25018082017-07-07 13:21:46 -04001414 const unsigned ArrayStride = DL.getTypeAllocSize(EleTy);
David Neto22f144c2017-06-12 14:26:21 -04001415 LiteralNum.push_back(ArrayStride);
1416 SPIRVOperand *ArrayStrideOp =
1417 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1418 Ops.push_back(ArrayStrideOp);
1419
1420 SPIRVInstruction *DecoInst =
1421 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
1422 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1423 }
1424 break;
1425 }
1426 case Type::StructTyID: {
1427 LLVMContext &Context = Ty->getContext();
1428
1429 StructType *STy = cast<StructType>(Ty);
1430
1431 // Handle sampler type.
1432 if (STy->isOpaque()) {
1433 if (STy->getName().equals("opencl.sampler_t")) {
1434 //
1435 // Generate OpTypeSampler
1436 //
1437 // Empty Ops.
1438 SPIRVOperandList Ops;
1439
1440 SPIRVInstruction *Inst =
1441 new SPIRVInstruction(2, spv::OpTypeSampler, nextID++, Ops);
1442 SPIRVInstList.push_back(Inst);
1443 break;
1444 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
1445 STy->getName().equals("opencl.image2d_wo_t") ||
1446 STy->getName().equals("opencl.image3d_ro_t") ||
1447 STy->getName().equals("opencl.image3d_wo_t")) {
1448 //
1449 // Generate OpTypeImage
1450 //
1451 // Ops[0] = Sampled Type ID
1452 // Ops[1] = Dim ID
1453 // Ops[2] = Depth (Literal Number)
1454 // Ops[3] = Arrayed (Literal Number)
1455 // Ops[4] = MS (Literal Number)
1456 // Ops[5] = Sampled (Literal Number)
1457 // Ops[6] = Image Format ID
1458 //
1459 SPIRVOperandList Ops;
1460
1461 // TODO: Changed Sampled Type according to situations.
1462 uint32_t SampledTyID = lookupType(Type::getFloatTy(Context));
1463 SPIRVOperand *SampledTyIDOp =
1464 new SPIRVOperand(SPIRVOperandType::NUMBERID, SampledTyID);
1465 Ops.push_back(SampledTyIDOp);
1466
1467 spv::Dim DimID = spv::Dim2D;
1468 if (STy->getName().equals("opencl.image3d_ro_t") ||
1469 STy->getName().equals("opencl.image3d_wo_t")) {
1470 DimID = spv::Dim3D;
1471 }
1472 SPIRVOperand *DimIDOp =
1473 new SPIRVOperand(SPIRVOperandType::NUMBERID, DimID);
1474 Ops.push_back(DimIDOp);
1475
1476 // TODO: Set up Depth.
1477 std::vector<uint32_t> LiteralNum;
1478 LiteralNum.push_back(0);
1479 SPIRVOperand *DepthOp =
1480 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1481 Ops.push_back(DepthOp);
1482
1483 // TODO: Set up Arrayed.
1484 LiteralNum.clear();
1485 LiteralNum.push_back(0);
1486 SPIRVOperand *ArrayedOp =
1487 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1488 Ops.push_back(ArrayedOp);
1489
1490 // TODO: Set up MS.
1491 LiteralNum.clear();
1492 LiteralNum.push_back(0);
1493 SPIRVOperand *MSOp =
1494 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1495 Ops.push_back(MSOp);
1496
1497 // TODO: Set up Sampled.
1498 //
1499 // From Spec
1500 //
1501 // 0 indicates this is only known at run time, not at compile time
1502 // 1 indicates will be used with sampler
1503 // 2 indicates will be used without a sampler (a storage image)
1504 uint32_t Sampled = 1;
1505 if (STy->getName().equals("opencl.image2d_wo_t") ||
1506 STy->getName().equals("opencl.image3d_wo_t")) {
1507 Sampled = 2;
1508 }
1509 LiteralNum.clear();
1510 LiteralNum.push_back(Sampled);
1511 SPIRVOperand *SampledOp =
1512 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1513 Ops.push_back(SampledOp);
1514
1515 // TODO: Set up Image Format.
1516 SPIRVOperand *ImageFormatOp = new SPIRVOperand(
1517 SPIRVOperandType::NUMBERID, spv::ImageFormatUnknown);
1518 Ops.push_back(ImageFormatOp);
1519
1520 SPIRVInstruction *Inst =
1521 new SPIRVInstruction(9, spv::OpTypeImage, nextID++, Ops);
1522 SPIRVInstList.push_back(Inst);
1523 break;
1524 }
1525 }
1526
1527 //
1528 // Generate OpTypeStruct
1529 //
1530 // Ops[0] ... Ops[n] = Member IDs
1531 SPIRVOperandList Ops;
1532
1533 for (auto *EleTy : STy->elements()) {
1534 uint32_t EleTyID = lookupType(EleTy);
1535
1536 // Check OpTypeRuntimeArray.
1537 if (isa<PointerType>(EleTy)) {
1538 for (auto ArgGV : ArgGVMap) {
1539 Type *ArgTy = ArgGV.first->getType();
1540 if (ArgTy == EleTy) {
1541 assert(0 != OpRuntimeTyMap.count(EleTy));
1542 EleTyID = OpRuntimeTyMap[EleTy];
1543 }
1544 }
1545 }
1546
1547 SPIRVOperand *EleTyOp =
1548 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1549 Ops.push_back(EleTyOp);
1550 }
1551
1552 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
1553 uint32_t STyID = nextID;
1554
1555 SPIRVInstruction *Inst =
1556 new SPIRVInstruction(WordCount, spv::OpTypeStruct, nextID++, Ops);
1557 SPIRVInstList.push_back(Inst);
1558
1559 // Generate OpMemberDecorate.
1560 auto DecoInsertPoint =
1561 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1562 [](SPIRVInstruction *Inst) -> bool {
1563 return Inst->getOpcode() != spv::OpDecorate &&
1564 Inst->getOpcode() != spv::OpMemberDecorate &&
1565 Inst->getOpcode() != spv::OpExtInstImport;
1566 });
1567
David Netoc463b372017-08-10 15:32:21 -04001568 const auto StructLayout = DL.getStructLayout(STy);
1569
David Neto22f144c2017-06-12 14:26:21 -04001570 for (unsigned MemberIdx = 0; MemberIdx < STy->getNumElements();
1571 MemberIdx++) {
1572 // Ops[0] = Structure Type ID
1573 // Ops[1] = Member Index(Literal Number)
1574 // Ops[2] = Decoration (Offset)
1575 // Ops[3] = Byte Offset (Literal Number)
1576 Ops.clear();
1577
1578 SPIRVOperand *STyIDOp =
1579 new SPIRVOperand(SPIRVOperandType::NUMBERID, STyID);
1580 Ops.push_back(STyIDOp);
1581
1582 std::vector<uint32_t> LiteralNum;
1583 LiteralNum.push_back(MemberIdx);
1584 SPIRVOperand *MemberIdxOp =
1585 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1586 Ops.push_back(MemberIdxOp);
1587
1588 SPIRVOperand *DecoOp =
1589 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationOffset);
1590 Ops.push_back(DecoOp);
1591
1592 LiteralNum.clear();
David Netoc463b372017-08-10 15:32:21 -04001593 const auto ByteOffset =
1594 uint32_t(StructLayout->getElementOffset(MemberIdx));
David Neto22f144c2017-06-12 14:26:21 -04001595 LiteralNum.push_back(ByteOffset);
1596 SPIRVOperand *ByteOffsetOp =
1597 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1598 Ops.push_back(ByteOffsetOp);
1599
1600 SPIRVInstruction *DecoInst =
1601 new SPIRVInstruction(5, spv::OpMemberDecorate, 0 /* No id */, Ops);
1602 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04001603 }
1604
1605 // Generate OpDecorate.
1606 for (auto ArgGV : ArgGVMap) {
1607 Type *ArgGVTy = ArgGV.second->getType();
1608 PointerType *PTy = cast<PointerType>(ArgGVTy);
1609 Type *ArgTy = PTy->getElementType();
1610
1611 // Struct type from argument is already distinguished with the other
1612 // struct types on llvm types. As a result, if current processing struct
1613 // type is same with argument type, we can generate OpDecorate with
1614 // Block or BufferBlock.
1615 if (ArgTy == STy) {
1616 // Ops[0] = Target ID
1617 // Ops[1] = Decoration (Block or BufferBlock)
1618 Ops.clear();
1619
1620 SPIRVOperand *STyIDOp =
1621 new SPIRVOperand(SPIRVOperandType::NUMBERID, STyID);
1622 Ops.push_back(STyIDOp);
1623
David Neto6e392822017-08-04 14:06:10 -04001624 // Use Block decorations with StorageBuffer storage class.
1625 const spv::Decoration Deco = spv::DecorationBlock;
David Neto22f144c2017-06-12 14:26:21 -04001626
1627 SPIRVOperand *DecoOp =
1628 new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
1629 Ops.push_back(DecoOp);
1630
1631 SPIRVInstruction *DecoInst =
1632 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
1633 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1634 break;
1635 }
1636 }
1637 break;
1638 }
1639 case Type::IntegerTyID: {
1640 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
1641
1642 if (BitWidth == 1) {
1643 SPIRVInstruction *Inst =
1644 new SPIRVInstruction(2, spv::OpTypeBool, nextID++, {});
1645 SPIRVInstList.push_back(Inst);
1646 } else {
1647 // i8 is added to TypeMap as i32.
1648 if (BitWidth == 8) {
1649 BitWidth = 32;
1650 }
1651
1652 SPIRVOperand *Ops[2] = {
1653 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, BitWidth),
1654 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, 0u)};
1655
1656 SPIRVInstList.push_back(
1657 new SPIRVInstruction(4, spv::OpTypeInt, nextID++, Ops));
1658 }
1659 break;
1660 }
1661 case Type::HalfTyID:
1662 case Type::FloatTyID:
1663 case Type::DoubleTyID: {
1664 SPIRVOperand *WidthOp = new SPIRVOperand(
1665 SPIRVOperandType::LITERAL_INTEGER, Ty->getPrimitiveSizeInBits());
1666
1667 SPIRVInstList.push_back(
1668 new SPIRVInstruction(3, spv::OpTypeFloat, nextID++, WidthOp));
1669 break;
1670 }
1671 case Type::ArrayTyID: {
1672 LLVMContext &Context = Ty->getContext();
1673 ArrayType *ArrTy = cast<ArrayType>(Ty);
1674 //
1675 // Generate OpConstant and OpTypeArray.
1676 //
1677
1678 //
1679 // Generate OpConstant for array length.
1680 //
1681 // Ops[0] = Result Type ID
1682 // Ops[1] .. Ops[n] = Values LiteralNumber
1683 SPIRVOperandList Ops;
1684
1685 Type *LengthTy = Type::getInt32Ty(Context);
1686 uint32_t ResTyID = lookupType(LengthTy);
1687 SPIRVOperand *ResTyOp =
1688 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
1689 Ops.push_back(ResTyOp);
1690
1691 uint64_t Length = ArrTy->getArrayNumElements();
1692 assert(Length < UINT32_MAX);
1693 std::vector<uint32_t> LiteralNum;
1694 LiteralNum.push_back(static_cast<uint32_t>(Length));
1695 SPIRVOperand *ValOp =
1696 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1697 Ops.push_back(ValOp);
1698
1699 // Add constant for length to constant list.
1700 Constant *CstLength = ConstantInt::get(LengthTy, Length);
1701 AllocatedVMap[CstLength] = nextID;
1702 VMap[CstLength] = nextID;
1703 uint32_t LengthID = nextID;
1704
1705 SPIRVInstruction *CstInst =
1706 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
1707 SPIRVInstList.push_back(CstInst);
1708
1709 //
1710 // Generate OpTypeArray.
1711 //
1712 // Ops[0] = Element Type ID
1713 // Ops[1] = Array Length Constant ID
1714 Ops.clear();
1715
1716 uint32_t EleTyID = lookupType(ArrTy->getElementType());
1717 SPIRVOperand *EleTyOp =
1718 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1719 Ops.push_back(EleTyOp);
1720
1721 SPIRVOperand *LengthOp =
1722 new SPIRVOperand(SPIRVOperandType::NUMBERID, LengthID);
1723 Ops.push_back(LengthOp);
1724
1725 // Update TypeMap with nextID.
1726 TypeMap[Ty] = nextID;
1727
1728 SPIRVInstruction *ArrayInst =
1729 new SPIRVInstruction(4, spv::OpTypeArray, nextID++, Ops);
1730 SPIRVInstList.push_back(ArrayInst);
1731 break;
1732 }
1733 case Type::VectorTyID: {
1734 // <4 x i8> is changed to i32.
1735 LLVMContext &Context = Ty->getContext();
1736 if (Ty->getVectorElementType() == Type::getInt8Ty(Context)) {
1737 if (Ty->getVectorNumElements() == 4) {
1738 TypeMap[Ty] = lookupType(Ty->getVectorElementType());
1739 break;
1740 } else {
1741 Ty->print(errs());
1742 llvm_unreachable("Support above i8 vector type");
1743 }
1744 }
1745
1746 // Ops[0] = Component Type ID
1747 // Ops[1] = Component Count (Literal Number)
1748 SPIRVOperand *Ops[2] = {
1749 new SPIRVOperand(SPIRVOperandType::NUMBERID,
1750 lookupType(Ty->getVectorElementType())),
1751 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER,
1752 Ty->getVectorNumElements())};
1753
1754 SPIRVInstList.push_back(
1755 new SPIRVInstruction(4, spv::OpTypeVector, nextID++, Ops));
1756 break;
1757 }
1758 case Type::VoidTyID: {
1759 SPIRVInstruction *Inst =
1760 new SPIRVInstruction(2, spv::OpTypeVoid, nextID++, {});
1761 SPIRVInstList.push_back(Inst);
1762 break;
1763 }
1764 case Type::FunctionTyID: {
1765 // Generate SPIRV instruction for function type.
1766 FunctionType *FTy = cast<FunctionType>(Ty);
1767
1768 // Ops[0] = Return Type ID
1769 // Ops[1] ... Ops[n] = Parameter Type IDs
1770 SPIRVOperandList Ops;
1771
1772 // Find SPIRV instruction for return type
1773 uint32_t RetTyID = lookupType(FTy->getReturnType());
1774
1775 SPIRVOperand *RetTyOp =
1776 new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
1777 Ops.push_back(RetTyOp);
1778
1779 // Find SPIRV instructions for parameter types
1780 for (unsigned k = 0; k < FTy->getNumParams(); k++) {
1781 // Find SPIRV instruction for parameter type.
1782 auto ParamTy = FTy->getParamType(k);
1783 if (ParamTy->isPointerTy()) {
1784 auto PointeeTy = ParamTy->getPointerElementType();
1785 if (PointeeTy->isStructTy() &&
1786 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1787 ParamTy = PointeeTy;
1788 }
1789 }
1790
1791 uint32_t ParamTyID = lookupType(ParamTy);
1792 SPIRVOperand *ParamTyOp =
1793 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParamTyID);
1794 Ops.push_back(ParamTyOp);
1795 }
1796
1797 // Return type id is included in operand list.
1798 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
1799
1800 SPIRVInstruction *Inst =
1801 new SPIRVInstruction(WordCount, spv::OpTypeFunction, nextID++, Ops);
1802 SPIRVInstList.push_back(Inst);
1803 break;
1804 }
1805 }
1806 }
1807
1808 // Generate OpTypeSampledImage.
1809 TypeMapType &OpImageTypeMap = getImageTypeMap();
1810 for (auto &ImageType : OpImageTypeMap) {
1811 //
1812 // Generate OpTypeSampledImage.
1813 //
1814 // Ops[0] = Image Type ID
1815 //
1816 SPIRVOperandList Ops;
1817
1818 Type *ImgTy = ImageType.first;
1819 uint32_t ImgTyID = TypeMap[ImgTy];
1820 SPIRVOperand *ImgTyOp =
1821 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImgTyID);
1822 Ops.push_back(ImgTyOp);
1823
1824 // Update OpImageTypeMap.
1825 ImageType.second = nextID;
1826
1827 SPIRVInstruction *Inst =
1828 new SPIRVInstruction(3, spv::OpTypeSampledImage, nextID++, Ops);
1829 SPIRVInstList.push_back(Inst);
1830 }
1831}
1832
1833void SPIRVProducerPass::GenerateSPIRVConstants() {
1834 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1835 ValueMapType &VMap = getValueMap();
1836 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1837 ValueList &CstList = getConstantList();
1838
1839 for (uint32_t i = 0; i < CstList.size(); i++) {
1840 Constant *Cst = cast<Constant>(CstList[i]);
1841
1842 // OpTypeArray's constant was already generated.
David Neto19a1bad2017-08-25 15:01:41 -04001843 //if (!AllocatedVMap.find_as(Cst) != AllocatedVMap.end())
David Neto22f144c2017-06-12 14:26:21 -04001844 if (AllocatedVMap[Cst]) {
1845 continue;
1846 }
1847
David Neto19a1bad2017-08-25 15:01:41 -04001848 // Update ValueMap with nextID for reference later.
David Neto22f144c2017-06-12 14:26:21 -04001849 VMap[Cst] = nextID;
1850
1851 //
1852 // Generate OpConstant.
1853 //
1854
1855 // Ops[0] = Result Type ID
1856 // Ops[1] .. Ops[n] = Values LiteralNumber
1857 SPIRVOperandList Ops;
1858
1859 uint32_t ResTyID = lookupType(Cst->getType());
1860 SPIRVOperand *ResTyIDOp =
1861 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
1862 Ops.push_back(ResTyIDOp);
1863
1864 std::vector<uint32_t> LiteralNum;
1865 uint16_t WordCount = 0;
1866 spv::Op Opcode = spv::OpNop;
1867
1868 if (isa<UndefValue>(Cst)) {
1869 // Ops[0] = Result Type ID
1870 Opcode = spv::OpUndef;
1871 WordCount = 3;
1872 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
1873 unsigned BitWidth = CI->getBitWidth();
1874 if (BitWidth == 1) {
1875 // If the bitwidth of constant is 1, generate OpConstantTrue or
1876 // OpConstantFalse.
1877 if (CI->getZExtValue()) {
1878 // Ops[0] = Result Type ID
1879 Opcode = spv::OpConstantTrue;
1880 } else {
1881 // Ops[0] = Result Type ID
1882 Opcode = spv::OpConstantFalse;
1883 }
1884 WordCount = 3;
1885 } else {
1886 auto V = CI->getZExtValue();
1887 LiteralNum.push_back(V & 0xFFFFFFFF);
1888
1889 if (BitWidth > 32) {
1890 LiteralNum.push_back(V >> 32);
1891 }
1892
1893 Opcode = spv::OpConstant;
1894 WordCount = static_cast<uint16_t>(3 + LiteralNum.size());
1895
1896 SPIRVOperand *CstValue =
1897 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1898 Ops.push_back(CstValue);
1899 }
1900 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Cst)) {
1901 uint64_t FPVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
1902 Type *CFPTy = CFP->getType();
1903 if (CFPTy->isFloatTy()) {
1904 LiteralNum.push_back(FPVal & 0xFFFFFFFF);
1905 } else {
1906 CFPTy->print(errs());
1907 llvm_unreachable("Implement this ConstantFP Type");
1908 }
1909
1910 Opcode = spv::OpConstant;
1911 WordCount = static_cast<uint16_t>(3 + LiteralNum.size());
1912
1913 SPIRVOperand *CstValue =
1914 new SPIRVOperand(SPIRVOperandType::LITERAL_FLOAT, LiteralNum);
1915 Ops.push_back(CstValue);
1916 } else if (isa<ConstantDataSequential>(Cst) &&
1917 cast<ConstantDataSequential>(Cst)->isString()) {
1918 Cst->print(errs());
1919 llvm_unreachable("Implement this Constant");
1920
1921 } else if (const ConstantDataSequential *CDS =
1922 dyn_cast<ConstantDataSequential>(Cst)) {
1923 for (unsigned k = 0; k < CDS->getNumElements(); k++) {
1924 Constant *EleCst = CDS->getElementAsConstant(k);
1925 uint32_t EleCstID = VMap[EleCst];
1926 SPIRVOperand *EleCstIDOp =
1927 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleCstID);
1928 Ops.push_back(EleCstIDOp);
1929 }
1930
1931 Opcode = spv::OpConstantComposite;
1932 WordCount = static_cast<uint16_t>(3 + CDS->getNumElements());
1933 } else if (const ConstantAggregate *CA = dyn_cast<ConstantAggregate>(Cst)) {
1934 // Let's convert <4 x i8> constant to int constant specially.
1935 Type *CstTy = Cst->getType();
1936 if (is4xi8vec(CstTy)) {
1937 LLVMContext &Context = CstTy->getContext();
1938
1939 //
1940 // Generate OpConstant with OpTypeInt 32 0.
1941 //
1942 uint64_t IntValue = 0;
1943 uint32_t Idx = 0;
1944 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end();
1945 I != E; ++I) {
1946 uint64_t Val = 0;
1947 if (ConstantInt *CI2 = dyn_cast<ConstantInt>(I)) {
1948 Val = CI2->getZExtValue();
1949 }
1950 IntValue = (IntValue << Idx) | Val;
1951 }
1952
1953 ConstantInt *CstInt =
1954 ConstantInt::get(Type::getInt32Ty(Context), IntValue);
1955 // If this constant is already registered on VMap, use it.
1956 if (VMap.count(CstInt)) {
1957 uint32_t CstID = VMap[CstInt];
1958 VMap[Cst] = CstID;
David Neto19a1bad2017-08-25 15:01:41 -04001959 continue;
David Neto22f144c2017-06-12 14:26:21 -04001960 }
1961
1962 LiteralNum.push_back(IntValue & 0xFFFFFFFF);
1963 SPIRVOperand *CstValue =
1964 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1965 Ops.push_back(CstValue);
1966
1967 SPIRVInstruction *CstInst =
1968 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
1969 SPIRVInstList.push_back(CstInst);
1970
David Neto19a1bad2017-08-25 15:01:41 -04001971 continue;
David Neto22f144c2017-06-12 14:26:21 -04001972 }
1973
David Neto19a1bad2017-08-25 15:01:41 -04001974 // This is a normal constant aggregate.
1975
David Neto22f144c2017-06-12 14:26:21 -04001976 // We use a constant composite in SPIR-V for our constant aggregate in
1977 // LLVM.
1978 Opcode = spv::OpConstantComposite;
1979 WordCount = static_cast<uint16_t>(3 + CA->getNumOperands());
1980
1981 for (unsigned k = 0; k < CA->getNumOperands(); k++) {
1982 // Look up the ID of the element of this aggregate (which we will
1983 // previously have created a constant for).
1984 uint32_t ElementConstantID = VMap[CA->getAggregateElement(k)];
1985
1986 // And add an operand to the composite we are constructing
1987 Ops.push_back(
1988 new SPIRVOperand(SPIRVOperandType::NUMBERID, ElementConstantID));
1989 }
1990 } else if (Cst->isNullValue()) {
1991 Opcode = spv::OpConstantNull;
1992 WordCount = 3;
1993 } else {
1994 Cst->print(errs());
1995 llvm_unreachable("Unsupported Constant???");
1996 }
1997
1998 SPIRVInstruction *CstInst =
1999 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
2000 SPIRVInstList.push_back(CstInst);
2001 }
2002}
2003
2004void SPIRVProducerPass::GenerateSamplers(Module &M) {
2005 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2006 ValueMapType &VMap = getValueMap();
2007
2008 DenseMap<unsigned, unsigned> SamplerLiteralToIDMap;
2009
2010 unsigned BindingIdx = 0;
2011
2012 // Generate the sampler map.
2013 for (auto SamplerLiteral : getSamplerMap()) {
2014 // Generate OpVariable.
2015 //
2016 // GIDOps[0] : Result Type ID
2017 // GIDOps[1] : Storage Class
2018 SPIRVOperandList Ops;
2019
2020 Ops.push_back(
2021 new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(SamplerTy)));
2022
2023 spv::StorageClass StorageClass = spv::StorageClassUniformConstant;
2024 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass));
2025
2026 SPIRVInstruction *Inst = new SPIRVInstruction(
2027 static_cast<uint16_t>(2 + Ops.size()), spv::OpVariable, nextID, Ops);
2028 SPIRVInstList.push_back(Inst);
2029
David Neto44795152017-07-13 15:45:28 -04002030 SamplerLiteralToIDMap[SamplerLiteral.first] = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04002031
2032 // Find Insert Point for OpDecorate.
2033 auto DecoInsertPoint =
2034 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2035 [](SPIRVInstruction *Inst) -> bool {
2036 return Inst->getOpcode() != spv::OpDecorate &&
2037 Inst->getOpcode() != spv::OpMemberDecorate &&
2038 Inst->getOpcode() != spv::OpExtInstImport;
2039 });
2040
2041 // Ops[0] = Target ID
2042 // Ops[1] = Decoration (DescriptorSet)
2043 // Ops[2] = LiteralNumber according to Decoration
2044 Ops.clear();
2045
David Neto44795152017-07-13 15:45:28 -04002046 SPIRVOperand *ArgIDOp =
2047 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2048 SamplerLiteralToIDMap[SamplerLiteral.first]);
David Neto22f144c2017-06-12 14:26:21 -04002049 Ops.push_back(ArgIDOp);
2050
2051 spv::Decoration Deco = spv::DecorationDescriptorSet;
2052 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2053 Ops.push_back(DecoOp);
2054
David Neto44795152017-07-13 15:45:28 -04002055 descriptorMapOut << "sampler," << SamplerLiteral.first << ",samplerExpr,\""
2056 << SamplerLiteral.second << "\",descriptorSet,0,binding,"
David Netoc2c368d2017-06-30 16:50:17 -04002057 << BindingIdx << "\n";
2058
David Neto22f144c2017-06-12 14:26:21 -04002059 std::vector<uint32_t> LiteralNum;
2060 LiteralNum.push_back(0);
2061 SPIRVOperand *DescSet =
2062 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2063 Ops.push_back(DescSet);
2064
2065 SPIRVInstruction *DescDecoInst =
2066 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2067 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2068
2069 // Ops[0] = Target ID
2070 // Ops[1] = Decoration (Binding)
2071 // Ops[2] = LiteralNumber according to Decoration
2072 Ops.clear();
2073
2074 Ops.push_back(ArgIDOp);
2075
2076 Deco = spv::DecorationBinding;
2077 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2078 Ops.push_back(DecoOp);
2079
2080 LiteralNum.clear();
2081 LiteralNum.push_back(BindingIdx++);
2082 SPIRVOperand *Binding =
2083 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2084 Ops.push_back(Binding);
2085
2086 SPIRVInstruction *BindDecoInst =
2087 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2088 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2089 }
2090
2091 const char *TranslateSamplerFunctionName = "__translate_sampler_initializer";
2092
2093 auto SamplerFunction = M.getFunction(TranslateSamplerFunctionName);
2094
2095 // If there are no uses of the sampler function, no work to do!
2096 if (!SamplerFunction) {
2097 return;
2098 }
2099
2100 // Iterate through the users of the sampler function.
2101 for (auto User : SamplerFunction->users()) {
2102 if (auto CI = dyn_cast<CallInst>(User)) {
2103 // Get the literal used to initialize the sampler.
2104 auto Constant = dyn_cast<ConstantInt>(CI->getArgOperand(0));
2105
2106 if (!Constant) {
2107 CI->getArgOperand(0)->print(errs());
2108 llvm_unreachable("Argument of sampler initializer was non-constant!");
2109 }
2110
2111 auto SamplerLiteral = static_cast<unsigned>(Constant->getZExtValue());
2112
2113 if (0 == SamplerLiteralToIDMap.count(SamplerLiteral)) {
2114 Constant->print(errs());
2115 llvm_unreachable("Sampler literal was not found in sampler map!");
2116 }
2117
2118 // Calls to the sampler literal function to initialize a sampler are
2119 // re-routed to the global variables declared for the sampler.
2120 VMap[CI] = SamplerLiteralToIDMap[SamplerLiteral];
2121 }
2122 }
2123}
2124
2125void SPIRVProducerPass::GenerateGlobalVar(GlobalVariable &GV) {
2126 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2127 ValueMapType &VMap = getValueMap();
2128 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2129
2130 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
2131 Type *Ty = GV.getType();
2132 PointerType *PTy = cast<PointerType>(Ty);
2133
2134 uint32_t InitializerID = 0;
2135
2136 // Workgroup size is handled differently (it goes into a constant)
2137 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2138 std::vector<bool> HasMDVec;
2139 uint32_t PrevXDimCst = 0xFFFFFFFF;
2140 uint32_t PrevYDimCst = 0xFFFFFFFF;
2141 uint32_t PrevZDimCst = 0xFFFFFFFF;
2142 for (Function &Func : *GV.getParent()) {
2143 if (Func.isDeclaration()) {
2144 continue;
2145 }
2146
2147 // We only need to check kernels.
2148 if (Func.getCallingConv() != CallingConv::SPIR_KERNEL) {
2149 continue;
2150 }
2151
2152 if (const MDNode *MD =
2153 dyn_cast<Function>(&Func)->getMetadata("reqd_work_group_size")) {
2154 uint32_t CurXDimCst = static_cast<uint32_t>(
2155 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2156 uint32_t CurYDimCst = static_cast<uint32_t>(
2157 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2158 uint32_t CurZDimCst = static_cast<uint32_t>(
2159 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2160
2161 if (PrevXDimCst == 0xFFFFFFFF && PrevYDimCst == 0xFFFFFFFF &&
2162 PrevZDimCst == 0xFFFFFFFF) {
2163 PrevXDimCst = CurXDimCst;
2164 PrevYDimCst = CurYDimCst;
2165 PrevZDimCst = CurZDimCst;
2166 } else if (CurXDimCst != PrevXDimCst || CurYDimCst != PrevYDimCst ||
2167 CurZDimCst != PrevZDimCst) {
2168 llvm_unreachable(
2169 "reqd_work_group_size must be the same across all kernels");
2170 } else {
2171 continue;
2172 }
2173
2174 //
2175 // Generate OpConstantComposite.
2176 //
2177 // Ops[0] : Result Type ID
2178 // Ops[1] : Constant size for x dimension.
2179 // Ops[2] : Constant size for y dimension.
2180 // Ops[3] : Constant size for z dimension.
2181 SPIRVOperandList Ops;
2182
2183 uint32_t XDimCstID =
2184 VMap[mdconst::extract<ConstantInt>(MD->getOperand(0))];
2185 uint32_t YDimCstID =
2186 VMap[mdconst::extract<ConstantInt>(MD->getOperand(1))];
2187 uint32_t ZDimCstID =
2188 VMap[mdconst::extract<ConstantInt>(MD->getOperand(2))];
2189
2190 InitializerID = nextID;
2191
2192 Ops.push_back(
2193 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2194 lookupType(Ty->getPointerElementType())));
2195
2196 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XDimCstID));
2197 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, YDimCstID));
2198 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ZDimCstID));
2199
2200 SPIRVInstruction *Inst =
2201 new SPIRVInstruction(6, spv::OpConstantComposite, nextID++, Ops);
2202 SPIRVInstList.push_back(Inst);
2203
2204 HasMDVec.push_back(true);
2205 } else {
2206 HasMDVec.push_back(false);
2207 }
2208 }
2209
2210 // Check all kernels have same definitions for work_group_size.
2211 bool HasMD = false;
2212 if (!HasMDVec.empty()) {
2213 HasMD = HasMDVec[0];
2214 for (uint32_t i = 1; i < HasMDVec.size(); i++) {
2215 if (HasMD != HasMDVec[i]) {
2216 llvm_unreachable(
2217 "Kernels should have consistent work group size definition");
2218 }
2219 }
2220 }
2221
2222 // If all kernels do not have metadata for reqd_work_group_size, generate
2223 // OpSpecConstants for x/y/z dimension.
2224 if (!HasMD) {
2225 //
2226 // Generate OpSpecConstants for x/y/z dimension.
2227 //
2228 // Ops[0] : Result Type ID
2229 // Ops[1] : Constant size for x/y/z dimension (Literal Number).
2230 uint32_t XDimCstID = 0;
2231 uint32_t YDimCstID = 0;
2232 uint32_t ZDimCstID = 0;
2233
2234 // X Dimension
2235 SPIRVOperandList Ops;
2236
2237 Ops.push_back(new SPIRVOperand(
2238 SPIRVOperandType::NUMBERID,
2239 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2240
2241 std::vector<uint32_t> LiteralNum;
2242 LiteralNum.push_back(1);
2243 SPIRVOperand *XDim =
2244 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2245 Ops.push_back(XDim);
2246
2247 XDimCstID = nextID;
2248 BuiltinDimVec.push_back(XDimCstID);
2249
2250 SPIRVInstruction *XDimCstInst =
2251 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2252 SPIRVInstList.push_back(XDimCstInst);
2253
2254 // Y Dimension
2255 Ops.clear();
2256
2257 Ops.push_back(new SPIRVOperand(
2258 SPIRVOperandType::NUMBERID,
2259 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2260
2261 LiteralNum.clear();
2262 LiteralNum.push_back(1);
2263 SPIRVOperand *YDim =
2264 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2265 Ops.push_back(YDim);
2266
2267 YDimCstID = nextID;
2268 BuiltinDimVec.push_back(YDimCstID);
2269
2270 SPIRVInstruction *YDimCstInst =
2271 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2272 SPIRVInstList.push_back(YDimCstInst);
2273
2274 // Z Dimension
2275 Ops.clear();
2276
2277 Ops.push_back(new SPIRVOperand(
2278 SPIRVOperandType::NUMBERID,
2279 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2280
2281 LiteralNum.clear();
2282 LiteralNum.push_back(1);
2283 SPIRVOperand *ZDim =
2284 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2285 Ops.push_back(ZDim);
2286
2287 ZDimCstID = nextID;
2288 BuiltinDimVec.push_back(ZDimCstID);
2289
2290 SPIRVInstruction *ZDimCstInst =
2291 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2292 SPIRVInstList.push_back(ZDimCstInst);
2293
2294 //
2295 // Generate OpSpecConstantComposite.
2296 //
2297 // Ops[0] : Result Type ID
2298 // Ops[1] : Constant size for x dimension.
2299 // Ops[2] : Constant size for y dimension.
2300 // Ops[3] : Constant size for z dimension.
2301 InitializerID = nextID;
2302
2303 Ops.clear();
2304
2305 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
2306 lookupType(Ty->getPointerElementType())));
2307
2308 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XDimCstID));
2309 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, YDimCstID));
2310 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ZDimCstID));
2311
2312 SPIRVInstruction *Inst =
2313 new SPIRVInstruction(6, spv::OpSpecConstantComposite, nextID++, Ops);
2314 SPIRVInstList.push_back(Inst);
2315 }
2316 }
2317
2318 if (GV.hasInitializer()) {
2319 InitializerID = VMap[GV.getInitializer()];
2320 }
2321
2322 VMap[&GV] = nextID;
2323
2324 //
2325 // Generate OpVariable.
2326 //
2327 // GIDOps[0] : Result Type ID
2328 // GIDOps[1] : Storage Class
2329 SPIRVOperandList Ops;
2330
2331 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(Ty)));
2332
2333 spv::StorageClass StorageClass = GetStorageClass(PTy->getAddressSpace());
2334 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass));
2335
2336 if (0 != InitializerID) {
2337 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, InitializerID));
2338 }
2339
2340 SPIRVInstruction *Inst = new SPIRVInstruction(
2341 static_cast<uint16_t>(2 + Ops.size()), spv::OpVariable, nextID++, Ops);
2342 SPIRVInstList.push_back(Inst);
2343
2344 // If we have a builtin.
2345 if (spv::BuiltInMax != BuiltinType) {
2346 // Find Insert Point for OpDecorate.
2347 auto DecoInsertPoint =
2348 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2349 [](SPIRVInstruction *Inst) -> bool {
2350 return Inst->getOpcode() != spv::OpDecorate &&
2351 Inst->getOpcode() != spv::OpMemberDecorate &&
2352 Inst->getOpcode() != spv::OpExtInstImport;
2353 });
2354 //
2355 // Generate OpDecorate.
2356 //
2357 // DOps[0] = Target ID
2358 // DOps[1] = Decoration (Builtin)
2359 // DOps[2] = BuiltIn ID
2360 uint32_t ResultID;
2361
2362 // WorkgroupSize is different, we decorate the constant composite that has
2363 // its value, rather than the variable that we use to access the value.
2364 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2365 ResultID = InitializerID;
2366 } else {
2367 ResultID = VMap[&GV];
2368 }
2369
2370 SPIRVOperandList DOps;
2371 SPIRVOperand *ResultIDOp =
2372 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResultID);
2373 DOps.push_back(ResultIDOp);
2374
2375 spv::Decoration Deco = spv::DecorationBuiltIn;
2376 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2377 DOps.push_back(DecoOp);
2378
2379 SPIRVOperand *Builtin =
2380 new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinType);
2381 DOps.push_back(Builtin);
2382
2383 SPIRVInstruction *DescDecoInst =
2384 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, DOps);
2385 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2386 }
2387}
2388
2389void SPIRVProducerPass::GenerateFuncPrologue(Function &F) {
2390 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2391 ValueMapType &VMap = getValueMap();
2392 EntryPointVecType &EntryPoints = getEntryPointVec();
2393 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
2394 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
2395 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
2396 auto &GlobalConstArgSet = getGlobalConstArgSet();
David Netoc2c368d2017-06-30 16:50:17 -04002397 const DataLayout& dataLayout(F.getParent()->getDataLayout());
David Neto22f144c2017-06-12 14:26:21 -04002398
2399 FunctionType *FTy = F.getFunctionType();
2400
2401 //
2402 // Generate OpVariable and OpDecorate for kernel function with arguments.
2403 //
2404 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2405
2406 // Find Insert Point for OpDecorate.
2407 auto DecoInsertPoint =
2408 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2409 [](SPIRVInstruction *Inst) -> bool {
2410 return Inst->getOpcode() != spv::OpDecorate &&
2411 Inst->getOpcode() != spv::OpMemberDecorate &&
2412 Inst->getOpcode() != spv::OpExtInstImport;
2413 });
2414
2415 uint32_t DescriptorSetIdx = (0 < getSamplerMap().size()) ? 1u : 0u;
2416 for (Function &Func : *F.getParent()) {
2417 if (Func.isDeclaration()) {
2418 continue;
2419 }
2420
2421 if (Func.getCallingConv() == CallingConv::SPIR_KERNEL) {
2422 if (&Func == &F) {
2423 break;
2424 }
2425 DescriptorSetIdx++;
2426 }
2427 }
2428
David Neto156783e2017-07-05 15:39:41 -04002429 const auto *ArgMap = F.getMetadata("kernel_arg_map");
2430 // Emit descriptor map entries, if there was explicit metadata
2431 // attached.
2432 if (ArgMap) {
2433 for (const auto &arg : ArgMap->operands()) {
2434 const MDNode *arg_node = dyn_cast<MDNode>(arg.get());
2435 assert(arg_node->getNumOperands() == 4);
2436 const auto name =
2437 dyn_cast<MDString>(arg_node->getOperand(0))->getString();
2438 const auto old_index =
2439 dyn_extract<ConstantInt>(arg_node->getOperand(1))->getZExtValue();
2440 const auto new_index =
2441 dyn_extract<ConstantInt>(arg_node->getOperand(2))->getZExtValue();
2442 const auto offset =
2443 dyn_extract<ConstantInt>(arg_node->getOperand(3))->getZExtValue();
2444 descriptorMapOut << "kernel," << F.getName() << ",arg," << name
2445 << ",argOrdinal," << old_index << ",descriptorSet,"
2446 << DescriptorSetIdx << ",binding," << new_index
2447 << ",offset," << offset << "\n";
2448 }
2449 }
2450
David Neto22f144c2017-06-12 14:26:21 -04002451 uint32_t BindingIdx = 0;
2452 for (auto &Arg : F.args()) {
2453 Value *NewGV = ArgGVMap[&Arg];
2454 VMap[&Arg] = VMap[NewGV];
2455 ArgGVIDMap[&Arg] = VMap[&Arg];
2456
David Neto156783e2017-07-05 15:39:41 -04002457 // Emit a descriptor map entry for this arg, in case there was no explicit
2458 // kernel arg mapping metadata.
2459 if (!ArgMap) {
2460 descriptorMapOut << "kernel," << F.getName() << ",arg," << Arg.getName()
2461 << ",argOrdinal," << BindingIdx << ",descriptorSet,"
2462 << DescriptorSetIdx << ",binding," << BindingIdx
2463 << ",offset,0\n";
David Netoc2c368d2017-06-30 16:50:17 -04002464 }
2465
David Neto22f144c2017-06-12 14:26:21 -04002466 // Ops[0] = Target ID
2467 // Ops[1] = Decoration (DescriptorSet)
2468 // Ops[2] = LiteralNumber according to Decoration
2469 SPIRVOperandList Ops;
2470
2471 SPIRVOperand *ArgIDOp =
2472 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[&Arg]);
2473 Ops.push_back(ArgIDOp);
2474
2475 spv::Decoration Deco = spv::DecorationDescriptorSet;
2476 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2477 Ops.push_back(DecoOp);
2478
2479 std::vector<uint32_t> LiteralNum;
2480 LiteralNum.push_back(DescriptorSetIdx);
2481 SPIRVOperand *DescSet =
2482 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2483 Ops.push_back(DescSet);
2484
2485 SPIRVInstruction *DescDecoInst =
2486 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2487 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2488
2489 // Ops[0] = Target ID
2490 // Ops[1] = Decoration (Binding)
2491 // Ops[2] = LiteralNumber according to Decoration
2492 Ops.clear();
2493
2494 Ops.push_back(ArgIDOp);
2495
2496 Deco = spv::DecorationBinding;
2497 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2498 Ops.push_back(DecoOp);
2499
2500 LiteralNum.clear();
2501 LiteralNum.push_back(BindingIdx++);
2502 SPIRVOperand *Binding =
2503 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2504 Ops.push_back(Binding);
2505
2506 SPIRVInstruction *BindDecoInst =
2507 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2508 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2509
2510 // Handle image type argument.
2511 bool HasReadOnlyImageType = false;
2512 bool HasWriteOnlyImageType = false;
2513 if (PointerType *ArgPTy = dyn_cast<PointerType>(Arg.getType())) {
2514 if (StructType *STy = dyn_cast<StructType>(ArgPTy->getElementType())) {
2515 if (STy->isOpaque()) {
2516 if (STy->getName().equals("opencl.image2d_ro_t") ||
2517 STy->getName().equals("opencl.image3d_ro_t")) {
2518 HasReadOnlyImageType = true;
2519 } else if (STy->getName().equals("opencl.image2d_wo_t") ||
2520 STy->getName().equals("opencl.image3d_wo_t")) {
2521 HasWriteOnlyImageType = true;
2522 }
2523 }
2524 }
2525 }
2526
2527 if (HasReadOnlyImageType || HasWriteOnlyImageType) {
2528 // Ops[0] = Target ID
2529 // Ops[1] = Decoration (NonReadable or NonWritable)
2530 Ops.clear();
2531
2532 ArgIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[&Arg]);
2533 Ops.push_back(ArgIDOp);
2534
2535 Deco = spv::DecorationNonReadable;
2536 if (HasReadOnlyImageType) {
2537 Deco = spv::DecorationNonWritable;
2538 }
2539 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2540 Ops.push_back(DecoOp);
2541
2542 DescDecoInst =
2543 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
2544 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2545 }
2546
2547 // Handle const address space.
2548 if (NewGV->getType()->getPointerAddressSpace() ==
2549 AddressSpace::Constant) {
2550 // Ops[0] = Target ID
2551 // Ops[1] = Decoration (NonWriteable)
2552 Ops.clear();
2553
2554 Ops.push_back(ArgIDOp);
2555
2556 Deco = spv::DecorationNonWritable;
2557 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2558 Ops.push_back(DecoOp);
2559
2560 BindDecoInst =
2561 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
2562 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2563 }
2564 }
2565 }
2566
2567 //
2568 // Generate OPFunction.
2569 //
2570
2571 // FOps[0] : Result Type ID
2572 // FOps[1] : Function Control
2573 // FOps[2] : Function Type ID
2574 SPIRVOperandList FOps;
2575
2576 // Find SPIRV instruction for return type.
2577 uint32_t RetTyID = lookupType(FTy->getReturnType());
2578 SPIRVOperand *RetTyOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
2579 FOps.push_back(RetTyOp);
2580
2581 // Check function attributes for SPIRV Function Control.
2582 uint32_t FuncControl = spv::FunctionControlMaskNone;
2583 if (F.hasFnAttribute(Attribute::AlwaysInline)) {
2584 FuncControl |= spv::FunctionControlInlineMask;
2585 }
2586 if (F.hasFnAttribute(Attribute::NoInline)) {
2587 FuncControl |= spv::FunctionControlDontInlineMask;
2588 }
2589 // TODO: Check llvm attribute for Function Control Pure.
2590 if (F.hasFnAttribute(Attribute::ReadOnly)) {
2591 FuncControl |= spv::FunctionControlPureMask;
2592 }
2593 // TODO: Check llvm attribute for Function Control Const.
2594 if (F.hasFnAttribute(Attribute::ReadNone)) {
2595 FuncControl |= spv::FunctionControlConstMask;
2596 }
2597
2598 SPIRVOperand *FunctionControlOp =
2599 new SPIRVOperand(SPIRVOperandType::NUMBERID, FuncControl);
2600 FOps.push_back(FunctionControlOp);
2601
2602 uint32_t FTyID;
2603 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2604 SmallVector<Type *, 4> NewFuncParamTys;
2605 FunctionType *NewFTy =
2606 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
2607 FTyID = lookupType(NewFTy);
2608 } else {
2609 // Handle function with global constant parameters.
2610 if (GlobalConstFuncTyMap.count(FTy)) {
2611 FTyID = lookupType(GlobalConstFuncTyMap[FTy].first);
2612 } else {
2613 FTyID = lookupType(FTy);
2614 }
2615 }
2616
2617 SPIRVOperand *FTyOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, FTyID);
2618 FOps.push_back(FTyOp);
2619
2620 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2621 EntryPoints.push_back(std::make_pair(&F, nextID));
2622 }
2623
2624 VMap[&F] = nextID;
2625
2626 // Generate SPIRV instruction for function.
2627 SPIRVInstruction *FuncInst =
2628 new SPIRVInstruction(5, spv::OpFunction, nextID++, FOps);
2629 SPIRVInstList.push_back(FuncInst);
2630
2631 //
2632 // Generate OpFunctionParameter for Normal function.
2633 //
2634
2635 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
2636 // Iterate Argument for name instead of param type from function type.
2637 unsigned ArgIdx = 0;
2638 for (Argument &Arg : F.args()) {
2639 VMap[&Arg] = nextID;
2640
2641 // ParamOps[0] : Result Type ID
2642 SPIRVOperandList ParamOps;
2643
2644 // Find SPIRV instruction for parameter type.
2645 uint32_t ParamTyID = lookupType(Arg.getType());
2646 if (PointerType *PTy = dyn_cast<PointerType>(Arg.getType())) {
2647 if (GlobalConstFuncTyMap.count(FTy)) {
2648 if (ArgIdx == GlobalConstFuncTyMap[FTy].second) {
2649 Type *EleTy = PTy->getPointerElementType();
2650 Type *ArgTy =
2651 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
2652 ParamTyID = lookupType(ArgTy);
2653 GlobalConstArgSet.insert(&Arg);
2654 }
2655 }
2656 }
2657 SPIRVOperand *ParamTyOp =
2658 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParamTyID);
2659 ParamOps.push_back(ParamTyOp);
2660
2661 // Generate SPIRV instruction for parameter.
2662 SPIRVInstruction *ParamInst =
2663 new SPIRVInstruction(3, spv::OpFunctionParameter, nextID++, ParamOps);
2664 SPIRVInstList.push_back(ParamInst);
2665
2666 ArgIdx++;
2667 }
2668 }
2669}
2670
2671void SPIRVProducerPass::GenerateModuleInfo() {
2672 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2673 EntryPointVecType &EntryPoints = getEntryPointVec();
2674 ValueMapType &VMap = getValueMap();
2675 ValueList &EntryPointInterfaces = getEntryPointInterfacesVec();
2676 uint32_t &ExtInstImportID = getOpExtInstImportID();
2677 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2678
2679 // Set up insert point.
2680 auto InsertPoint = SPIRVInstList.begin();
2681
2682 //
2683 // Generate OpCapability
2684 //
2685 // TODO: Which llvm information is mapped to SPIRV Capapbility?
2686
2687 // Ops[0] = Capability
2688 SPIRVOperandList Ops;
2689
2690 SPIRVInstruction *CapInst = new SPIRVInstruction(
2691 2, spv::OpCapability, 0 /* No id */,
2692 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::CapabilityShader));
2693 SPIRVInstList.insert(InsertPoint, CapInst);
2694
2695 for (Type *Ty : getTypeList()) {
2696 // Find the i16 type.
2697 if (Ty->isIntegerTy(16)) {
2698 // Generate OpCapability for i16 type.
2699 SPIRVInstList.insert(
2700 InsertPoint,
2701 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2702 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2703 spv::CapabilityInt16)));
2704 } else if (Ty->isIntegerTy(64)) {
2705 // Generate OpCapability for i64 type.
2706 SPIRVInstList.insert(
2707 InsertPoint,
2708 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2709 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2710 spv::CapabilityInt64)));
2711 } else if (Ty->isHalfTy()) {
2712 // Generate OpCapability for half type.
2713 SPIRVInstList.insert(
2714 InsertPoint,
2715 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2716 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2717 spv::CapabilityFloat16)));
2718 } else if (Ty->isDoubleTy()) {
2719 // Generate OpCapability for double type.
2720 SPIRVInstList.insert(
2721 InsertPoint,
2722 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2723 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2724 spv::CapabilityFloat64)));
2725 } else if (auto *STy = dyn_cast<StructType>(Ty)) {
2726 if (STy->isOpaque()) {
David Neto565571c2017-08-21 12:00:05 -04002727 if (STy->getName().equals("opencl.image2d_wo_t") ||
2728 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -04002729 // Generate OpCapability for write only image type.
2730 SPIRVInstList.insert(
2731 InsertPoint,
2732 new SPIRVInstruction(
2733 2, spv::OpCapability, 0 /* No id */,
2734 new SPIRVOperand(
2735 SPIRVOperandType::NUMBERID,
2736 spv::CapabilityStorageImageWriteWithoutFormat)));
2737 }
2738 }
2739 }
2740 }
2741
2742 if (hasVariablePointers()) {
2743 //
2744 // Generate OpCapability and OpExtension
2745 //
2746
2747 //
2748 // Generate OpCapability.
2749 //
2750 // Ops[0] = Capability
2751 //
2752 Ops.clear();
2753
2754 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
2755 spv::CapabilityVariablePointers));
2756
2757 SPIRVInstList.insert(InsertPoint, new SPIRVInstruction(2, spv::OpCapability,
2758 0 /* No id */, Ops));
2759
2760 //
2761 // Generate OpExtension.
2762 //
2763 // Ops[0] = Name (Literal String)
2764 //
David Netoa772fd12017-08-04 14:17:33 -04002765 for (auto extension : {"SPV_KHR_storage_buffer_storage_class",
2766 "SPV_KHR_variable_pointers"}) {
2767 Ops.clear();
David Neto22f144c2017-06-12 14:26:21 -04002768
David Netoa772fd12017-08-04 14:17:33 -04002769 SPIRVOperand *Name =
2770 new SPIRVOperand(SPIRVOperandType::LITERAL_STRING, extension);
2771 Ops.push_back(Name);
David Neto22f144c2017-06-12 14:26:21 -04002772
David Netoa772fd12017-08-04 14:17:33 -04002773 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
2774 if ((Name->getLiteralStr().size() + 1) % 4) {
2775 NameWordSize += 1;
2776 }
2777
2778 assert((NameWordSize + 1) < UINT16_MAX);
2779 uint16_t WordCount = static_cast<uint16_t>(1 + NameWordSize);
2780
2781 SPIRVInstruction *ExtensionInst =
2782 new SPIRVInstruction(WordCount, spv::OpExtension, 0 /* No id */, Ops);
2783 SPIRVInstList.insert(InsertPoint, ExtensionInst);
David Neto22f144c2017-06-12 14:26:21 -04002784 }
David Neto22f144c2017-06-12 14:26:21 -04002785 }
2786
2787 if (ExtInstImportID) {
2788 ++InsertPoint;
2789 }
2790
2791 //
2792 // Generate OpMemoryModel
2793 //
2794 // Memory model for Vulkan will always be GLSL450.
2795
2796 // Ops[0] = Addressing Model
2797 // Ops[1] = Memory Model
2798 Ops.clear();
2799 SPIRVOperand *AddrModel =
2800 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::AddressingModelLogical);
2801 Ops.push_back(AddrModel);
2802
2803 SPIRVOperand *MemModel =
2804 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::MemoryModelGLSL450);
2805 Ops.push_back(MemModel);
2806
2807 SPIRVInstruction *MemModelInst =
2808 new SPIRVInstruction(3, spv::OpMemoryModel, 0 /* No id */, Ops);
2809 SPIRVInstList.insert(InsertPoint, MemModelInst);
2810
2811 //
2812 // Generate OpEntryPoint
2813 //
2814 for (auto EntryPoint : EntryPoints) {
2815 // Ops[0] = Execution Model
2816 // Ops[1] = EntryPoint ID
2817 // Ops[2] = Name (Literal String)
2818 // ...
2819 //
2820 // TODO: Do we need to consider Interface ID for forward references???
2821 Ops.clear();
2822 SPIRVOperand *ExecModel = new SPIRVOperand(SPIRVOperandType::NUMBERID,
2823 spv::ExecutionModelGLCompute);
2824 Ops.push_back(ExecModel);
2825
2826 SPIRVOperand *EntryPointID =
2827 new SPIRVOperand(SPIRVOperandType::NUMBERID, EntryPoint.second);
2828 Ops.push_back(EntryPointID);
2829
2830 SPIRVOperand *Name = new SPIRVOperand(SPIRVOperandType::LITERAL_STRING,
2831 EntryPoint.first->getName());
2832 Ops.push_back(Name);
2833
2834 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
2835 if ((Name->getLiteralStr().size() + 1) % 4) {
2836 NameWordSize += 1;
2837 }
2838
2839 assert((3 + NameWordSize) < UINT16_MAX);
2840 uint16_t WordCount = static_cast<uint16_t>(3 + NameWordSize);
2841
2842 for (Value *Interface : EntryPointInterfaces) {
2843 SPIRVOperand *GIDOp =
2844 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[Interface]);
2845 Ops.push_back(GIDOp);
2846 WordCount++;
2847 }
2848
2849 SPIRVInstruction *EntryPointInst =
2850 new SPIRVInstruction(WordCount, spv::OpEntryPoint, 0 /* No id */, Ops);
2851 SPIRVInstList.insert(InsertPoint, EntryPointInst);
2852 }
2853
2854 for (auto EntryPoint : EntryPoints) {
2855 if (const MDNode *MD = dyn_cast<Function>(EntryPoint.first)
2856 ->getMetadata("reqd_work_group_size")) {
2857
2858 if (!BuiltinDimVec.empty()) {
2859 llvm_unreachable(
2860 "Kernels should have consistent work group size definition");
2861 }
2862
2863 //
2864 // Generate OpExecutionMode
2865 //
2866
2867 // Ops[0] = Entry Point ID
2868 // Ops[1] = Execution Mode
2869 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
2870 Ops.clear();
2871 SPIRVOperand *EntryPointID =
2872 new SPIRVOperand(SPIRVOperandType::NUMBERID, EntryPoint.second);
2873 Ops.push_back(EntryPointID);
2874
2875 SPIRVOperand *ExecMode = new SPIRVOperand(SPIRVOperandType::NUMBERID,
2876 spv::ExecutionModeLocalSize);
2877 Ops.push_back(ExecMode);
2878
2879 uint32_t XDim = static_cast<uint32_t>(
2880 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2881 uint32_t YDim = static_cast<uint32_t>(
2882 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2883 uint32_t ZDim = static_cast<uint32_t>(
2884 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2885
2886 std::vector<uint32_t> LiteralNum;
2887 LiteralNum.push_back(XDim);
2888 SPIRVOperand *XDimOp =
2889 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2890 Ops.push_back(XDimOp);
2891
2892 LiteralNum.clear();
2893 LiteralNum.push_back(YDim);
2894 SPIRVOperand *YDimOp =
2895 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2896 Ops.push_back(YDimOp);
2897
2898 LiteralNum.clear();
2899 LiteralNum.push_back(ZDim);
2900 SPIRVOperand *ZDimOp =
2901 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2902 Ops.push_back(ZDimOp);
2903
2904 SPIRVInstruction *ExecModeInst =
2905 new SPIRVInstruction(static_cast<uint16_t>(1 + Ops.size()),
2906 spv::OpExecutionMode, 0 /* No id */, Ops);
2907 SPIRVInstList.insert(InsertPoint, ExecModeInst);
2908 }
2909 }
2910
2911 //
2912 // Generate OpSource.
2913 //
2914 // Ops[0] = SourceLanguage ID
2915 // Ops[1] = Version (LiteralNum)
2916 //
2917 Ops.clear();
2918 SPIRVOperand *SourceLanguage =
2919 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::SourceLanguageOpenCL_C);
2920 Ops.push_back(SourceLanguage);
2921
2922 std::vector<uint32_t> LiteralNum;
2923 LiteralNum.push_back(120);
2924 SPIRVOperand *Version =
2925 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2926 Ops.push_back(Version);
2927
2928 SPIRVInstruction *OpenSourceInst =
2929 new SPIRVInstruction(3, spv::OpSource, 0 /* No id */, Ops);
2930 SPIRVInstList.insert(InsertPoint, OpenSourceInst);
2931
2932 if (!BuiltinDimVec.empty()) {
2933 //
2934 // Generate OpDecorates for x/y/z dimension.
2935 //
2936 // Ops[0] = Target ID
2937 // Ops[1] = Decoration (SpecId)
2938 // Ops[2] = Specialization Cosntant ID (Literal Number)
2939
2940 // X Dimension
2941 Ops.clear();
2942
2943 SPIRVOperand *TargetID =
2944 new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[0]);
2945 Ops.push_back(TargetID);
2946
2947 SPIRVOperand *DecoOp =
2948 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
2949 Ops.push_back(DecoOp);
2950
2951 LiteralNum.clear();
2952 LiteralNum.push_back(0);
2953 SPIRVOperand *XDim =
2954 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2955 Ops.push_back(XDim);
2956
2957 SPIRVInstruction *XDimDecoInst =
2958 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2959 SPIRVInstList.insert(InsertPoint, XDimDecoInst);
2960
2961 // Y Dimension
2962 Ops.clear();
2963
2964 TargetID = new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[1]);
2965 Ops.push_back(TargetID);
2966
2967 DecoOp =
2968 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
2969 Ops.push_back(DecoOp);
2970
2971 LiteralNum.clear();
2972 LiteralNum.push_back(1);
2973 SPIRVOperand *YDim =
2974 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2975 Ops.push_back(YDim);
2976
2977 SPIRVInstruction *YDimDecoInst =
2978 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2979 SPIRVInstList.insert(InsertPoint, YDimDecoInst);
2980
2981 // Z Dimension
2982 Ops.clear();
2983
2984 TargetID = new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[2]);
2985 Ops.push_back(TargetID);
2986
2987 DecoOp =
2988 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
2989 Ops.push_back(DecoOp);
2990
2991 LiteralNum.clear();
2992 LiteralNum.push_back(2);
2993 SPIRVOperand *ZDim =
2994 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2995 Ops.push_back(ZDim);
2996
2997 SPIRVInstruction *ZDimDecoInst =
2998 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2999 SPIRVInstList.insert(InsertPoint, ZDimDecoInst);
3000 }
3001}
3002
3003void SPIRVProducerPass::GenerateInstForArg(Function &F) {
3004 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3005 ValueMapType &VMap = getValueMap();
3006 Module *Module = F.getParent();
3007 LLVMContext &Context = Module->getContext();
3008 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3009
3010 for (Argument &Arg : F.args()) {
3011 if (Arg.use_empty()) {
3012 continue;
3013 }
3014
3015 // Check the type of users of arguments.
3016 bool HasOnlyGEPUse = true;
3017 for (auto *U : Arg.users()) {
3018 if (!isa<GetElementPtrInst>(U) && isa<Instruction>(U)) {
3019 HasOnlyGEPUse = false;
3020 break;
3021 }
3022 }
3023
3024 Type *ArgTy = Arg.getType();
3025
3026 if (PointerType *PTy = dyn_cast<PointerType>(ArgTy)) {
3027 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType())) {
3028 if (STy->isOpaque()) {
3029 // Generate OpLoad for sampler and image types.
3030 if (STy->getName().equals("opencl.sampler_t") ||
3031 STy->getName().equals("opencl.image2d_ro_t") ||
3032 STy->getName().equals("opencl.image2d_wo_t") ||
3033 STy->getName().equals("opencl.image3d_ro_t") ||
3034 STy->getName().equals("opencl.image3d_wo_t")) {
3035 //
3036 // Generate OpLoad.
3037 //
3038 // Ops[0] = Result Type ID
3039 // Ops[1] = Pointer ID
3040 // Ops[2] ... Ops[n] = Optional Memory Access
3041 //
3042 // TODO: Do we need to implement Optional Memory Access???
3043 SPIRVOperandList Ops;
3044
3045 // Use type with address space modified.
3046 ArgTy = ArgGVMap[&Arg]->getType()->getPointerElementType();
3047
3048 uint32_t ResTyID = lookupType(ArgTy);
3049 SPIRVOperand *ResTyIDOp =
3050 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3051 Ops.push_back(ResTyIDOp);
3052
3053 uint32_t PointerID = VMap[&Arg];
3054 SPIRVOperand *PointerIDOp =
3055 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
3056 Ops.push_back(PointerIDOp);
3057
3058 VMap[&Arg] = nextID;
3059 SPIRVInstruction *Inst =
3060 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
3061 SPIRVInstList.push_back(Inst);
3062 continue;
3063 }
3064 }
3065 }
3066
3067 if (!HasOnlyGEPUse) {
3068 //
3069 // Generate OpAccessChain.
3070 //
3071 // Ops[0] = Result Type ID
3072 // Ops[1] = Base ID
3073 // Ops[2] ... Ops[n] = Indexes ID
3074 SPIRVOperandList Ops;
3075
3076 uint32_t ResTyID = lookupType(ArgTy);
3077 if (!isa<PointerType>(ArgTy)) {
3078 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3079 }
3080 SPIRVOperand *ResTyOp =
3081 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3082 Ops.push_back(ResTyOp);
3083
3084 uint32_t BaseID = VMap[&Arg];
3085 SPIRVOperand *BaseOp =
3086 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3087 Ops.push_back(BaseOp);
3088
3089 Type *IdxTy = Type::getInt32Ty(Context);
3090 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3091 SPIRVOperand *IndexIDOp =
3092 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3093 Ops.push_back(IndexIDOp);
3094 Ops.push_back(IndexIDOp);
3095
3096 // Generate SPIRV instruction for argument.
3097 VMap[&Arg] = nextID;
3098 SPIRVInstruction *ArgInst =
3099 new SPIRVInstruction(6, spv::OpAccessChain, nextID++, Ops);
3100 SPIRVInstList.push_back(ArgInst);
3101 } else {
3102 // For GEP uses, generate OpAccessChain with folding GEP ahead of GEP.
3103 // Nothing to do here.
3104 }
3105 } else {
3106 //
3107 // Generate OpAccessChain and OpLoad for non-pointer type argument.
3108 //
3109
3110 //
3111 // Generate OpAccessChain.
3112 //
3113 // Ops[0] = Result Type ID
3114 // Ops[1] = Base ID
3115 // Ops[2] ... Ops[n] = Indexes ID
3116 SPIRVOperandList Ops;
3117
3118 uint32_t ResTyID = lookupType(ArgTy);
3119 if (!isa<PointerType>(ArgTy)) {
3120 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3121 }
3122 SPIRVOperand *ResTyIDOp =
3123 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3124 Ops.push_back(ResTyIDOp);
3125
3126 uint32_t BaseID = VMap[&Arg];
3127 SPIRVOperand *BaseOp =
3128 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3129 Ops.push_back(BaseOp);
3130
3131 Type *IdxTy = Type::getInt32Ty(Context);
3132 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3133 SPIRVOperand *IndexIDOp =
3134 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3135 Ops.push_back(IndexIDOp);
3136
3137 // Generate SPIRV instruction for argument.
3138 uint32_t PointerID = nextID;
3139 VMap[&Arg] = nextID;
3140 SPIRVInstruction *ArgInst =
3141 new SPIRVInstruction(5, spv::OpAccessChain, nextID++, Ops);
3142 SPIRVInstList.push_back(ArgInst);
3143
3144 //
3145 // Generate OpLoad.
3146 //
3147
3148 // Ops[0] = Result Type ID
3149 // Ops[1] = Pointer ID
3150 // Ops[2] ... Ops[n] = Optional Memory Access
3151 //
3152 // TODO: Do we need to implement Optional Memory Access???
3153 Ops.clear();
3154
3155 ResTyID = lookupType(ArgTy);
3156 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3157 Ops.push_back(ResTyIDOp);
3158
3159 SPIRVOperand *PointerIDOp =
3160 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
3161 Ops.push_back(PointerIDOp);
3162
3163 VMap[&Arg] = nextID;
3164 SPIRVInstruction *Inst =
3165 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
3166 SPIRVInstList.push_back(Inst);
3167 }
3168 }
3169}
3170
3171void SPIRVProducerPass::GenerateFuncBody(Function &F) {
3172 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3173 ValueMapType &VMap = getValueMap();
3174
3175 bool IsKernel = false;
3176 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
3177 IsKernel = true;
3178 }
3179
3180 for (BasicBlock &BB : F) {
3181 // Register BasicBlock to ValueMap.
3182 VMap[&BB] = nextID;
3183
3184 //
3185 // Generate OpLabel for Basic Block.
3186 //
3187 SPIRVOperandList Ops;
3188 SPIRVInstruction *Inst =
3189 new SPIRVInstruction(2, spv::OpLabel, nextID++, Ops);
3190 SPIRVInstList.push_back(Inst);
3191
David Neto6dcd4712017-06-23 11:06:47 -04003192 // OpVariable instructions must come first.
3193 for (Instruction &I : BB) {
3194 if (isa<AllocaInst>(I)) {
3195 GenerateInstruction(I);
3196 }
3197 }
3198
David Neto22f144c2017-06-12 14:26:21 -04003199 if (&BB == &F.getEntryBlock() && IsKernel) {
3200 GenerateInstForArg(F);
3201 }
3202
3203 for (Instruction &I : BB) {
David Neto6dcd4712017-06-23 11:06:47 -04003204 if (!isa<AllocaInst>(I)) {
3205 GenerateInstruction(I);
3206 }
David Neto22f144c2017-06-12 14:26:21 -04003207 }
3208 }
3209}
3210
3211spv::Op SPIRVProducerPass::GetSPIRVCmpOpcode(CmpInst *I) {
3212 const std::map<CmpInst::Predicate, spv::Op> Map = {
3213 {CmpInst::ICMP_EQ, spv::OpIEqual},
3214 {CmpInst::ICMP_NE, spv::OpINotEqual},
3215 {CmpInst::ICMP_UGT, spv::OpUGreaterThan},
3216 {CmpInst::ICMP_UGE, spv::OpUGreaterThanEqual},
3217 {CmpInst::ICMP_ULT, spv::OpULessThan},
3218 {CmpInst::ICMP_ULE, spv::OpULessThanEqual},
3219 {CmpInst::ICMP_SGT, spv::OpSGreaterThan},
3220 {CmpInst::ICMP_SGE, spv::OpSGreaterThanEqual},
3221 {CmpInst::ICMP_SLT, spv::OpSLessThan},
3222 {CmpInst::ICMP_SLE, spv::OpSLessThanEqual},
3223 {CmpInst::FCMP_OEQ, spv::OpFOrdEqual},
3224 {CmpInst::FCMP_OGT, spv::OpFOrdGreaterThan},
3225 {CmpInst::FCMP_OGE, spv::OpFOrdGreaterThanEqual},
3226 {CmpInst::FCMP_OLT, spv::OpFOrdLessThan},
3227 {CmpInst::FCMP_OLE, spv::OpFOrdLessThanEqual},
3228 {CmpInst::FCMP_ONE, spv::OpFOrdNotEqual},
3229 {CmpInst::FCMP_UEQ, spv::OpFUnordEqual},
3230 {CmpInst::FCMP_UGT, spv::OpFUnordGreaterThan},
3231 {CmpInst::FCMP_UGE, spv::OpFUnordGreaterThanEqual},
3232 {CmpInst::FCMP_ULT, spv::OpFUnordLessThan},
3233 {CmpInst::FCMP_ULE, spv::OpFUnordLessThanEqual},
3234 {CmpInst::FCMP_UNE, spv::OpFUnordNotEqual}};
3235
3236 assert(0 != Map.count(I->getPredicate()));
3237
3238 return Map.at(I->getPredicate());
3239}
3240
3241spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
3242 const std::map<unsigned, spv::Op> Map{
3243 {Instruction::Trunc, spv::OpUConvert},
3244 {Instruction::ZExt, spv::OpUConvert},
3245 {Instruction::SExt, spv::OpSConvert},
3246 {Instruction::FPToUI, spv::OpConvertFToU},
3247 {Instruction::FPToSI, spv::OpConvertFToS},
3248 {Instruction::UIToFP, spv::OpConvertUToF},
3249 {Instruction::SIToFP, spv::OpConvertSToF},
3250 {Instruction::FPTrunc, spv::OpFConvert},
3251 {Instruction::FPExt, spv::OpFConvert},
3252 {Instruction::BitCast, spv::OpBitcast}};
3253
3254 assert(0 != Map.count(I.getOpcode()));
3255
3256 return Map.at(I.getOpcode());
3257}
3258
3259spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
3260 if (I.getType()->isIntegerTy(1)) {
3261 switch (I.getOpcode()) {
3262 default:
3263 break;
3264 case Instruction::Or:
3265 return spv::OpLogicalOr;
3266 case Instruction::And:
3267 return spv::OpLogicalAnd;
3268 case Instruction::Xor:
3269 return spv::OpLogicalNotEqual;
3270 }
3271 }
3272
3273 const std::map<unsigned, spv::Op> Map {
3274 {Instruction::Add, spv::OpIAdd},
3275 {Instruction::FAdd, spv::OpFAdd},
3276 {Instruction::Sub, spv::OpISub},
3277 {Instruction::FSub, spv::OpFSub},
3278 {Instruction::Mul, spv::OpIMul},
3279 {Instruction::FMul, spv::OpFMul},
3280 {Instruction::UDiv, spv::OpUDiv},
3281 {Instruction::SDiv, spv::OpSDiv},
3282 {Instruction::FDiv, spv::OpFDiv},
3283 {Instruction::URem, spv::OpUMod},
3284 {Instruction::SRem, spv::OpSRem},
3285 {Instruction::FRem, spv::OpFRem},
3286 {Instruction::Or, spv::OpBitwiseOr},
3287 {Instruction::Xor, spv::OpBitwiseXor},
3288 {Instruction::And, spv::OpBitwiseAnd},
3289 {Instruction::Shl, spv::OpShiftLeftLogical},
3290 {Instruction::LShr, spv::OpShiftRightLogical},
3291 {Instruction::AShr, spv::OpShiftRightArithmetic}};
3292
3293 assert(0 != Map.count(I.getOpcode()));
3294
3295 return Map.at(I.getOpcode());
3296}
3297
3298void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
3299 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3300 ValueMapType &VMap = getValueMap();
3301 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3302 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
3303 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
3304 LLVMContext &Context = I.getParent()->getParent()->getParent()->getContext();
3305
3306 // Register Instruction to ValueMap.
3307 if (0 == VMap[&I]) {
3308 VMap[&I] = nextID;
3309 }
3310
3311 switch (I.getOpcode()) {
3312 default: {
3313 if (Instruction::isCast(I.getOpcode())) {
3314 //
3315 // Generate SPIRV instructions for cast operators.
3316 //
3317
3318 auto OpTy = I.getOperand(0)->getType();
3319 // Handle zext, sext and uitofp with i1 type specially.
3320 if ((I.getOpcode() == Instruction::ZExt ||
3321 I.getOpcode() == Instruction::SExt ||
3322 I.getOpcode() == Instruction::UIToFP) &&
3323 (OpTy->isIntegerTy(1) ||
3324 (OpTy->isVectorTy() &&
3325 OpTy->getVectorElementType()->isIntegerTy(1)))) {
3326 //
3327 // Generate OpSelect.
3328 //
3329
3330 // Ops[0] = Result Type ID
3331 // Ops[1] = Condition ID
3332 // Ops[2] = True Constant ID
3333 // Ops[3] = False Constant ID
3334 SPIRVOperandList Ops;
3335
3336 uint32_t ResTyID = lookupType(I.getType());
3337 SPIRVOperand *ResTyIDOp =
3338 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3339 Ops.push_back(ResTyIDOp);
3340
3341 // TODO: zext's first operand should be compare instructions???
3342 uint32_t CondID = VMap[I.getOperand(0)];
3343 SPIRVOperand *CondIDOp =
3344 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3345 Ops.push_back(CondIDOp);
3346
3347 uint32_t TrueID = 0;
3348 if (I.getOpcode() == Instruction::ZExt) {
3349 APInt One(32, 1);
3350 TrueID = VMap[Constant::getIntegerValue(I.getType(), One)];
3351 } else if (I.getOpcode() == Instruction::SExt) {
3352 APInt MinusOne(32, UINT64_MAX, true);
3353 TrueID = VMap[Constant::getIntegerValue(I.getType(), MinusOne)];
3354 } else {
3355 TrueID = VMap[ConstantFP::get(Context, APFloat(1.0f))];
3356 }
3357 SPIRVOperand *TrueIDOp =
3358 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueID);
3359 Ops.push_back(TrueIDOp);
3360
3361 uint32_t FalseID = 0;
3362 if (I.getOpcode() == Instruction::ZExt) {
3363 FalseID = VMap[Constant::getNullValue(I.getType())];
3364 } else if (I.getOpcode() == Instruction::SExt) {
3365 FalseID = VMap[Constant::getNullValue(I.getType())];
3366 } else {
3367 FalseID = VMap[ConstantFP::get(Context, APFloat(0.0f))];
3368 }
3369 SPIRVOperand *FalseIDOp =
3370 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseID);
3371 Ops.push_back(FalseIDOp);
3372
3373 SPIRVInstruction *Inst =
3374 new SPIRVInstruction(6, spv::OpSelect, nextID++, Ops);
3375 SPIRVInstList.push_back(Inst);
3376 } else {
3377 // Ops[0] = Result Type ID
3378 // Ops[1] = Source Value ID
3379 SPIRVOperandList Ops;
3380
3381 uint32_t ResTyID = lookupType(I.getType());
3382 SPIRVOperand *ResTyIDOp =
3383 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3384 Ops.push_back(ResTyIDOp);
3385
3386 uint32_t SrcID = VMap[I.getOperand(0)];
3387 SPIRVOperand *SrcIDOp =
3388 new SPIRVOperand(SPIRVOperandType::NUMBERID, SrcID);
3389 Ops.push_back(SrcIDOp);
3390
3391 SPIRVInstruction *Inst =
3392 new SPIRVInstruction(4, GetSPIRVCastOpcode(I), nextID++, Ops);
3393 SPIRVInstList.push_back(Inst);
3394 }
3395 } else if (isa<BinaryOperator>(I)) {
3396 //
3397 // Generate SPIRV instructions for binary operators.
3398 //
3399
3400 // Handle xor with i1 type specially.
3401 if (I.getOpcode() == Instruction::Xor &&
3402 I.getType() == Type::getInt1Ty(Context) &&
3403 (isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
3404 //
3405 // Generate OpLogicalNot.
3406 //
3407 // Ops[0] = Result Type ID
3408 // Ops[1] = Operand
3409 SPIRVOperandList Ops;
3410
3411 uint32_t ResTyID = lookupType(I.getType());
3412 SPIRVOperand *ResTyIDOp =
3413 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3414 Ops.push_back(ResTyIDOp);
3415
3416 Value *CondV = I.getOperand(0);
3417 if (isa<Constant>(I.getOperand(0))) {
3418 CondV = I.getOperand(1);
3419 }
3420 uint32_t CondID = VMap[CondV];
3421 SPIRVOperand *CondIDOp =
3422 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3423 Ops.push_back(CondIDOp);
3424
3425 SPIRVInstruction *Inst =
3426 new SPIRVInstruction(4, spv::OpLogicalNot, nextID++, Ops);
3427 SPIRVInstList.push_back(Inst);
3428 } else {
3429 // Ops[0] = Result Type ID
3430 // Ops[1] = Operand 0
3431 // Ops[2] = Operand 1
3432 SPIRVOperandList Ops;
3433
3434 uint32_t ResTyID = lookupType(I.getType());
3435 SPIRVOperand *ResTyIDOp =
3436 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3437 Ops.push_back(ResTyIDOp);
3438
3439 uint32_t Op0ID = VMap[I.getOperand(0)];
3440 SPIRVOperand *Op0IDOp =
3441 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3442 Ops.push_back(Op0IDOp);
3443
3444 uint32_t Op1ID = VMap[I.getOperand(1)];
3445 SPIRVOperand *Op1IDOp =
3446 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3447 Ops.push_back(Op1IDOp);
3448
3449 SPIRVInstruction *Inst =
3450 new SPIRVInstruction(5, GetSPIRVBinaryOpcode(I), nextID++, Ops);
3451 SPIRVInstList.push_back(Inst);
3452 }
3453 } else {
3454 I.print(errs());
3455 llvm_unreachable("Unsupported instruction???");
3456 }
3457 break;
3458 }
3459 case Instruction::GetElementPtr: {
3460 auto &GlobalConstArgSet = getGlobalConstArgSet();
3461
3462 //
3463 // Generate OpAccessChain.
3464 //
3465 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&I);
3466
3467 //
3468 // Generate OpAccessChain.
3469 //
3470
3471 // Ops[0] = Result Type ID
3472 // Ops[1] = Base ID
3473 // Ops[2] ... Ops[n] = Indexes ID
3474 SPIRVOperandList Ops;
3475
David Neto1a1a0582017-07-07 12:01:44 -04003476 PointerType* ResultType = cast<PointerType>(GEP->getType());
David Neto22f144c2017-06-12 14:26:21 -04003477 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate ||
3478 GlobalConstArgSet.count(GEP->getPointerOperand())) {
3479 // Use pointer type with private address space for global constant.
3480 Type *EleTy = I.getType()->getPointerElementType();
David Neto1a1a0582017-07-07 12:01:44 -04003481 ResultType = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
David Neto22f144c2017-06-12 14:26:21 -04003482 }
David Neto1a1a0582017-07-07 12:01:44 -04003483 const uint32_t ResTyID = lookupType(ResultType);
David Neto22f144c2017-06-12 14:26:21 -04003484 SPIRVOperand *ResTyIDOp =
3485 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3486 Ops.push_back(ResTyIDOp);
3487
3488 // Check whether GEP's pointer operand is pointer argument.
3489 bool HasArgBasePointer = false;
3490 for (auto ArgGV : ArgGVMap) {
3491 if (ArgGV.first == GEP->getPointerOperand()) {
3492 if (isa<PointerType>(ArgGV.first->getType())) {
3493 HasArgBasePointer = true;
3494 } else {
3495 llvm_unreachable(
3496 "GEP's pointer operand is argument of non-poninter type???");
3497 }
3498 }
3499 }
3500
3501 uint32_t BaseID;
3502 if (HasArgBasePointer) {
3503 // Point to global variable for argument directly.
3504 BaseID = ArgGVIDMap[GEP->getPointerOperand()];
3505 } else {
3506 BaseID = VMap[GEP->getPointerOperand()];
3507 }
3508
3509 SPIRVOperand *BaseIDOp =
3510 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3511 Ops.push_back(BaseIDOp);
3512
3513 uint16_t WordCount = 4;
3514
3515 if (HasArgBasePointer) {
3516 // If GEP's pointer operand is argument, add one more index for struct
3517 // type to wrap up argument type.
3518 Type *IdxTy = Type::getInt32Ty(Context);
3519 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3520 SPIRVOperand *IndexIDOp =
3521 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3522 Ops.push_back(IndexIDOp);
3523
3524 WordCount++;
3525 }
3526
3527 //
3528 // Follows below rules for gep.
3529 //
3530 // 1. If gep's first index is 0 and gep's base is not kernel function's
3531 // argument, generate OpAccessChain and ignore gep's first index.
3532 // 2. If gep's first index is not 0, generate OpPtrAccessChain and use gep's
3533 // first index.
3534 // 3. If gep's first index is not constant, generate OpPtrAccessChain and
3535 // use gep's first index.
3536 // 4. If it is not above case 1, 2 and 3, generate OpAccessChain and use
3537 // gep's first index.
3538 //
3539 spv::Op Opcode = spv::OpAccessChain;
3540 unsigned offset = 0;
3541 if (ConstantInt *CstInt = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
3542 if (CstInt->getZExtValue() == 0 && !HasArgBasePointer) {
3543 offset = 1;
3544 } else if (CstInt->getZExtValue() != 0 && !HasArgBasePointer) {
3545 Opcode = spv::OpPtrAccessChain;
David Neto22f144c2017-06-12 14:26:21 -04003546 }
3547 } else if (!HasArgBasePointer) {
3548 Opcode = spv::OpPtrAccessChain;
David Neto1a1a0582017-07-07 12:01:44 -04003549 }
3550
3551 if (Opcode == spv::OpPtrAccessChain) {
David Neto22f144c2017-06-12 14:26:21 -04003552 setVariablePointers(true);
David Neto1a1a0582017-07-07 12:01:44 -04003553 // Do we need to generate ArrayStride? Check against the GEP result type
3554 // rather than the pointer type of the base because when indexing into
3555 // an OpenCL program-scope constant, we'll swap out the LLVM base pointer
3556 // for something else in the SPIR-V.
3557 // E.g. see test/PointerAccessChain/pointer_index_is_constant_1.cl
3558 if (GetStorageClass(ResultType->getAddressSpace()) ==
3559 spv::StorageClassStorageBuffer) {
3560 // Save the need to generate an ArrayStride decoration. But defer
3561 // generation until later, so we only make one decoration.
3562 getPointerTypesNeedingArrayStride().insert(ResultType);
3563 }
David Neto22f144c2017-06-12 14:26:21 -04003564 }
3565
3566 for (auto II = GEP->idx_begin() + offset; II != GEP->idx_end(); II++) {
3567 uint32_t IndexID = VMap[*II];
3568 SPIRVOperand *IndexIDOp =
3569 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3570 Ops.push_back(IndexIDOp);
3571
3572 WordCount++;
3573 }
3574
3575 SPIRVInstruction *Inst =
3576 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
3577 SPIRVInstList.push_back(Inst);
3578 break;
3579 }
3580 case Instruction::ExtractValue: {
3581 ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
3582 // Ops[0] = Result Type ID
3583 // Ops[1] = Composite ID
3584 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3585 SPIRVOperandList Ops;
3586
3587 uint32_t ResTyID = lookupType(I.getType());
3588 SPIRVOperand *ResTyIDOp =
3589 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3590 Ops.push_back(ResTyIDOp);
3591
3592 uint32_t CompositeID = VMap[EVI->getAggregateOperand()];
3593 SPIRVOperand *CompositeIDOp =
3594 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3595 Ops.push_back(CompositeIDOp);
3596
3597 for (auto &Index : EVI->indices()) {
3598 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, Index));
3599 }
3600
3601 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
3602 SPIRVInstruction *Inst =
3603 new SPIRVInstruction(WordCount, spv::OpCompositeExtract, nextID++, Ops);
3604 SPIRVInstList.push_back(Inst);
3605 break;
3606 }
3607 case Instruction::InsertValue: {
3608 InsertValueInst *IVI = cast<InsertValueInst>(&I);
3609 // Ops[0] = Result Type ID
3610 // Ops[1] = Object ID
3611 // Ops[2] = Composite ID
3612 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3613 SPIRVOperandList Ops;
3614
3615 uint32_t ResTyID = lookupType(I.getType());
3616 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID));
3617
3618 uint32_t ObjectID = VMap[IVI->getInsertedValueOperand()];
3619 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID));
3620
3621 uint32_t CompositeID = VMap[IVI->getAggregateOperand()];
3622 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID));
3623
3624 for (auto &Index : IVI->indices()) {
3625 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, Index));
3626 }
3627
3628 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
3629 SPIRVInstruction *Inst =
3630 new SPIRVInstruction(WordCount, spv::OpCompositeInsert, nextID++, Ops);
3631 SPIRVInstList.push_back(Inst);
3632 break;
3633 }
3634 case Instruction::Select: {
3635 //
3636 // Generate OpSelect.
3637 //
3638
3639 // Ops[0] = Result Type ID
3640 // Ops[1] = Condition ID
3641 // Ops[2] = True Constant ID
3642 // Ops[3] = False Constant ID
3643 SPIRVOperandList Ops;
3644
3645 // Find SPIRV instruction for parameter type.
3646 auto Ty = I.getType();
3647 if (Ty->isPointerTy()) {
3648 auto PointeeTy = Ty->getPointerElementType();
3649 if (PointeeTy->isStructTy() &&
3650 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
3651 Ty = PointeeTy;
3652 }
3653 }
3654
3655 uint32_t ResTyID = lookupType(Ty);
3656 SPIRVOperand *ResTyIDOp =
3657 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3658 Ops.push_back(ResTyIDOp);
3659
3660 uint32_t CondID = VMap[I.getOperand(0)];
3661 SPIRVOperand *CondIDOp =
3662 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3663 Ops.push_back(CondIDOp);
3664
3665 uint32_t TrueID = VMap[I.getOperand(1)];
3666 SPIRVOperand *TrueIDOp =
3667 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueID);
3668 Ops.push_back(TrueIDOp);
3669
3670 uint32_t FalseID = VMap[I.getOperand(2)];
3671 SPIRVOperand *FalseIDOp =
3672 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseID);
3673 Ops.push_back(FalseIDOp);
3674
3675 SPIRVInstruction *Inst =
3676 new SPIRVInstruction(6, spv::OpSelect, nextID++, Ops);
3677 SPIRVInstList.push_back(Inst);
3678 break;
3679 }
3680 case Instruction::ExtractElement: {
3681 // Handle <4 x i8> type manually.
3682 Type *CompositeTy = I.getOperand(0)->getType();
3683 if (is4xi8vec(CompositeTy)) {
3684 //
3685 // Generate OpShiftRightLogical and OpBitwiseAnd for extractelement with
3686 // <4 x i8>.
3687 //
3688
3689 //
3690 // Generate OpShiftRightLogical
3691 //
3692 // Ops[0] = Result Type ID
3693 // Ops[1] = Operand 0
3694 // Ops[2] = Operand 1
3695 //
3696 SPIRVOperandList Ops;
3697
3698 uint32_t ResTyID = lookupType(CompositeTy);
3699 SPIRVOperand *ResTyIDOp =
3700 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3701 Ops.push_back(ResTyIDOp);
3702
3703 uint32_t Op0ID = VMap[I.getOperand(0)];
3704 SPIRVOperand *Op0IDOp =
3705 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3706 Ops.push_back(Op0IDOp);
3707
3708 uint32_t Op1ID = 0;
3709 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3710 // Handle constant index.
3711 uint64_t Idx = CI->getZExtValue();
3712 Value *ShiftAmount =
3713 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3714 Op1ID = VMap[ShiftAmount];
3715 } else {
3716 // Handle variable index.
3717 SPIRVOperandList TmpOps;
3718
3719 uint32_t TmpResTyID = lookupType(Type::getInt32Ty(Context));
3720 SPIRVOperand *TmpResTyIDOp =
3721 new SPIRVOperand(SPIRVOperandType::NUMBERID, TmpResTyID);
3722 TmpOps.push_back(TmpResTyIDOp);
3723
3724 uint32_t IdxID = VMap[I.getOperand(1)];
3725 SPIRVOperand *TmpOp0IDOp =
3726 new SPIRVOperand(SPIRVOperandType::NUMBERID, IdxID);
3727 TmpOps.push_back(TmpOp0IDOp);
3728
3729 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
3730 uint32_t Cst8ID = VMap[Cst8];
3731 SPIRVOperand *TmpOp1IDOp =
3732 new SPIRVOperand(SPIRVOperandType::NUMBERID, Cst8ID);
3733 TmpOps.push_back(TmpOp1IDOp);
3734
3735 Op1ID = nextID;
3736
3737 SPIRVInstruction *TmpInst =
3738 new SPIRVInstruction(5, spv::OpIMul, nextID++, TmpOps);
3739 SPIRVInstList.push_back(TmpInst);
3740 }
3741 SPIRVOperand *Op1IDOp =
3742 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3743 Ops.push_back(Op1IDOp);
3744
3745 uint32_t ShiftID = nextID;
3746
3747 SPIRVInstruction *Inst =
3748 new SPIRVInstruction(5, spv::OpShiftRightLogical, nextID++, Ops);
3749 SPIRVInstList.push_back(Inst);
3750
3751 //
3752 // Generate OpBitwiseAnd
3753 //
3754 // Ops[0] = Result Type ID
3755 // Ops[1] = Operand 0
3756 // Ops[2] = Operand 1
3757 //
3758 Ops.clear();
3759
3760 ResTyID = lookupType(CompositeTy);
3761 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3762 Ops.push_back(ResTyIDOp);
3763
3764 Op0ID = ShiftID;
3765 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3766 Ops.push_back(Op0IDOp);
3767
3768 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3769 Op1ID = VMap[CstFF];
3770 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3771 Ops.push_back(Op1IDOp);
3772
3773 Inst = new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
3774 SPIRVInstList.push_back(Inst);
3775 break;
3776 }
3777
3778 // Ops[0] = Result Type ID
3779 // Ops[1] = Composite ID
3780 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3781 SPIRVOperandList Ops;
3782
3783 uint32_t ResTyID = lookupType(I.getType());
3784 SPIRVOperand *ResTyIDOp =
3785 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3786 Ops.push_back(ResTyIDOp);
3787
3788 uint32_t CompositeID = VMap[I.getOperand(0)];
3789 SPIRVOperand *CompositeIDOp =
3790 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3791 Ops.push_back(CompositeIDOp);
3792
3793 spv::Op Opcode = spv::OpCompositeExtract;
3794 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3795 std::vector<uint32_t> LiteralNum;
3796 assert(CI->getZExtValue() < UINT32_MAX);
3797 LiteralNum.push_back(static_cast<uint32_t>(CI->getZExtValue()));
3798 SPIRVOperand *Indexes =
3799 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3800 Ops.push_back(Indexes);
3801 } else {
3802 uint32_t IndexID = VMap[I.getOperand(1)];
3803 SPIRVOperand *IndexIDOp =
3804 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3805 Ops.push_back(IndexIDOp);
3806 Opcode = spv::OpVectorExtractDynamic;
3807 }
3808
3809 uint16_t WordCount = 5;
3810 SPIRVInstruction *Inst =
3811 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
3812 SPIRVInstList.push_back(Inst);
3813 break;
3814 }
3815 case Instruction::InsertElement: {
3816 // Handle <4 x i8> type manually.
3817 Type *CompositeTy = I.getOperand(0)->getType();
3818 if (is4xi8vec(CompositeTy)) {
3819 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3820 uint32_t CstFFID = VMap[CstFF];
3821
3822 uint32_t ShiftAmountID = 0;
3823 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
3824 // Handle constant index.
3825 uint64_t Idx = CI->getZExtValue();
3826 Value *ShiftAmount =
3827 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3828 ShiftAmountID = VMap[ShiftAmount];
3829 } else {
3830 // Handle variable index.
3831 SPIRVOperandList TmpOps;
3832
3833 uint32_t TmpResTyID = lookupType(Type::getInt32Ty(Context));
3834 SPIRVOperand *TmpResTyIDOp =
3835 new SPIRVOperand(SPIRVOperandType::NUMBERID, TmpResTyID);
3836 TmpOps.push_back(TmpResTyIDOp);
3837
3838 uint32_t IdxID = VMap[I.getOperand(2)];
3839 SPIRVOperand *TmpOp0IDOp =
3840 new SPIRVOperand(SPIRVOperandType::NUMBERID, IdxID);
3841 TmpOps.push_back(TmpOp0IDOp);
3842
3843 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
3844 uint32_t Cst8ID = VMap[Cst8];
3845 SPIRVOperand *TmpOp1IDOp =
3846 new SPIRVOperand(SPIRVOperandType::NUMBERID, Cst8ID);
3847 TmpOps.push_back(TmpOp1IDOp);
3848
3849 ShiftAmountID = nextID;
3850
3851 SPIRVInstruction *TmpInst =
3852 new SPIRVInstruction(5, spv::OpIMul, nextID++, TmpOps);
3853 SPIRVInstList.push_back(TmpInst);
3854 }
3855
3856 //
3857 // Generate mask operations.
3858 //
3859
3860 // ShiftLeft mask according to index of insertelement.
3861 SPIRVOperandList Ops;
3862
3863 uint32_t ResTyID = lookupType(CompositeTy);
3864 SPIRVOperand *ResTyIDOp =
3865 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3866 Ops.push_back(ResTyIDOp);
3867
3868 uint32_t Op0ID = CstFFID;
3869 SPIRVOperand *Op0IDOp =
3870 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3871 Ops.push_back(Op0IDOp);
3872
3873 uint32_t Op1ID = ShiftAmountID;
3874 SPIRVOperand *Op1IDOp =
3875 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3876 Ops.push_back(Op1IDOp);
3877
3878 uint32_t MaskID = nextID;
3879
3880 SPIRVInstruction *Inst =
3881 new SPIRVInstruction(5, spv::OpShiftLeftLogical, nextID++, Ops);
3882 SPIRVInstList.push_back(Inst);
3883
3884 // Inverse mask.
3885 Ops.clear();
3886
3887 Ops.push_back(ResTyIDOp);
3888
3889 Op0ID = MaskID;
3890 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3891 Ops.push_back(Op0IDOp);
3892
3893 uint32_t InvMaskID = nextID;
3894
3895 Inst = new SPIRVInstruction(4, spv::OpLogicalNot, nextID++, Ops);
3896 SPIRVInstList.push_back(Inst);
3897
3898 // Apply mask.
3899 Ops.clear();
3900
3901 Ops.push_back(ResTyIDOp);
3902
3903 Op0ID = VMap[I.getOperand(0)];
3904 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3905 Ops.push_back(Op0IDOp);
3906
3907 Op1ID = InvMaskID;
3908 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3909 Ops.push_back(Op1IDOp);
3910
3911 uint32_t OrgValID = nextID;
3912
3913 Inst = new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
3914 SPIRVInstList.push_back(Inst);
3915
3916 // Create correct value according to index of insertelement.
3917 Ops.clear();
3918
3919 Ops.push_back(ResTyIDOp);
3920
3921 Op0ID = VMap[I.getOperand(1)];
3922 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3923 Ops.push_back(Op0IDOp);
3924
3925 Op1ID = ShiftAmountID;
3926 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3927 Ops.push_back(Op1IDOp);
3928
3929 uint32_t InsertValID = nextID;
3930
3931 Inst = new SPIRVInstruction(5, spv::OpShiftLeftLogical, nextID++, Ops);
3932 SPIRVInstList.push_back(Inst);
3933
3934 // Insert value to original value.
3935 Ops.clear();
3936
3937 Ops.push_back(ResTyIDOp);
3938
3939 Op0ID = OrgValID;
3940 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3941 Ops.push_back(Op0IDOp);
3942
3943 Op1ID = InsertValID;
3944 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3945 Ops.push_back(Op1IDOp);
3946
3947 Inst = new SPIRVInstruction(5, spv::OpBitwiseOr, nextID++, Ops);
3948 SPIRVInstList.push_back(Inst);
3949
3950 break;
3951 }
3952
3953 // Ops[0] = Result Type ID
3954 // Ops[1] = Object ID
3955 // Ops[2] = Composite ID
3956 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3957 SPIRVOperandList Ops;
3958
3959 uint32_t ResTyID = lookupType(I.getType());
3960 SPIRVOperand *ResTyIDOp =
3961 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3962 Ops.push_back(ResTyIDOp);
3963
3964 uint32_t ObjectID = VMap[I.getOperand(1)];
3965 SPIRVOperand *ObjectIDOp =
3966 new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID);
3967 Ops.push_back(ObjectIDOp);
3968
3969 uint32_t CompositeID = VMap[I.getOperand(0)];
3970 SPIRVOperand *CompositeIDOp =
3971 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3972 Ops.push_back(CompositeIDOp);
3973
3974 spv::Op Opcode = spv::OpCompositeInsert;
3975 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
3976 std::vector<uint32_t> LiteralNum;
3977 assert(CI->getZExtValue() < UINT32_MAX);
3978 LiteralNum.push_back(static_cast<uint32_t>(CI->getZExtValue()));
3979 SPIRVOperand *Indexes =
3980 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3981 Ops.push_back(Indexes);
3982 } else {
3983 uint32_t IndexID = VMap[I.getOperand(1)];
3984 SPIRVOperand *IndexIDOp =
3985 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3986 Ops.push_back(IndexIDOp);
3987 Opcode = spv::OpVectorInsertDynamic;
3988 }
3989
3990 uint16_t WordCount = 6;
3991 SPIRVInstruction *Inst =
3992 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
3993 SPIRVInstList.push_back(Inst);
3994 break;
3995 }
3996 case Instruction::ShuffleVector: {
3997 // Ops[0] = Result Type ID
3998 // Ops[1] = Vector 1 ID
3999 // Ops[2] = Vector 2 ID
4000 // Ops[3] ... Ops[n] = Components (Literal Number)
4001 SPIRVOperandList Ops;
4002
4003 uint32_t ResTyID = lookupType(I.getType());
4004 SPIRVOperand *ResTyIDOp =
4005 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4006 Ops.push_back(ResTyIDOp);
4007
4008 uint32_t Vec1ID = VMap[I.getOperand(0)];
4009 SPIRVOperand *Vec1IDOp =
4010 new SPIRVOperand(SPIRVOperandType::NUMBERID, Vec1ID);
4011 Ops.push_back(Vec1IDOp);
4012
4013 uint32_t Vec2ID = VMap[I.getOperand(1)];
4014 SPIRVOperand *Vec2IDOp =
4015 new SPIRVOperand(SPIRVOperandType::NUMBERID, Vec2ID);
4016 Ops.push_back(Vec2IDOp);
4017
4018 uint64_t NumElements = 0;
4019 if (Constant *Cst = dyn_cast<Constant>(I.getOperand(2))) {
4020 NumElements = cast<VectorType>(Cst->getType())->getNumElements();
4021
4022 if (Cst->isNullValue()) {
4023 for (unsigned i = 0; i < NumElements; i++) {
4024 std::vector<uint32_t> LiteralNum;
4025 LiteralNum.push_back(0);
4026 SPIRVOperand *Component =
4027 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4028 Ops.push_back(Component);
4029 }
4030 } else if (const ConstantDataSequential *CDS =
4031 dyn_cast<ConstantDataSequential>(Cst)) {
4032 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
4033 std::vector<uint32_t> LiteralNum;
4034 assert(CDS->getElementAsInteger(i) < UINT32_MAX);
4035 LiteralNum.push_back(
4036 static_cast<uint32_t>(CDS->getElementAsInteger(i)));
4037 SPIRVOperand *Component =
4038 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4039 Ops.push_back(Component);
4040 }
4041 } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(Cst)) {
4042 for (unsigned i = 0; i < CV->getNumOperands(); i++) {
4043 auto Op = CV->getOperand(i);
4044
4045 uint32_t literal = 0;
4046
4047 if (auto CI = dyn_cast<ConstantInt>(Op)) {
4048 literal = static_cast<uint32_t>(CI->getZExtValue());
4049 } else if (auto UI = dyn_cast<UndefValue>(Op)) {
4050 literal = 0xFFFFFFFFu;
4051 } else {
4052 Op->print(errs());
4053 llvm_unreachable("Unsupported element in ConstantVector!");
4054 }
4055
4056 std::vector<uint32_t> LiteralNum;
4057 LiteralNum.push_back(literal);
4058 SPIRVOperand *Component =
4059 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4060 Ops.push_back(Component);
4061 }
4062 } else {
4063 Cst->print(errs());
4064 llvm_unreachable("Unsupported constant mask in ShuffleVector!");
4065 }
4066 }
4067
4068 uint16_t WordCount = static_cast<uint16_t>(5 + NumElements);
4069 SPIRVInstruction *Inst =
4070 new SPIRVInstruction(WordCount, spv::OpVectorShuffle, nextID++, Ops);
4071 SPIRVInstList.push_back(Inst);
4072 break;
4073 }
4074 case Instruction::ICmp:
4075 case Instruction::FCmp: {
4076 CmpInst *CmpI = cast<CmpInst>(&I);
4077
4078 // Ops[0] = Result Type ID
4079 // Ops[1] = Operand 1 ID
4080 // Ops[2] = Operand 2 ID
4081 SPIRVOperandList Ops;
4082
4083 uint32_t ResTyID = lookupType(CmpI->getType());
4084 SPIRVOperand *ResTyIDOp =
4085 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4086 Ops.push_back(ResTyIDOp);
4087
David Netod4ca2e62017-07-06 18:47:35 -04004088 // Pointer equality is invalid.
4089 Type* ArgTy = CmpI->getOperand(0)->getType();
4090 if (isa<PointerType>(ArgTy)) {
4091 CmpI->print(errs());
4092 std::string name = I.getParent()->getParent()->getName();
4093 errs()
4094 << "\nPointer equality test is not supported by SPIR-V for Vulkan, "
4095 << "in function " << name << "\n";
4096 llvm_unreachable("Pointer equality check is invalid");
4097 break;
4098 }
4099
David Neto22f144c2017-06-12 14:26:21 -04004100 uint32_t Op1ID = VMap[CmpI->getOperand(0)];
4101 SPIRVOperand *Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4102 Ops.push_back(Op1IDOp);
4103
4104 uint32_t Op2ID = VMap[CmpI->getOperand(1)];
4105 SPIRVOperand *Op2IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op2ID);
4106 Ops.push_back(Op2IDOp);
4107
4108 spv::Op Opcode = GetSPIRVCmpOpcode(CmpI);
4109 SPIRVInstruction *Inst = new SPIRVInstruction(5, Opcode, nextID++, Ops);
4110 SPIRVInstList.push_back(Inst);
4111 break;
4112 }
4113 case Instruction::Br: {
4114 // Branch instrucion is deferred because it needs label's ID. Record slot's
4115 // location on SPIRVInstructionList.
4116 DeferredInsts.push_back(
4117 std::make_tuple(&I, --SPIRVInstList.end(), 0 /* No id */));
4118 break;
4119 }
4120 case Instruction::Switch: {
4121 I.print(errs());
4122 llvm_unreachable("Unsupported instruction???");
4123 break;
4124 }
4125 case Instruction::IndirectBr: {
4126 I.print(errs());
4127 llvm_unreachable("Unsupported instruction???");
4128 break;
4129 }
4130 case Instruction::PHI: {
4131 // Branch instrucion is deferred because it needs label's ID. Record slot's
4132 // location on SPIRVInstructionList.
4133 DeferredInsts.push_back(
4134 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4135 break;
4136 }
4137 case Instruction::Alloca: {
4138 //
4139 // Generate OpVariable.
4140 //
4141 // Ops[0] : Result Type ID
4142 // Ops[1] : Storage Class
4143 SPIRVOperandList Ops;
4144
4145 Type *ResTy = I.getType();
4146 uint32_t ResTyID = lookupType(ResTy);
4147 SPIRVOperand *ResTyOp =
4148 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4149 Ops.push_back(ResTyOp);
4150
4151 spv::StorageClass StorageClass = spv::StorageClassFunction;
4152 SPIRVOperand *StorageClassOp =
4153 new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass);
4154 Ops.push_back(StorageClassOp);
4155
4156 SPIRVInstruction *Inst =
4157 new SPIRVInstruction(4, spv::OpVariable, nextID++, Ops);
4158 SPIRVInstList.push_back(Inst);
4159 break;
4160 }
4161 case Instruction::Load: {
4162 LoadInst *LD = cast<LoadInst>(&I);
4163 //
4164 // Generate OpLoad.
4165 //
4166
4167 // Ops[0] = Result Type ID
4168 // Ops[1] = Pointer ID
4169 // Ops[2] ... Ops[n] = Optional Memory Access
4170 //
4171 // TODO: Do we need to implement Optional Memory Access???
4172 SPIRVOperandList Ops;
4173
4174 uint32_t ResTyID = lookupType(LD->getType());
4175 SPIRVOperand *ResTyIDOp =
4176 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4177 Ops.push_back(ResTyIDOp);
4178
4179 uint32_t PointerID = VMap[LD->getPointerOperand()];
4180 SPIRVOperand *PointerIDOp =
4181 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4182 Ops.push_back(PointerIDOp);
4183
4184 SPIRVInstruction *Inst =
4185 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
4186 SPIRVInstList.push_back(Inst);
4187 break;
4188 }
4189 case Instruction::Store: {
4190 StoreInst *ST = cast<StoreInst>(&I);
4191 //
4192 // Generate OpStore.
4193 //
4194
4195 // Ops[0] = Pointer ID
4196 // Ops[1] = Object ID
4197 // Ops[2] ... Ops[n] = Optional Memory Access (later???)
4198 //
4199 // TODO: Do we need to implement Optional Memory Access???
4200 SPIRVOperand *Ops[2] = {new SPIRVOperand(SPIRVOperandType::NUMBERID,
4201 VMap[ST->getPointerOperand()]),
4202 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4203 VMap[ST->getValueOperand()])};
4204
4205 SPIRVInstruction *Inst =
4206 new SPIRVInstruction(3, spv::OpStore, 0 /* No id */, Ops);
4207 SPIRVInstList.push_back(Inst);
4208 break;
4209 }
4210 case Instruction::AtomicCmpXchg: {
4211 I.print(errs());
4212 llvm_unreachable("Unsupported instruction???");
4213 break;
4214 }
4215 case Instruction::AtomicRMW: {
4216 I.print(errs());
4217 llvm_unreachable("Unsupported instruction???");
4218 break;
4219 }
4220 case Instruction::Fence: {
4221 I.print(errs());
4222 llvm_unreachable("Unsupported instruction???");
4223 break;
4224 }
4225 case Instruction::Call: {
4226 CallInst *Call = dyn_cast<CallInst>(&I);
4227 Function *Callee = Call->getCalledFunction();
4228
4229 // Sampler initializers become a load of the corresponding sampler.
4230 if (Callee->getName().equals("__translate_sampler_initializer")) {
4231 // Check that the sampler map was definitely used though.
4232 if (0 == getSamplerMap().size()) {
4233 llvm_unreachable("Sampler literal in source without sampler map!");
4234 }
4235
4236 SPIRVOperandList Ops;
4237
4238 uint32_t ResTyID = lookupType(SamplerTy->getPointerElementType());
4239 SPIRVOperand *ResTyIDOp =
4240 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4241 Ops.push_back(ResTyIDOp);
4242
4243 uint32_t PointerID = VMap[Call];
4244 SPIRVOperand *PointerIDOp =
4245 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4246 Ops.push_back(PointerIDOp);
4247
4248 VMap[Call] = nextID;
4249 SPIRVInstruction *Inst =
4250 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
4251 SPIRVInstList.push_back(Inst);
4252
4253 break;
4254 }
4255
4256 if (Callee->getName().startswith("spirv.atomic")) {
4257 spv::Op opcode = StringSwitch<spv::Op>(Callee->getName())
4258 .Case("spirv.atomic_add", spv::OpAtomicIAdd)
4259 .Case("spirv.atomic_sub", spv::OpAtomicISub)
4260 .Case("spirv.atomic_exchange", spv::OpAtomicExchange)
4261 .Case("spirv.atomic_inc", spv::OpAtomicIIncrement)
4262 .Case("spirv.atomic_dec", spv::OpAtomicIDecrement)
4263 .Case("spirv.atomic_compare_exchange",
4264 spv::OpAtomicCompareExchange)
4265 .Case("spirv.atomic_umin", spv::OpAtomicUMin)
4266 .Case("spirv.atomic_smin", spv::OpAtomicSMin)
4267 .Case("spirv.atomic_umax", spv::OpAtomicUMax)
4268 .Case("spirv.atomic_smax", spv::OpAtomicSMax)
4269 .Case("spirv.atomic_and", spv::OpAtomicAnd)
4270 .Case("spirv.atomic_or", spv::OpAtomicOr)
4271 .Case("spirv.atomic_xor", spv::OpAtomicXor)
4272 .Default(spv::OpNop);
4273
4274 //
4275 // Generate OpAtomic*.
4276 //
4277 SPIRVOperandList Ops;
4278
4279 uint32_t TyID = lookupType(I.getType());
4280 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4281
4282 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4283 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4284 VMap[Call->getArgOperand(i)]));
4285 }
4286
4287 VMap[&I] = nextID;
4288
4289 SPIRVInstruction *Inst = new SPIRVInstruction(
4290 static_cast<uint16_t>(2 + Ops.size()), opcode, nextID++, Ops);
4291 SPIRVInstList.push_back(Inst);
4292 break;
4293 }
4294
4295 if (Callee->getName().startswith("_Z3dot")) {
4296 // If the argument is a vector type, generate OpDot
4297 if (Call->getArgOperand(0)->getType()->isVectorTy()) {
4298 //
4299 // Generate OpDot.
4300 //
4301 SPIRVOperandList Ops;
4302
4303 uint32_t TyID = lookupType(I.getType());
4304 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4305
4306 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4307 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4308 VMap[Call->getArgOperand(i)]));
4309 }
4310
4311 VMap[&I] = nextID;
4312
4313 SPIRVInstruction *Inst = new SPIRVInstruction(
4314 static_cast<uint16_t>(2 + Ops.size()), spv::OpDot, nextID++, Ops);
4315 SPIRVInstList.push_back(Inst);
4316 } else {
4317 //
4318 // Generate OpFMul.
4319 //
4320 SPIRVOperandList Ops;
4321
4322 uint32_t TyID = lookupType(I.getType());
4323 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4324
4325 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4326 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4327 VMap[Call->getArgOperand(i)]));
4328 }
4329
4330 VMap[&I] = nextID;
4331
4332 SPIRVInstruction *Inst = new SPIRVInstruction(
4333 static_cast<uint16_t>(2 + Ops.size()), spv::OpFMul, nextID++, Ops);
4334 SPIRVInstList.push_back(Inst);
4335 }
4336 break;
4337 }
4338
4339 // spirv.store_null.* intrinsics become OpStore's.
4340 if (Callee->getName().startswith("spirv.store_null")) {
4341 //
4342 // Generate OpStore.
4343 //
4344
4345 // Ops[0] = Pointer ID
4346 // Ops[1] = Object ID
4347 // Ops[2] ... Ops[n]
4348 SPIRVOperandList Ops;
4349
4350 uint32_t PointerID = VMap[Call->getArgOperand(0)];
4351 SPIRVOperand *PointerIDOp =
4352 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4353 Ops.push_back(PointerIDOp);
4354
4355 uint32_t ObjectID = VMap[Call->getArgOperand(1)];
4356 SPIRVOperand *ObjectIDOp =
4357 new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID);
4358 Ops.push_back(ObjectIDOp);
4359
4360 SPIRVInstruction *Inst =
4361 new SPIRVInstruction(3, spv::OpStore, 0 /* No id */, Ops);
4362 SPIRVInstList.push_back(Inst);
4363
4364 break;
4365 }
4366
4367 // spirv.copy_memory.* intrinsics become OpMemoryMemory's.
4368 if (Callee->getName().startswith("spirv.copy_memory")) {
4369 //
4370 // Generate OpCopyMemory.
4371 //
4372
4373 // Ops[0] = Dst ID
4374 // Ops[1] = Src ID
4375 // Ops[2] = Memory Access
4376 // Ops[3] = Alignment
4377
4378 auto IsVolatile =
4379 dyn_cast<ConstantInt>(Call->getArgOperand(3))->getZExtValue() != 0;
4380
4381 auto VolatileMemoryAccess = (IsVolatile) ? spv::MemoryAccessVolatileMask
4382 : spv::MemoryAccessMaskNone;
4383
4384 auto MemoryAccess = VolatileMemoryAccess | spv::MemoryAccessAlignedMask;
4385
4386 auto Alignment =
4387 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4388
4389 SPIRVOperand *Ops[4] = {
4390 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4391 VMap[Call->getArgOperand(0)]),
4392 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4393 VMap[Call->getArgOperand(1)]),
4394 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, MemoryAccess),
4395 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER,
4396 static_cast<uint32_t>(Alignment))};
4397
4398 SPIRVInstruction *Inst =
4399 new SPIRVInstruction(5, spv::OpCopyMemory, 0 /* No id */, Ops);
4400
4401 SPIRVInstList.push_back(Inst);
4402
4403 break;
4404 }
4405
4406 // Nothing to do for abs with uint. Map abs's operand ID to VMap for abs
4407 // with unit.
4408 if (Callee->getName().equals("_Z3absj") ||
4409 Callee->getName().equals("_Z3absDv2_j") ||
4410 Callee->getName().equals("_Z3absDv3_j") ||
4411 Callee->getName().equals("_Z3absDv4_j")) {
4412 VMap[&I] = VMap[Call->getOperand(0)];
4413 break;
4414 }
4415
4416 // barrier is converted to OpControlBarrier
4417 if (Callee->getName().equals("__spirv_control_barrier")) {
4418 //
4419 // Generate OpControlBarrier.
4420 //
4421 // Ops[0] = Execution Scope ID
4422 // Ops[1] = Memory Scope ID
4423 // Ops[2] = Memory Semantics ID
4424 //
4425 Value *ExecutionScope = Call->getArgOperand(0);
4426 Value *MemoryScope = Call->getArgOperand(1);
4427 Value *MemorySemantics = Call->getArgOperand(2);
4428
4429 SPIRVOperand *Ops[3] = {
4430 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[ExecutionScope]),
4431 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[MemoryScope]),
4432 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[MemorySemantics])};
4433
4434 SPIRVInstList.push_back(
4435 new SPIRVInstruction(4, spv::OpControlBarrier, 0 /* No id */, Ops));
4436 break;
4437 }
4438
4439 // memory barrier is converted to OpMemoryBarrier
4440 if (Callee->getName().equals("__spirv_memory_barrier")) {
4441 //
4442 // Generate OpMemoryBarrier.
4443 //
4444 // Ops[0] = Memory Scope ID
4445 // Ops[1] = Memory Semantics ID
4446 //
4447 SPIRVOperandList Ops;
4448
4449 Value *MemoryScope = Call->getArgOperand(0);
4450 Value *MemorySemantics = Call->getArgOperand(1);
4451
4452 uint32_t MemoryScopeID = VMap[MemoryScope];
4453 Ops.push_back(
4454 new SPIRVOperand(SPIRVOperandType::NUMBERID, MemoryScopeID));
4455
4456 uint32_t MemorySemanticsID = VMap[MemorySemantics];
4457 Ops.push_back(
4458 new SPIRVOperand(SPIRVOperandType::NUMBERID, MemorySemanticsID));
4459
4460 SPIRVInstruction *Inst =
4461 new SPIRVInstruction(3, spv::OpMemoryBarrier, 0 /* No id */, Ops);
4462 SPIRVInstList.push_back(Inst);
4463 break;
4464 }
4465
4466 // isinf is converted to OpIsInf
4467 if (Callee->getName().equals("__spirv_isinff") ||
4468 Callee->getName().equals("__spirv_isinfDv2_f") ||
4469 Callee->getName().equals("__spirv_isinfDv3_f") ||
4470 Callee->getName().equals("__spirv_isinfDv4_f")) {
4471 //
4472 // Generate OpIsInf.
4473 //
4474 // Ops[0] = Result Type ID
4475 // Ops[1] = X ID
4476 //
4477 SPIRVOperandList Ops;
4478
4479 uint32_t TyID = lookupType(I.getType());
4480 SPIRVOperand *ResTyIDOp =
4481 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4482 Ops.push_back(ResTyIDOp);
4483
4484 uint32_t XID = VMap[Call->getArgOperand(0)];
4485 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XID));
4486
4487 VMap[&I] = nextID;
4488
4489 SPIRVInstruction *Inst =
4490 new SPIRVInstruction(4, spv::OpIsInf, nextID++, Ops);
4491 SPIRVInstList.push_back(Inst);
4492 break;
4493 }
4494
4495 // isnan is converted to OpIsNan
4496 if (Callee->getName().equals("__spirv_isnanf") ||
4497 Callee->getName().equals("__spirv_isnanDv2_f") ||
4498 Callee->getName().equals("__spirv_isnanDv3_f") ||
4499 Callee->getName().equals("__spirv_isnanDv4_f")) {
4500 //
4501 // Generate OpIsInf.
4502 //
4503 // Ops[0] = Result Type ID
4504 // Ops[1] = X ID
4505 //
4506 SPIRVOperandList Ops;
4507
4508 uint32_t TyID = lookupType(I.getType());
4509 SPIRVOperand *ResTyIDOp =
4510 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4511 Ops.push_back(ResTyIDOp);
4512
4513 uint32_t XID = VMap[Call->getArgOperand(0)];
4514 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XID));
4515
4516 VMap[&I] = nextID;
4517
4518 SPIRVInstruction *Inst =
4519 new SPIRVInstruction(4, spv::OpIsNan, nextID++, Ops);
4520 SPIRVInstList.push_back(Inst);
4521 break;
4522 }
4523
4524 // all is converted to OpAll
4525 if (Callee->getName().equals("__spirv_allDv2_i") ||
4526 Callee->getName().equals("__spirv_allDv3_i") ||
4527 Callee->getName().equals("__spirv_allDv4_i")) {
4528 //
4529 // Generate OpAll.
4530 //
4531 // Ops[0] = Result Type ID
4532 // Ops[1] = Vector ID
4533 //
4534 SPIRVOperandList Ops;
4535
4536 uint32_t TyID = lookupType(I.getType());
4537 SPIRVOperand *ResTyIDOp =
4538 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4539 Ops.push_back(ResTyIDOp);
4540
4541 uint32_t VectorID = VMap[Call->getArgOperand(0)];
4542 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, VectorID));
4543
4544 VMap[&I] = nextID;
4545
4546 SPIRVInstruction *Inst =
4547 new SPIRVInstruction(4, spv::OpAll, nextID++, Ops);
4548 SPIRVInstList.push_back(Inst);
4549 break;
4550 }
4551
4552 // any is converted to OpAny
4553 if (Callee->getName().equals("__spirv_anyDv2_i") ||
4554 Callee->getName().equals("__spirv_anyDv3_i") ||
4555 Callee->getName().equals("__spirv_anyDv4_i")) {
4556 //
4557 // Generate OpAny.
4558 //
4559 // Ops[0] = Result Type ID
4560 // Ops[1] = Vector ID
4561 //
4562 SPIRVOperandList Ops;
4563
4564 uint32_t TyID = lookupType(I.getType());
4565 SPIRVOperand *ResTyIDOp =
4566 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4567 Ops.push_back(ResTyIDOp);
4568
4569 uint32_t VectorID = VMap[Call->getArgOperand(0)];
4570 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, VectorID));
4571
4572 VMap[&I] = nextID;
4573
4574 SPIRVInstruction *Inst =
4575 new SPIRVInstruction(4, spv::OpAny, nextID++, Ops);
4576 SPIRVInstList.push_back(Inst);
4577 break;
4578 }
4579
4580 // read_image is converted to OpSampledImage and OpImageSampleExplicitLod.
4581 // Additionally, OpTypeSampledImage is generated.
4582 if (Callee->getName().equals(
4583 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
4584 Callee->getName().equals(
4585 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
4586 //
4587 // Generate OpSampledImage.
4588 //
4589 // Ops[0] = Result Type ID
4590 // Ops[1] = Image ID
4591 // Ops[2] = Sampler ID
4592 //
4593 SPIRVOperandList Ops;
4594
4595 Value *Image = Call->getArgOperand(0);
4596 Value *Sampler = Call->getArgOperand(1);
4597 Value *Coordinate = Call->getArgOperand(2);
4598
4599 TypeMapType &OpImageTypeMap = getImageTypeMap();
4600 Type *ImageTy = Image->getType()->getPointerElementType();
4601 uint32_t ImageTyID = OpImageTypeMap[ImageTy];
4602 SPIRVOperand *ResTyIDOp =
4603 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageTyID);
4604 Ops.push_back(ResTyIDOp);
4605
4606 uint32_t ImageID = VMap[Image];
4607 SPIRVOperand *ImageIDOp =
4608 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageID);
4609 Ops.push_back(ImageIDOp);
4610
4611 uint32_t SamplerID = VMap[Sampler];
4612 SPIRVOperand *SamplerIDOp =
4613 new SPIRVOperand(SPIRVOperandType::NUMBERID, SamplerID);
4614 Ops.push_back(SamplerIDOp);
4615
4616 uint32_t SampledImageID = nextID;
4617
4618 SPIRVInstruction *Inst =
4619 new SPIRVInstruction(5, spv::OpSampledImage, nextID++, Ops);
4620 SPIRVInstList.push_back(Inst);
4621
4622 //
4623 // Generate OpImageSampleExplicitLod.
4624 //
4625 // Ops[0] = Result Type ID
4626 // Ops[1] = Sampled Image ID
4627 // Ops[2] = Coordinate ID
4628 // Ops[3] = Image Operands Type ID
4629 // Ops[4] ... Ops[n] = Operands ID
4630 //
4631 Ops.clear();
4632
4633 uint32_t RetTyID = lookupType(Call->getType());
4634 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
4635 Ops.push_back(ResTyIDOp);
4636
4637 SPIRVOperand *SampledImageIDOp =
4638 new SPIRVOperand(SPIRVOperandType::NUMBERID, SampledImageID);
4639 Ops.push_back(SampledImageIDOp);
4640
4641 uint32_t CoordinateID = VMap[Coordinate];
4642 SPIRVOperand *CoordinateIDOp =
4643 new SPIRVOperand(SPIRVOperandType::NUMBERID, CoordinateID);
4644 Ops.push_back(CoordinateIDOp);
4645
4646 std::vector<uint32_t> LiteralNum;
4647 LiteralNum.push_back(spv::ImageOperandsLodMask);
4648 SPIRVOperand *ImageOperandTyIDOp =
4649 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4650 Ops.push_back(ImageOperandTyIDOp);
4651
4652 Constant *CstFP0 = ConstantFP::get(Context, APFloat(0.0f));
4653 uint32_t OperandID = VMap[CstFP0];
4654 SPIRVOperand *OperandIDOp =
4655 new SPIRVOperand(SPIRVOperandType::NUMBERID, OperandID);
4656 Ops.push_back(OperandIDOp);
4657
4658 VMap[&I] = nextID;
4659
4660 Inst =
4661 new SPIRVInstruction(7, spv::OpImageSampleExplicitLod, nextID++, Ops);
4662 SPIRVInstList.push_back(Inst);
4663 break;
4664 }
4665
4666 // write_imagef is mapped to OpImageWrite.
4667 if (Callee->getName().equals(
4668 "_Z12write_imagef14ocl_image2d_woDv2_iDv4_f") ||
4669 Callee->getName().equals(
4670 "_Z12write_imagef14ocl_image3d_woDv4_iDv4_f")) {
4671 //
4672 // Generate OpImageWrite.
4673 //
4674 // Ops[0] = Image ID
4675 // Ops[1] = Coordinate ID
4676 // Ops[2] = Texel ID
4677 // Ops[3] = (Optional) Image Operands Type (Literal Number)
4678 // Ops[4] ... Ops[n] = (Optional) Operands ID
4679 //
4680 SPIRVOperandList Ops;
4681
4682 Value *Image = Call->getArgOperand(0);
4683 Value *Coordinate = Call->getArgOperand(1);
4684 Value *Texel = Call->getArgOperand(2);
4685
4686 uint32_t ImageID = VMap[Image];
4687 SPIRVOperand *ImageIDOp =
4688 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageID);
4689 Ops.push_back(ImageIDOp);
4690
4691 uint32_t CoordinateID = VMap[Coordinate];
4692 SPIRVOperand *CoordinateIDOp =
4693 new SPIRVOperand(SPIRVOperandType::NUMBERID, CoordinateID);
4694 Ops.push_back(CoordinateIDOp);
4695
4696 uint32_t TexelID = VMap[Texel];
4697 SPIRVOperand *TexelIDOp =
4698 new SPIRVOperand(SPIRVOperandType::NUMBERID, TexelID);
4699 Ops.push_back(TexelIDOp);
4700
4701 SPIRVInstruction *Inst =
4702 new SPIRVInstruction(4, spv::OpImageWrite, 0 /* No id */, Ops);
4703 SPIRVInstList.push_back(Inst);
4704 break;
4705 }
4706
4707 // Call instrucion is deferred because it needs function's ID. Record
4708 // slot's location on SPIRVInstructionList.
4709 DeferredInsts.push_back(
4710 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4711
4712 // Check whether this call is for extend instructions.
4713 glsl::ExtInst EInst = getExtInstEnum(Callee->getName());
4714 if (EInst == glsl::ExtInstFindUMsb) {
4715 // clz needs OpExtInst and OpISub with constant 31. Increase nextID.
4716 VMap[&I] = nextID;
4717 nextID++;
4718 }
4719 break;
4720 }
4721 case Instruction::Ret: {
4722 unsigned NumOps = I.getNumOperands();
4723 if (NumOps == 0) {
4724 //
4725 // Generate OpReturn.
4726 //
4727
4728 // Empty Ops
4729 SPIRVOperandList Ops;
4730 SPIRVInstruction *Inst =
4731 new SPIRVInstruction(1, spv::OpReturn, 0 /* No id */, Ops);
4732 SPIRVInstList.push_back(Inst);
4733 } else {
4734 //
4735 // Generate OpReturnValue.
4736 //
4737
4738 // Ops[0] = Return Value ID
4739 SPIRVOperandList Ops;
4740 uint32_t RetValID = VMap[I.getOperand(0)];
4741 SPIRVOperand *RetValIDOp =
4742 new SPIRVOperand(SPIRVOperandType::NUMBERID, RetValID);
4743 Ops.push_back(RetValIDOp);
4744
4745 SPIRVInstruction *Inst =
4746 new SPIRVInstruction(2, spv::OpReturnValue, 0 /* No id */, Ops);
4747 SPIRVInstList.push_back(Inst);
4748 break;
4749 }
4750 break;
4751 }
4752 }
4753}
4754
4755void SPIRVProducerPass::GenerateFuncEpilogue() {
4756 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4757
4758 //
4759 // Generate OpFunctionEnd
4760 //
4761
4762 // Empty Ops
4763 SPIRVOperandList Ops;
4764 SPIRVInstruction *Inst =
4765 new SPIRVInstruction(1, spv::OpFunctionEnd, 0 /* No id */, Ops);
4766 SPIRVInstList.push_back(Inst);
4767}
4768
4769bool SPIRVProducerPass::is4xi8vec(Type *Ty) const {
4770 LLVMContext &Context = Ty->getContext();
4771 if (Ty->isVectorTy()) {
4772 if (Ty->getVectorElementType() == Type::getInt8Ty(Context) &&
4773 Ty->getVectorNumElements() == 4) {
4774 return true;
4775 }
4776 }
4777
4778 return false;
4779}
4780
4781void SPIRVProducerPass::HandleDeferredInstruction() {
4782 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4783 ValueMapType &VMap = getValueMap();
4784 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
4785
4786 for (auto DeferredInst = DeferredInsts.rbegin();
4787 DeferredInst != DeferredInsts.rend(); ++DeferredInst) {
4788 Value *Inst = std::get<0>(*DeferredInst);
4789 SPIRVInstructionList::iterator InsertPoint = ++std::get<1>(*DeferredInst);
4790 if (InsertPoint != SPIRVInstList.end()) {
4791 while ((*InsertPoint)->getOpcode() == spv::OpPhi) {
4792 ++InsertPoint;
4793 }
4794 }
4795
4796 if (BranchInst *Br = dyn_cast<BranchInst>(Inst)) {
4797 // Check whether basic block, which has this branch instruction, is loop
4798 // header or not. If it is loop header, generate OpLoopMerge and
4799 // OpBranchConditional.
4800 Function *Func = Br->getParent()->getParent();
4801 DominatorTree &DT =
4802 getAnalysis<DominatorTreeWrapperPass>(*Func).getDomTree();
4803 const LoopInfo &LI =
4804 getAnalysis<LoopInfoWrapperPass>(*Func).getLoopInfo();
4805
4806 BasicBlock *BrBB = Br->getParent();
4807 if (LI.isLoopHeader(BrBB)) {
4808 Value *ContinueBB = nullptr;
4809 Value *MergeBB = nullptr;
4810
4811 Loop *L = LI.getLoopFor(BrBB);
4812 MergeBB = L->getExitBlock();
4813 if (!MergeBB) {
4814 // StructurizeCFG pass converts CFG into triangle shape and the cfg
4815 // has regions with single entry/exit. As a result, loop should not
4816 // have multiple exits.
4817 llvm_unreachable("Loop has multiple exits???");
4818 }
4819
4820 if (L->isLoopLatch(BrBB)) {
4821 ContinueBB = BrBB;
4822 } else {
4823 // From SPIR-V spec 2.11, Continue Target must dominate that back-edge
4824 // block.
4825 BasicBlock *Header = L->getHeader();
4826 BasicBlock *Latch = L->getLoopLatch();
4827 for (BasicBlock *BB : L->blocks()) {
4828 if (BB == Header) {
4829 continue;
4830 }
4831
4832 // Check whether block dominates block with back-edge.
4833 if (DT.dominates(BB, Latch)) {
4834 ContinueBB = BB;
4835 }
4836 }
4837
4838 if (!ContinueBB) {
4839 llvm_unreachable("Wrong continue block from loop");
4840 }
4841 }
4842
4843 //
4844 // Generate OpLoopMerge.
4845 //
4846 // Ops[0] = Merge Block ID
4847 // Ops[1] = Continue Target ID
4848 // Ops[2] = Selection Control
4849 SPIRVOperandList Ops;
4850
4851 // StructurizeCFG pass already manipulated CFG. Just use false block of
4852 // branch instruction as merge block.
4853 uint32_t MergeBBID = VMap[MergeBB];
4854 SPIRVOperand *MergeBBIDOp =
4855 new SPIRVOperand(SPIRVOperandType::NUMBERID, MergeBBID);
4856 Ops.push_back(MergeBBIDOp);
4857
4858 uint32_t ContinueBBID = VMap[ContinueBB];
4859 SPIRVOperand *ContinueBBIDOp =
4860 new SPIRVOperand(SPIRVOperandType::NUMBERID, ContinueBBID);
4861 Ops.push_back(ContinueBBIDOp);
4862
4863 SPIRVOperand *SelectionControlOp = new SPIRVOperand(
4864 SPIRVOperandType::NUMBERID, spv::SelectionControlMaskNone);
4865 Ops.push_back(SelectionControlOp);
4866
4867 SPIRVInstruction *MergeInst =
4868 new SPIRVInstruction(4, spv::OpLoopMerge, 0 /* No id */, Ops);
4869 SPIRVInstList.insert(InsertPoint, MergeInst);
4870
4871 } else if (Br->isConditional()) {
4872 bool HasBackEdge = false;
4873
4874 for (unsigned i = 0; i < Br->getNumSuccessors(); i++) {
4875 if (LI.isLoopHeader(Br->getSuccessor(i))) {
4876 HasBackEdge = true;
4877 }
4878 }
4879 if (!HasBackEdge) {
4880 //
4881 // Generate OpSelectionMerge.
4882 //
4883 // Ops[0] = Merge Block ID
4884 // Ops[1] = Selection Control
4885 SPIRVOperandList Ops;
4886
4887 // StructurizeCFG pass already manipulated CFG. Just use false block
4888 // of branch instruction as merge block.
4889 uint32_t MergeBBID = VMap[Br->getSuccessor(1)];
4890 SPIRVOperand *MergeBBIDOp =
4891 new SPIRVOperand(SPIRVOperandType::NUMBERID, MergeBBID);
4892 Ops.push_back(MergeBBIDOp);
4893
4894 SPIRVOperand *SelectionControlOp = new SPIRVOperand(
4895 SPIRVOperandType::NUMBERID, spv::SelectionControlMaskNone);
4896 Ops.push_back(SelectionControlOp);
4897
4898 SPIRVInstruction *MergeInst = new SPIRVInstruction(
4899 3, spv::OpSelectionMerge, 0 /* No id */, Ops);
4900 SPIRVInstList.insert(InsertPoint, MergeInst);
4901 }
4902 }
4903
4904 if (Br->isConditional()) {
4905 //
4906 // Generate OpBranchConditional.
4907 //
4908 // Ops[0] = Condition ID
4909 // Ops[1] = True Label ID
4910 // Ops[2] = False Label ID
4911 // Ops[3] ... Ops[n] = Branch weights (Literal Number)
4912 SPIRVOperandList Ops;
4913
4914 uint32_t CondID = VMap[Br->getCondition()];
4915 SPIRVOperand *CondIDOp =
4916 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
4917 Ops.push_back(CondIDOp);
4918
4919 uint32_t TrueBBID = VMap[Br->getSuccessor(0)];
4920 SPIRVOperand *TrueBBIDOp =
4921 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueBBID);
4922 Ops.push_back(TrueBBIDOp);
4923
4924 uint32_t FalseBBID = VMap[Br->getSuccessor(1)];
4925 SPIRVOperand *FalseBBIDOp =
4926 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseBBID);
4927 Ops.push_back(FalseBBIDOp);
4928
4929 SPIRVInstruction *BrInst = new SPIRVInstruction(
4930 4, spv::OpBranchConditional, 0 /* No id */, Ops);
4931 SPIRVInstList.insert(InsertPoint, BrInst);
4932 } else {
4933 //
4934 // Generate OpBranch.
4935 //
4936 // Ops[0] = Target Label ID
4937 SPIRVOperandList Ops;
4938
4939 uint32_t TargetID = VMap[Br->getSuccessor(0)];
4940 SPIRVOperand *TargetIDOp =
4941 new SPIRVOperand(SPIRVOperandType::NUMBERID, TargetID);
4942 Ops.push_back(TargetIDOp);
4943
4944 SPIRVInstList.insert(
4945 InsertPoint,
4946 new SPIRVInstruction(2, spv::OpBranch, 0 /* No id */, Ops));
4947 }
4948 } else if (PHINode *PHI = dyn_cast<PHINode>(Inst)) {
4949 //
4950 // Generate OpPhi.
4951 //
4952 // Ops[0] = Result Type ID
4953 // Ops[1] ... Ops[n] = (Variable ID, Parent ID) pairs
4954 SPIRVOperandList Ops;
4955
4956 uint32_t ResTyID = lookupType(PHI->getType());
4957 SPIRVOperand *ResTyIDOp =
4958 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4959 Ops.push_back(ResTyIDOp);
4960
4961 uint16_t WordCount = 3;
4962 for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
4963 uint32_t VarID = VMap[PHI->getIncomingValue(i)];
4964 SPIRVOperand *VarIDOp =
4965 new SPIRVOperand(SPIRVOperandType::NUMBERID, VarID);
4966 Ops.push_back(VarIDOp);
4967
4968 uint32_t ParentID = VMap[PHI->getIncomingBlock(i)];
4969 SPIRVOperand *ParentIDOp =
4970 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParentID);
4971 Ops.push_back(ParentIDOp);
4972
4973 WordCount += 2;
4974 }
4975
4976 SPIRVInstList.insert(
4977 InsertPoint, new SPIRVInstruction(WordCount, spv::OpPhi,
4978 std::get<2>(*DeferredInst), Ops));
4979 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
4980 Function *Callee = Call->getCalledFunction();
4981 glsl::ExtInst EInst = getExtInstEnum(Callee->getName());
4982
4983 if (EInst) {
4984 uint32_t &ExtInstImportID = getOpExtInstImportID();
4985
4986 //
4987 // Generate OpExtInst.
4988 //
4989
4990 // Ops[0] = Result Type ID
4991 // Ops[1] = Set ID (OpExtInstImport ID)
4992 // Ops[2] = Instruction Number (Literal Number)
4993 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
4994 SPIRVOperandList Ops;
4995
4996 uint32_t ResTyID = lookupType(Call->getType());
4997 SPIRVOperand *ResTyIDOp =
4998 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4999 Ops.push_back(ResTyIDOp);
5000
5001 SPIRVOperand *SetIDOp =
5002 new SPIRVOperand(SPIRVOperandType::NUMBERID, ExtInstImportID);
5003 Ops.push_back(SetIDOp);
5004
5005 std::vector<uint32_t> LiteralNum;
5006 LiteralNum.push_back(EInst);
5007 SPIRVOperand *InstructionOp =
5008 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
5009 Ops.push_back(InstructionOp);
5010
5011 uint16_t WordCount = 5;
5012
5013 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5014 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
5015 uint32_t ArgID = VMap[Call->getOperand(i)];
5016 SPIRVOperand *ArgIDOp =
5017 new SPIRVOperand(SPIRVOperandType::NUMBERID, ArgID);
5018 Ops.push_back(ArgIDOp);
5019 WordCount++;
5020 }
5021
5022 SPIRVInstruction *ExtInst = new SPIRVInstruction(
5023 WordCount, spv::OpExtInst, std::get<2>(*DeferredInst), Ops);
5024 SPIRVInstList.insert(InsertPoint, ExtInst);
5025
5026 // clz needs OpExtInst and OpISub with constant 31.
5027 if (EInst == glsl::ExtInstFindUMsb) {
5028 LLVMContext &Context =
5029 Call->getParent()->getParent()->getParent()->getContext();
5030 //
5031 // Generate OpISub with constant 31.
5032 //
5033 // Ops[0] = Result Type ID
5034 // Ops[1] = Operand 0
5035 // Ops[2] = Operand 1
5036 Ops.clear();
5037
5038 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
5039 lookupType(Call->getType())));
5040
5041 Type *IdxTy = Type::getInt32Ty(Context);
5042 Constant *Cst31 = ConstantInt::get(IdxTy, 31);
5043 uint32_t Op0ID = VMap[Cst31];
5044 SPIRVOperand *Op0IDOp =
5045 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
5046 Ops.push_back(Op0IDOp);
5047
5048 SPIRVOperand *Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID,
5049 std::get<2>(*DeferredInst));
5050 Ops.push_back(Op1IDOp);
5051
5052 SPIRVInstList.insert(
5053 InsertPoint,
5054 new SPIRVInstruction(5, spv::OpISub,
5055 std::get<2>(*DeferredInst) + 1, Ops));
5056 }
5057 } else if (Callee->getName().equals("_Z8popcounti") ||
5058 Callee->getName().equals("_Z8popcountj") ||
5059 Callee->getName().equals("_Z8popcountDv2_i") ||
5060 Callee->getName().equals("_Z8popcountDv3_i") ||
5061 Callee->getName().equals("_Z8popcountDv4_i") ||
5062 Callee->getName().equals("_Z8popcountDv2_j") ||
5063 Callee->getName().equals("_Z8popcountDv3_j") ||
5064 Callee->getName().equals("_Z8popcountDv4_j")) {
5065 //
5066 // Generate OpBitCount
5067 //
5068 // Ops[0] = Result Type ID
5069 // Ops[1] = Base ID
5070 SPIRVOperand *Ops[2]{new SPIRVOperand(SPIRVOperandType::NUMBERID,
5071 lookupType(Call->getType())),
5072 new SPIRVOperand(SPIRVOperandType::NUMBERID,
5073 VMap[Call->getOperand(0)])};
5074
5075 SPIRVInstList.insert(
5076 InsertPoint, new SPIRVInstruction(4, spv::OpBitCount,
5077 std::get<2>(*DeferredInst), Ops));
5078 } else {
5079 //
5080 // Generate OpFunctionCall.
5081 //
5082
5083 // Ops[0] = Result Type ID
5084 // Ops[1] = Callee Function ID
5085 // Ops[2] ... Ops[n] = Argument 0, ... , Argument n
5086 SPIRVOperandList Ops;
5087
5088 uint32_t ResTyID = lookupType(Call->getType());
5089 SPIRVOperand *ResTyIDOp =
5090 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5091 Ops.push_back(ResTyIDOp);
5092
5093 uint32_t CalleeID = VMap[Callee];
5094
5095 SPIRVOperand *CalleeIDOp =
5096 new SPIRVOperand(SPIRVOperandType::NUMBERID, CalleeID);
5097 Ops.push_back(CalleeIDOp);
5098
5099 uint16_t WordCount = 4;
5100
5101 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5102 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
5103 uint32_t ArgID = VMap[Call->getOperand(i)];
5104 SPIRVOperand *ArgIDOp =
5105 new SPIRVOperand(SPIRVOperandType::NUMBERID, ArgID);
5106 Ops.push_back(ArgIDOp);
5107 WordCount++;
5108 }
5109
5110 SPIRVInstruction *CallInst = new SPIRVInstruction(
5111 WordCount, spv::OpFunctionCall, std::get<2>(*DeferredInst), Ops);
5112 SPIRVInstList.insert(InsertPoint, CallInst);
5113 }
5114 }
5115 }
5116}
5117
David Neto1a1a0582017-07-07 12:01:44 -04005118void SPIRVProducerPass::HandleDeferredDecorations(const DataLayout &DL) {
5119 // Insert ArrayStride decorations on pointer types, due to OpPtrAccessChain
5120 // instructions we generated earlier.
5121 if (getPointerTypesNeedingArrayStride().empty())
5122 return;
5123
5124 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5125 ValueMapType &VMap = getValueMap();
5126
5127 // Find an iterator pointing just past the last decoration.
5128 bool seen_decorations = false;
5129 auto DecoInsertPoint =
5130 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
5131 [&seen_decorations](SPIRVInstruction *Inst) -> bool {
5132 const bool is_decoration =
5133 Inst->getOpcode() == spv::OpDecorate ||
5134 Inst->getOpcode() == spv::OpMemberDecorate;
5135 if (is_decoration) {
5136 seen_decorations = true;
5137 return false;
5138 } else {
5139 return seen_decorations;
5140 }
5141 });
5142
5143 for (auto *type : getPointerTypesNeedingArrayStride()) {
5144 auto *ptrType = cast<PointerType>(type);
5145
5146 // Ops[0] = Target ID
5147 // Ops[1] = Decoration (ArrayStride)
5148 // Ops[2] = Stride number (Literal Number)
5149 SPIRVOperandList Ops;
5150
5151 Ops.push_back(
5152 new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(ptrType)));
5153 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
5154 spv::DecorationArrayStride));
5155 Type *elemTy = ptrType->getElementType();
5156 // Same as DL.getIndexedOfffsetInType( elemTy, { 1 } );
5157 const unsigned stride = DL.getTypeAllocSize(elemTy);
5158 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, stride));
5159
5160 SPIRVInstruction *DecoInst =
5161 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
5162 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
5163 }
5164}
5165
David Neto22f144c2017-06-12 14:26:21 -04005166glsl::ExtInst SPIRVProducerPass::getExtInstEnum(StringRef Name) {
5167 return StringSwitch<glsl::ExtInst>(Name)
5168 .Case("_Z3absi", glsl::ExtInst::ExtInstSAbs)
5169 .Case("_Z3absDv2_i", glsl::ExtInst::ExtInstSAbs)
5170 .Case("_Z3absDv3_i", glsl::ExtInst::ExtInstSAbs)
5171 .Case("_Z3absDv4_i", glsl::ExtInst::ExtInstSAbs)
5172 .Case("_Z5clampiii", glsl::ExtInst::ExtInstSClamp)
5173 .Case("_Z5clampDv2_iS_S_", glsl::ExtInst::ExtInstSClamp)
5174 .Case("_Z5clampDv3_iS_S_", glsl::ExtInst::ExtInstSClamp)
5175 .Case("_Z5clampDv4_iS_S_", glsl::ExtInst::ExtInstSClamp)
5176 .Case("_Z5clampjjj", glsl::ExtInst::ExtInstUClamp)
5177 .Case("_Z5clampDv2_jS_S_", glsl::ExtInst::ExtInstUClamp)
5178 .Case("_Z5clampDv3_jS_S_", glsl::ExtInst::ExtInstUClamp)
5179 .Case("_Z5clampDv4_jS_S_", glsl::ExtInst::ExtInstUClamp)
5180 .Case("_Z5clampfff", glsl::ExtInst::ExtInstFClamp)
5181 .Case("_Z5clampDv2_fS_S_", glsl::ExtInst::ExtInstFClamp)
5182 .Case("_Z5clampDv3_fS_S_", glsl::ExtInst::ExtInstFClamp)
5183 .Case("_Z5clampDv4_fS_S_", glsl::ExtInst::ExtInstFClamp)
5184 .StartsWith("_Z3clz", glsl::ExtInst::ExtInstFindUMsb)
5185 .Case("_Z3maxii", glsl::ExtInst::ExtInstSMax)
5186 .Case("_Z3maxDv2_iS_", glsl::ExtInst::ExtInstSMax)
5187 .Case("_Z3maxDv3_iS_", glsl::ExtInst::ExtInstSMax)
5188 .Case("_Z3maxDv4_iS_", glsl::ExtInst::ExtInstSMax)
5189 .Case("_Z3maxjj", glsl::ExtInst::ExtInstUMax)
5190 .Case("_Z3maxDv2_jS_", glsl::ExtInst::ExtInstUMax)
5191 .Case("_Z3maxDv3_jS_", glsl::ExtInst::ExtInstUMax)
5192 .Case("_Z3maxDv4_jS_", glsl::ExtInst::ExtInstUMax)
5193 .Case("_Z3maxff", glsl::ExtInst::ExtInstFMax)
5194 .Case("_Z3maxDv2_fS_", glsl::ExtInst::ExtInstFMax)
5195 .Case("_Z3maxDv3_fS_", glsl::ExtInst::ExtInstFMax)
5196 .Case("_Z3maxDv4_fS_", glsl::ExtInst::ExtInstFMax)
5197 .StartsWith("_Z4fmax", glsl::ExtInst::ExtInstFMax)
5198 .Case("_Z3minii", glsl::ExtInst::ExtInstSMin)
5199 .Case("_Z3minDv2_iS_", glsl::ExtInst::ExtInstSMin)
5200 .Case("_Z3minDv3_iS_", glsl::ExtInst::ExtInstSMin)
5201 .Case("_Z3minDv4_iS_", glsl::ExtInst::ExtInstSMin)
5202 .Case("_Z3minjj", glsl::ExtInst::ExtInstUMin)
5203 .Case("_Z3minDv2_jS_", glsl::ExtInst::ExtInstUMin)
5204 .Case("_Z3minDv3_jS_", glsl::ExtInst::ExtInstUMin)
5205 .Case("_Z3minDv4_jS_", glsl::ExtInst::ExtInstUMin)
5206 .Case("_Z3minff", glsl::ExtInst::ExtInstFMin)
5207 .Case("_Z3minDv2_fS_", glsl::ExtInst::ExtInstFMin)
5208 .Case("_Z3minDv3_fS_", glsl::ExtInst::ExtInstFMin)
5209 .Case("_Z3minDv4_fS_", glsl::ExtInst::ExtInstFMin)
5210 .StartsWith("_Z4fmin", glsl::ExtInst::ExtInstFMin)
5211 .StartsWith("_Z7degrees", glsl::ExtInst::ExtInstDegrees)
5212 .StartsWith("_Z7radians", glsl::ExtInst::ExtInstRadians)
5213 .StartsWith("_Z3mix", glsl::ExtInst::ExtInstFMix)
5214 .StartsWith("_Z4acos", glsl::ExtInst::ExtInstAcos)
5215 .StartsWith("_Z5acosh", glsl::ExtInst::ExtInstAcosh)
5216 .StartsWith("_Z4asin", glsl::ExtInst::ExtInstAsin)
5217 .StartsWith("_Z5asinh", glsl::ExtInst::ExtInstAsinh)
5218 .StartsWith("_Z4atan", glsl::ExtInst::ExtInstAtan)
5219 .StartsWith("_Z5atan2", glsl::ExtInst::ExtInstAtan2)
5220 .StartsWith("_Z5atanh", glsl::ExtInst::ExtInstAtanh)
5221 .StartsWith("_Z4ceil", glsl::ExtInst::ExtInstCeil)
5222 .StartsWith("_Z3sin", glsl::ExtInst::ExtInstSin)
5223 .StartsWith("_Z4sinh", glsl::ExtInst::ExtInstSinh)
5224 .StartsWith("_Z8half_sin", glsl::ExtInst::ExtInstSin)
5225 .StartsWith("_Z10native_sin", glsl::ExtInst::ExtInstSin)
5226 .StartsWith("_Z3cos", glsl::ExtInst::ExtInstCos)
5227 .StartsWith("_Z4cosh", glsl::ExtInst::ExtInstCosh)
5228 .StartsWith("_Z8half_cos", glsl::ExtInst::ExtInstCos)
5229 .StartsWith("_Z10native_cos", glsl::ExtInst::ExtInstCos)
5230 .StartsWith("_Z3tan", glsl::ExtInst::ExtInstTan)
5231 .StartsWith("_Z4tanh", glsl::ExtInst::ExtInstTanh)
5232 .StartsWith("_Z8half_tan", glsl::ExtInst::ExtInstTan)
5233 .StartsWith("_Z10native_tan", glsl::ExtInst::ExtInstTan)
5234 .StartsWith("_Z3exp", glsl::ExtInst::ExtInstExp)
5235 .StartsWith("_Z8half_exp", glsl::ExtInst::ExtInstExp)
5236 .StartsWith("_Z10native_exp", glsl::ExtInst::ExtInstExp)
5237 .StartsWith("_Z4exp2", glsl::ExtInst::ExtInstExp2)
5238 .StartsWith("_Z9half_exp2", glsl::ExtInst::ExtInstExp2)
5239 .StartsWith("_Z11native_exp2", glsl::ExtInst::ExtInstExp2)
5240 .StartsWith("_Z3log", glsl::ExtInst::ExtInstLog)
5241 .StartsWith("_Z8half_log", glsl::ExtInst::ExtInstLog)
5242 .StartsWith("_Z10native_log", glsl::ExtInst::ExtInstLog)
5243 .StartsWith("_Z4log2", glsl::ExtInst::ExtInstLog2)
5244 .StartsWith("_Z9half_log2", glsl::ExtInst::ExtInstLog2)
5245 .StartsWith("_Z11native_log2", glsl::ExtInst::ExtInstLog2)
5246 .StartsWith("_Z4fabs", glsl::ExtInst::ExtInstFAbs)
5247 .StartsWith("_Z5floor", glsl::ExtInst::ExtInstFloor)
5248 .StartsWith("_Z5ldexp", glsl::ExtInst::ExtInstLdexp)
5249 .StartsWith("_Z3pow", glsl::ExtInst::ExtInstPow)
5250 .StartsWith("_Z4powr", glsl::ExtInst::ExtInstPow)
5251 .StartsWith("_Z9half_powr", glsl::ExtInst::ExtInstPow)
5252 .StartsWith("_Z11native_powr", glsl::ExtInst::ExtInstPow)
5253 .StartsWith("_Z5round", glsl::ExtInst::ExtInstRound)
5254 .StartsWith("_Z4sqrt", glsl::ExtInst::ExtInstSqrt)
5255 .StartsWith("_Z9half_sqrt", glsl::ExtInst::ExtInstSqrt)
5256 .StartsWith("_Z11native_sqrt", glsl::ExtInst::ExtInstSqrt)
5257 .StartsWith("_Z5rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5258 .StartsWith("_Z10half_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5259 .StartsWith("_Z12native_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5260 .StartsWith("_Z5trunc", glsl::ExtInst::ExtInstTrunc)
5261 .StartsWith("_Z5frexp", glsl::ExtInst::ExtInstFrexp)
5262 .StartsWith("_Z4sign", glsl::ExtInst::ExtInstFSign)
5263 .StartsWith("_Z6length", glsl::ExtInst::ExtInstLength)
5264 .StartsWith("_Z8distance", glsl::ExtInst::ExtInstDistance)
5265 .Case("_Z5crossDv3_fS_", glsl::ExtInst::ExtInstCross)
5266 .StartsWith("_Z9normalize", glsl::ExtInst::ExtInstNormalize)
5267 .StartsWith("llvm.fmuladd.", glsl::ExtInst::ExtInstFma)
5268 .Case("spirv.unpack.v2f16", glsl::ExtInst::ExtInstUnpackHalf2x16)
5269 .Case("spirv.pack.v2f16", glsl::ExtInst::ExtInstPackHalf2x16)
5270 .Default(static_cast<glsl::ExtInst>(0));
5271}
5272
5273void SPIRVProducerPass::PrintResID(SPIRVInstruction *Inst) {
5274 out << "%" << Inst->getResultID();
5275}
5276
5277void SPIRVProducerPass::PrintOpcode(SPIRVInstruction *Inst) {
5278 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5279 out << "\t" << spv::getOpName(Opcode);
5280}
5281
5282void SPIRVProducerPass::PrintOperand(SPIRVOperand *Op) {
5283 SPIRVOperandType OpTy = Op->getType();
5284 switch (OpTy) {
5285 default: {
5286 llvm_unreachable("Unsupported SPIRV Operand Type???");
5287 break;
5288 }
5289 case SPIRVOperandType::NUMBERID: {
5290 out << "%" << Op->getNumID();
5291 break;
5292 }
5293 case SPIRVOperandType::LITERAL_STRING: {
5294 out << "\"" << Op->getLiteralStr() << "\"";
5295 break;
5296 }
5297 case SPIRVOperandType::LITERAL_INTEGER: {
5298 // TODO: Handle LiteralNum carefully.
5299 for (auto Word : Op->getLiteralNum()) {
5300 out << Word;
5301 }
5302 break;
5303 }
5304 case SPIRVOperandType::LITERAL_FLOAT: {
5305 // TODO: Handle LiteralNum carefully.
5306 for (auto Word : Op->getLiteralNum()) {
5307 APFloat APF = APFloat(APFloat::IEEEsingle(), APInt(32, Word));
5308 SmallString<8> Str;
5309 APF.toString(Str, 6, 2);
5310 out << Str;
5311 }
5312 break;
5313 }
5314 }
5315}
5316
5317void SPIRVProducerPass::PrintCapability(SPIRVOperand *Op) {
5318 spv::Capability Cap = static_cast<spv::Capability>(Op->getNumID());
5319 out << spv::getCapabilityName(Cap);
5320}
5321
5322void SPIRVProducerPass::PrintExtInst(SPIRVOperand *Op) {
5323 auto LiteralNum = Op->getLiteralNum();
5324 glsl::ExtInst Ext = static_cast<glsl::ExtInst>(LiteralNum[0]);
5325 out << glsl::getExtInstName(Ext);
5326}
5327
5328void SPIRVProducerPass::PrintAddrModel(SPIRVOperand *Op) {
5329 spv::AddressingModel AddrModel =
5330 static_cast<spv::AddressingModel>(Op->getNumID());
5331 out << spv::getAddressingModelName(AddrModel);
5332}
5333
5334void SPIRVProducerPass::PrintMemModel(SPIRVOperand *Op) {
5335 spv::MemoryModel MemModel = static_cast<spv::MemoryModel>(Op->getNumID());
5336 out << spv::getMemoryModelName(MemModel);
5337}
5338
5339void SPIRVProducerPass::PrintExecModel(SPIRVOperand *Op) {
5340 spv::ExecutionModel ExecModel =
5341 static_cast<spv::ExecutionModel>(Op->getNumID());
5342 out << spv::getExecutionModelName(ExecModel);
5343}
5344
5345void SPIRVProducerPass::PrintExecMode(SPIRVOperand *Op) {
5346 spv::ExecutionMode ExecMode = static_cast<spv::ExecutionMode>(Op->getNumID());
5347 out << spv::getExecutionModeName(ExecMode);
5348}
5349
5350void SPIRVProducerPass::PrintSourceLanguage(SPIRVOperand *Op) {
5351 spv::SourceLanguage SourceLang = static_cast<spv::SourceLanguage>(Op->getNumID());
5352 out << spv::getSourceLanguageName(SourceLang);
5353}
5354
5355void SPIRVProducerPass::PrintFuncCtrl(SPIRVOperand *Op) {
5356 spv::FunctionControlMask FuncCtrl =
5357 static_cast<spv::FunctionControlMask>(Op->getNumID());
5358 out << spv::getFunctionControlName(FuncCtrl);
5359}
5360
5361void SPIRVProducerPass::PrintStorageClass(SPIRVOperand *Op) {
5362 spv::StorageClass StClass = static_cast<spv::StorageClass>(Op->getNumID());
5363 out << getStorageClassName(StClass);
5364}
5365
5366void SPIRVProducerPass::PrintDecoration(SPIRVOperand *Op) {
5367 spv::Decoration Deco = static_cast<spv::Decoration>(Op->getNumID());
5368 out << getDecorationName(Deco);
5369}
5370
5371void SPIRVProducerPass::PrintBuiltIn(SPIRVOperand *Op) {
5372 spv::BuiltIn BIn = static_cast<spv::BuiltIn>(Op->getNumID());
5373 out << getBuiltInName(BIn);
5374}
5375
5376void SPIRVProducerPass::PrintSelectionControl(SPIRVOperand *Op) {
5377 spv::SelectionControlMask BIn =
5378 static_cast<spv::SelectionControlMask>(Op->getNumID());
5379 out << getSelectionControlName(BIn);
5380}
5381
5382void SPIRVProducerPass::PrintLoopControl(SPIRVOperand *Op) {
5383 spv::LoopControlMask BIn = static_cast<spv::LoopControlMask>(Op->getNumID());
5384 out << getLoopControlName(BIn);
5385}
5386
5387void SPIRVProducerPass::PrintDimensionality(SPIRVOperand *Op) {
5388 spv::Dim DIM = static_cast<spv::Dim>(Op->getNumID());
5389 out << getDimName(DIM);
5390}
5391
5392void SPIRVProducerPass::PrintImageFormat(SPIRVOperand *Op) {
5393 spv::ImageFormat Format = static_cast<spv::ImageFormat>(Op->getNumID());
5394 out << getImageFormatName(Format);
5395}
5396
5397void SPIRVProducerPass::PrintMemoryAccess(SPIRVOperand *Op) {
5398 out << spv::getMemoryAccessName(
5399 static_cast<spv::MemoryAccessMask>(Op->getNumID()));
5400}
5401
5402void SPIRVProducerPass::PrintImageOperandsType(SPIRVOperand *Op) {
5403 auto LiteralNum = Op->getLiteralNum();
5404 spv::ImageOperandsMask Type =
5405 static_cast<spv::ImageOperandsMask>(LiteralNum[0]);
5406 out << getImageOperandsName(Type);
5407}
5408
5409void SPIRVProducerPass::WriteSPIRVAssembly() {
5410 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5411
5412 for (auto Inst : SPIRVInstList) {
5413 SPIRVOperandList Ops = Inst->getOperands();
5414 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5415
5416 switch (Opcode) {
5417 default: {
5418 llvm_unreachable("Unsupported SPIRV instruction");
5419 break;
5420 }
5421 case spv::OpCapability: {
5422 // Ops[0] = Capability
5423 PrintOpcode(Inst);
5424 out << " ";
5425 PrintCapability(Ops[0]);
5426 out << "\n";
5427 break;
5428 }
5429 case spv::OpMemoryModel: {
5430 // Ops[0] = Addressing Model
5431 // Ops[1] = Memory Model
5432 PrintOpcode(Inst);
5433 out << " ";
5434 PrintAddrModel(Ops[0]);
5435 out << " ";
5436 PrintMemModel(Ops[1]);
5437 out << "\n";
5438 break;
5439 }
5440 case spv::OpEntryPoint: {
5441 // Ops[0] = Execution Model
5442 // Ops[1] = EntryPoint ID
5443 // Ops[2] = Name (Literal String)
5444 // Ops[3] ... Ops[n] = Interface ID
5445 PrintOpcode(Inst);
5446 out << " ";
5447 PrintExecModel(Ops[0]);
5448 for (uint32_t i = 1; i < Ops.size(); i++) {
5449 out << " ";
5450 PrintOperand(Ops[i]);
5451 }
5452 out << "\n";
5453 break;
5454 }
5455 case spv::OpExecutionMode: {
5456 // Ops[0] = Entry Point ID
5457 // Ops[1] = Execution Mode
5458 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
5459 PrintOpcode(Inst);
5460 out << " ";
5461 PrintOperand(Ops[0]);
5462 out << " ";
5463 PrintExecMode(Ops[1]);
5464 for (uint32_t i = 2; i < Ops.size(); i++) {
5465 out << " ";
5466 PrintOperand(Ops[i]);
5467 }
5468 out << "\n";
5469 break;
5470 }
5471 case spv::OpSource: {
5472 // Ops[0] = SourceLanguage ID
5473 // Ops[1] = Version (LiteralNum)
5474 PrintOpcode(Inst);
5475 out << " ";
5476 PrintSourceLanguage(Ops[0]);
5477 out << " ";
5478 PrintOperand(Ops[1]);
5479 out << "\n";
5480 break;
5481 }
5482 case spv::OpDecorate: {
5483 // Ops[0] = Target ID
5484 // Ops[1] = Decoration (Block or BufferBlock)
5485 // Ops[2] ... Ops[n] = Optional literals according to Decoration
5486 PrintOpcode(Inst);
5487 out << " ";
5488 PrintOperand(Ops[0]);
5489 out << " ";
5490 PrintDecoration(Ops[1]);
5491 // Handle BuiltIn OpDecorate specially.
5492 if (Ops[1]->getNumID() == spv::DecorationBuiltIn) {
5493 out << " ";
5494 PrintBuiltIn(Ops[2]);
5495 } else {
5496 for (uint32_t i = 2; i < Ops.size(); i++) {
5497 out << " ";
5498 PrintOperand(Ops[i]);
5499 }
5500 }
5501 out << "\n";
5502 break;
5503 }
5504 case spv::OpMemberDecorate: {
5505 // Ops[0] = Structure Type ID
5506 // Ops[1] = Member Index(Literal Number)
5507 // Ops[2] = Decoration
5508 // Ops[3] ... Ops[n] = Optional literals according to Decoration
5509 PrintOpcode(Inst);
5510 out << " ";
5511 PrintOperand(Ops[0]);
5512 out << " ";
5513 PrintOperand(Ops[1]);
5514 out << " ";
5515 PrintDecoration(Ops[2]);
5516 for (uint32_t i = 3; i < Ops.size(); i++) {
5517 out << " ";
5518 PrintOperand(Ops[i]);
5519 }
5520 out << "\n";
5521 break;
5522 }
5523 case spv::OpTypePointer: {
5524 // Ops[0] = Storage Class
5525 // Ops[1] = Element Type ID
5526 PrintResID(Inst);
5527 out << " = ";
5528 PrintOpcode(Inst);
5529 out << " ";
5530 PrintStorageClass(Ops[0]);
5531 out << " ";
5532 PrintOperand(Ops[1]);
5533 out << "\n";
5534 break;
5535 }
5536 case spv::OpTypeImage: {
5537 // Ops[0] = Sampled Type ID
5538 // Ops[1] = Dim ID
5539 // Ops[2] = Depth (Literal Number)
5540 // Ops[3] = Arrayed (Literal Number)
5541 // Ops[4] = MS (Literal Number)
5542 // Ops[5] = Sampled (Literal Number)
5543 // Ops[6] = Image Format ID
5544 PrintResID(Inst);
5545 out << " = ";
5546 PrintOpcode(Inst);
5547 out << " ";
5548 PrintOperand(Ops[0]);
5549 out << " ";
5550 PrintDimensionality(Ops[1]);
5551 out << " ";
5552 PrintOperand(Ops[2]);
5553 out << " ";
5554 PrintOperand(Ops[3]);
5555 out << " ";
5556 PrintOperand(Ops[4]);
5557 out << " ";
5558 PrintOperand(Ops[5]);
5559 out << " ";
5560 PrintImageFormat(Ops[6]);
5561 out << "\n";
5562 break;
5563 }
5564 case spv::OpFunction: {
5565 // Ops[0] : Result Type ID
5566 // Ops[1] : Function Control
5567 // Ops[2] : Function Type ID
5568 PrintResID(Inst);
5569 out << " = ";
5570 PrintOpcode(Inst);
5571 out << " ";
5572 PrintOperand(Ops[0]);
5573 out << " ";
5574 PrintFuncCtrl(Ops[1]);
5575 out << " ";
5576 PrintOperand(Ops[2]);
5577 out << "\n";
5578 break;
5579 }
5580 case spv::OpSelectionMerge: {
5581 // Ops[0] = Merge Block ID
5582 // Ops[1] = Selection Control
5583 PrintOpcode(Inst);
5584 out << " ";
5585 PrintOperand(Ops[0]);
5586 out << " ";
5587 PrintSelectionControl(Ops[1]);
5588 out << "\n";
5589 break;
5590 }
5591 case spv::OpLoopMerge: {
5592 // Ops[0] = Merge Block ID
5593 // Ops[1] = Continue Target ID
5594 // Ops[2] = Selection Control
5595 PrintOpcode(Inst);
5596 out << " ";
5597 PrintOperand(Ops[0]);
5598 out << " ";
5599 PrintOperand(Ops[1]);
5600 out << " ";
5601 PrintLoopControl(Ops[2]);
5602 out << "\n";
5603 break;
5604 }
5605 case spv::OpImageSampleExplicitLod: {
5606 // Ops[0] = Result Type ID
5607 // Ops[1] = Sampled Image ID
5608 // Ops[2] = Coordinate ID
5609 // Ops[3] = Image Operands Type ID
5610 // Ops[4] ... Ops[n] = Operands ID
5611 PrintResID(Inst);
5612 out << " = ";
5613 PrintOpcode(Inst);
5614 for (uint32_t i = 0; i < 3; i++) {
5615 out << " ";
5616 PrintOperand(Ops[i]);
5617 }
5618 out << " ";
5619 PrintImageOperandsType(Ops[3]);
5620 for (uint32_t i = 4; i < Ops.size(); i++) {
5621 out << " ";
5622 PrintOperand(Ops[i]);
5623 }
5624 out << "\n";
5625 break;
5626 }
5627 case spv::OpVariable: {
5628 // Ops[0] : Result Type ID
5629 // Ops[1] : Storage Class
5630 // Ops[2] ... Ops[n] = Initializer IDs
5631 PrintResID(Inst);
5632 out << " = ";
5633 PrintOpcode(Inst);
5634 out << " ";
5635 PrintOperand(Ops[0]);
5636 out << " ";
5637 PrintStorageClass(Ops[1]);
5638 for (uint32_t i = 2; i < Ops.size(); i++) {
5639 out << " ";
5640 PrintOperand(Ops[i]);
5641 }
5642 out << "\n";
5643 break;
5644 }
5645 case spv::OpExtInst: {
5646 // Ops[0] = Result Type ID
5647 // Ops[1] = Set ID (OpExtInstImport ID)
5648 // Ops[2] = Instruction Number (Literal Number)
5649 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5650 PrintResID(Inst);
5651 out << " = ";
5652 PrintOpcode(Inst);
5653 out << " ";
5654 PrintOperand(Ops[0]);
5655 out << " ";
5656 PrintOperand(Ops[1]);
5657 out << " ";
5658 PrintExtInst(Ops[2]);
5659 for (uint32_t i = 3; i < Ops.size(); i++) {
5660 out << " ";
5661 PrintOperand(Ops[i]);
5662 }
5663 out << "\n";
5664 break;
5665 }
5666 case spv::OpCopyMemory: {
5667 // Ops[0] = Addressing Model
5668 // Ops[1] = Memory Model
5669 PrintOpcode(Inst);
5670 out << " ";
5671 PrintOperand(Ops[0]);
5672 out << " ";
5673 PrintOperand(Ops[1]);
5674 out << " ";
5675 PrintMemoryAccess(Ops[2]);
5676 out << " ";
5677 PrintOperand(Ops[3]);
5678 out << "\n";
5679 break;
5680 }
5681 case spv::OpExtension:
5682 case spv::OpControlBarrier:
5683 case spv::OpMemoryBarrier:
5684 case spv::OpBranch:
5685 case spv::OpBranchConditional:
5686 case spv::OpStore:
5687 case spv::OpImageWrite:
5688 case spv::OpReturnValue:
5689 case spv::OpReturn:
5690 case spv::OpFunctionEnd: {
5691 PrintOpcode(Inst);
5692 for (uint32_t i = 0; i < Ops.size(); i++) {
5693 out << " ";
5694 PrintOperand(Ops[i]);
5695 }
5696 out << "\n";
5697 break;
5698 }
5699 case spv::OpExtInstImport:
5700 case spv::OpTypeRuntimeArray:
5701 case spv::OpTypeStruct:
5702 case spv::OpTypeSampler:
5703 case spv::OpTypeSampledImage:
5704 case spv::OpTypeInt:
5705 case spv::OpTypeFloat:
5706 case spv::OpTypeArray:
5707 case spv::OpTypeVector:
5708 case spv::OpTypeBool:
5709 case spv::OpTypeVoid:
5710 case spv::OpTypeFunction:
5711 case spv::OpFunctionParameter:
5712 case spv::OpLabel:
5713 case spv::OpPhi:
5714 case spv::OpLoad:
5715 case spv::OpSelect:
5716 case spv::OpAccessChain:
5717 case spv::OpPtrAccessChain:
5718 case spv::OpInBoundsAccessChain:
5719 case spv::OpUConvert:
5720 case spv::OpSConvert:
5721 case spv::OpConvertFToU:
5722 case spv::OpConvertFToS:
5723 case spv::OpConvertUToF:
5724 case spv::OpConvertSToF:
5725 case spv::OpFConvert:
5726 case spv::OpConvertPtrToU:
5727 case spv::OpConvertUToPtr:
5728 case spv::OpBitcast:
5729 case spv::OpIAdd:
5730 case spv::OpFAdd:
5731 case spv::OpISub:
5732 case spv::OpFSub:
5733 case spv::OpIMul:
5734 case spv::OpFMul:
5735 case spv::OpUDiv:
5736 case spv::OpSDiv:
5737 case spv::OpFDiv:
5738 case spv::OpUMod:
5739 case spv::OpSRem:
5740 case spv::OpFRem:
5741 case spv::OpBitwiseOr:
5742 case spv::OpBitwiseXor:
5743 case spv::OpBitwiseAnd:
5744 case spv::OpShiftLeftLogical:
5745 case spv::OpShiftRightLogical:
5746 case spv::OpShiftRightArithmetic:
5747 case spv::OpBitCount:
5748 case spv::OpCompositeExtract:
5749 case spv::OpVectorExtractDynamic:
5750 case spv::OpCompositeInsert:
5751 case spv::OpVectorInsertDynamic:
5752 case spv::OpVectorShuffle:
5753 case spv::OpIEqual:
5754 case spv::OpINotEqual:
5755 case spv::OpUGreaterThan:
5756 case spv::OpUGreaterThanEqual:
5757 case spv::OpULessThan:
5758 case spv::OpULessThanEqual:
5759 case spv::OpSGreaterThan:
5760 case spv::OpSGreaterThanEqual:
5761 case spv::OpSLessThan:
5762 case spv::OpSLessThanEqual:
5763 case spv::OpFOrdEqual:
5764 case spv::OpFOrdGreaterThan:
5765 case spv::OpFOrdGreaterThanEqual:
5766 case spv::OpFOrdLessThan:
5767 case spv::OpFOrdLessThanEqual:
5768 case spv::OpFOrdNotEqual:
5769 case spv::OpFUnordEqual:
5770 case spv::OpFUnordGreaterThan:
5771 case spv::OpFUnordGreaterThanEqual:
5772 case spv::OpFUnordLessThan:
5773 case spv::OpFUnordLessThanEqual:
5774 case spv::OpFUnordNotEqual:
5775 case spv::OpSampledImage:
5776 case spv::OpFunctionCall:
5777 case spv::OpConstantTrue:
5778 case spv::OpConstantFalse:
5779 case spv::OpConstant:
5780 case spv::OpSpecConstant:
5781 case spv::OpConstantComposite:
5782 case spv::OpSpecConstantComposite:
5783 case spv::OpConstantNull:
5784 case spv::OpLogicalOr:
5785 case spv::OpLogicalAnd:
5786 case spv::OpLogicalNot:
5787 case spv::OpLogicalNotEqual:
5788 case spv::OpUndef:
5789 case spv::OpIsInf:
5790 case spv::OpIsNan:
5791 case spv::OpAny:
5792 case spv::OpAll:
5793 case spv::OpAtomicIAdd:
5794 case spv::OpAtomicISub:
5795 case spv::OpAtomicExchange:
5796 case spv::OpAtomicIIncrement:
5797 case spv::OpAtomicIDecrement:
5798 case spv::OpAtomicCompareExchange:
5799 case spv::OpAtomicUMin:
5800 case spv::OpAtomicSMin:
5801 case spv::OpAtomicUMax:
5802 case spv::OpAtomicSMax:
5803 case spv::OpAtomicAnd:
5804 case spv::OpAtomicOr:
5805 case spv::OpAtomicXor:
5806 case spv::OpDot: {
5807 PrintResID(Inst);
5808 out << " = ";
5809 PrintOpcode(Inst);
5810 for (uint32_t i = 0; i < Ops.size(); i++) {
5811 out << " ";
5812 PrintOperand(Ops[i]);
5813 }
5814 out << "\n";
5815 break;
5816 }
5817 }
5818 }
5819}
5820
5821void SPIRVProducerPass::WriteOneWord(uint32_t Word) {
David Neto0676e6f2017-07-11 18:47:44 -04005822 binaryOut->write(reinterpret_cast<const char *>(&Word), sizeof(uint32_t));
David Neto22f144c2017-06-12 14:26:21 -04005823}
5824
5825void SPIRVProducerPass::WriteResultID(SPIRVInstruction *Inst) {
5826 WriteOneWord(Inst->getResultID());
5827}
5828
5829void SPIRVProducerPass::WriteWordCountAndOpcode(SPIRVInstruction *Inst) {
5830 // High 16 bit : Word Count
5831 // Low 16 bit : Opcode
5832 uint32_t Word = Inst->getOpcode();
5833 Word |= Inst->getWordCount() << 16;
5834 WriteOneWord(Word);
5835}
5836
5837void SPIRVProducerPass::WriteOperand(SPIRVOperand *Op) {
5838 SPIRVOperandType OpTy = Op->getType();
5839 switch (OpTy) {
5840 default: {
5841 llvm_unreachable("Unsupported SPIRV Operand Type???");
5842 break;
5843 }
5844 case SPIRVOperandType::NUMBERID: {
5845 WriteOneWord(Op->getNumID());
5846 break;
5847 }
5848 case SPIRVOperandType::LITERAL_STRING: {
5849 std::string Str = Op->getLiteralStr();
5850 const char *Data = Str.c_str();
5851 size_t WordSize = Str.size() / 4;
5852 for (unsigned Idx = 0; Idx < WordSize; Idx++) {
5853 WriteOneWord(*reinterpret_cast<const uint32_t *>(&Data[4 * Idx]));
5854 }
5855
5856 uint32_t Remainder = Str.size() % 4;
5857 uint32_t LastWord = 0;
5858 if (Remainder) {
5859 for (unsigned Idx = 0; Idx < Remainder; Idx++) {
5860 LastWord |= Data[4 * WordSize + Idx] << 8 * Idx;
5861 }
5862 }
5863
5864 WriteOneWord(LastWord);
5865 break;
5866 }
5867 case SPIRVOperandType::LITERAL_INTEGER:
5868 case SPIRVOperandType::LITERAL_FLOAT: {
5869 auto LiteralNum = Op->getLiteralNum();
5870 // TODO: Handle LiteranNum carefully.
5871 for (auto Word : LiteralNum) {
5872 WriteOneWord(Word);
5873 }
5874 break;
5875 }
5876 }
5877}
5878
5879void SPIRVProducerPass::WriteSPIRVBinary() {
5880 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5881
5882 for (auto Inst : SPIRVInstList) {
5883 SPIRVOperandList Ops = Inst->getOperands();
5884 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5885
5886 switch (Opcode) {
5887 default: {
5888 llvm_unreachable("Unsupported SPIRV instruction");
5889 break;
5890 }
5891 case spv::OpCapability:
5892 case spv::OpExtension:
5893 case spv::OpMemoryModel:
5894 case spv::OpEntryPoint:
5895 case spv::OpExecutionMode:
5896 case spv::OpSource:
5897 case spv::OpDecorate:
5898 case spv::OpMemberDecorate:
5899 case spv::OpBranch:
5900 case spv::OpBranchConditional:
5901 case spv::OpSelectionMerge:
5902 case spv::OpLoopMerge:
5903 case spv::OpStore:
5904 case spv::OpImageWrite:
5905 case spv::OpReturnValue:
5906 case spv::OpControlBarrier:
5907 case spv::OpMemoryBarrier:
5908 case spv::OpReturn:
5909 case spv::OpFunctionEnd:
5910 case spv::OpCopyMemory: {
5911 WriteWordCountAndOpcode(Inst);
5912 for (uint32_t i = 0; i < Ops.size(); i++) {
5913 WriteOperand(Ops[i]);
5914 }
5915 break;
5916 }
5917 case spv::OpTypeBool:
5918 case spv::OpTypeVoid:
5919 case spv::OpTypeSampler:
5920 case spv::OpLabel:
5921 case spv::OpExtInstImport:
5922 case spv::OpTypePointer:
5923 case spv::OpTypeRuntimeArray:
5924 case spv::OpTypeStruct:
5925 case spv::OpTypeImage:
5926 case spv::OpTypeSampledImage:
5927 case spv::OpTypeInt:
5928 case spv::OpTypeFloat:
5929 case spv::OpTypeArray:
5930 case spv::OpTypeVector:
5931 case spv::OpTypeFunction: {
5932 WriteWordCountAndOpcode(Inst);
5933 WriteResultID(Inst);
5934 for (uint32_t i = 0; i < Ops.size(); i++) {
5935 WriteOperand(Ops[i]);
5936 }
5937 break;
5938 }
5939 case spv::OpFunction:
5940 case spv::OpFunctionParameter:
5941 case spv::OpAccessChain:
5942 case spv::OpPtrAccessChain:
5943 case spv::OpInBoundsAccessChain:
5944 case spv::OpUConvert:
5945 case spv::OpSConvert:
5946 case spv::OpConvertFToU:
5947 case spv::OpConvertFToS:
5948 case spv::OpConvertUToF:
5949 case spv::OpConvertSToF:
5950 case spv::OpFConvert:
5951 case spv::OpConvertPtrToU:
5952 case spv::OpConvertUToPtr:
5953 case spv::OpBitcast:
5954 case spv::OpIAdd:
5955 case spv::OpFAdd:
5956 case spv::OpISub:
5957 case spv::OpFSub:
5958 case spv::OpIMul:
5959 case spv::OpFMul:
5960 case spv::OpUDiv:
5961 case spv::OpSDiv:
5962 case spv::OpFDiv:
5963 case spv::OpUMod:
5964 case spv::OpSRem:
5965 case spv::OpFRem:
5966 case spv::OpBitwiseOr:
5967 case spv::OpBitwiseXor:
5968 case spv::OpBitwiseAnd:
5969 case spv::OpShiftLeftLogical:
5970 case spv::OpShiftRightLogical:
5971 case spv::OpShiftRightArithmetic:
5972 case spv::OpBitCount:
5973 case spv::OpCompositeExtract:
5974 case spv::OpVectorExtractDynamic:
5975 case spv::OpCompositeInsert:
5976 case spv::OpVectorInsertDynamic:
5977 case spv::OpVectorShuffle:
5978 case spv::OpIEqual:
5979 case spv::OpINotEqual:
5980 case spv::OpUGreaterThan:
5981 case spv::OpUGreaterThanEqual:
5982 case spv::OpULessThan:
5983 case spv::OpULessThanEqual:
5984 case spv::OpSGreaterThan:
5985 case spv::OpSGreaterThanEqual:
5986 case spv::OpSLessThan:
5987 case spv::OpSLessThanEqual:
5988 case spv::OpFOrdEqual:
5989 case spv::OpFOrdGreaterThan:
5990 case spv::OpFOrdGreaterThanEqual:
5991 case spv::OpFOrdLessThan:
5992 case spv::OpFOrdLessThanEqual:
5993 case spv::OpFOrdNotEqual:
5994 case spv::OpFUnordEqual:
5995 case spv::OpFUnordGreaterThan:
5996 case spv::OpFUnordGreaterThanEqual:
5997 case spv::OpFUnordLessThan:
5998 case spv::OpFUnordLessThanEqual:
5999 case spv::OpFUnordNotEqual:
6000 case spv::OpExtInst:
6001 case spv::OpIsInf:
6002 case spv::OpIsNan:
6003 case spv::OpAny:
6004 case spv::OpAll:
6005 case spv::OpUndef:
6006 case spv::OpConstantNull:
6007 case spv::OpLogicalOr:
6008 case spv::OpLogicalAnd:
6009 case spv::OpLogicalNot:
6010 case spv::OpLogicalNotEqual:
6011 case spv::OpConstantComposite:
6012 case spv::OpSpecConstantComposite:
6013 case spv::OpConstantTrue:
6014 case spv::OpConstantFalse:
6015 case spv::OpConstant:
6016 case spv::OpSpecConstant:
6017 case spv::OpVariable:
6018 case spv::OpFunctionCall:
6019 case spv::OpSampledImage:
6020 case spv::OpImageSampleExplicitLod:
6021 case spv::OpSelect:
6022 case spv::OpPhi:
6023 case spv::OpLoad:
6024 case spv::OpAtomicIAdd:
6025 case spv::OpAtomicISub:
6026 case spv::OpAtomicExchange:
6027 case spv::OpAtomicIIncrement:
6028 case spv::OpAtomicIDecrement:
6029 case spv::OpAtomicCompareExchange:
6030 case spv::OpAtomicUMin:
6031 case spv::OpAtomicSMin:
6032 case spv::OpAtomicUMax:
6033 case spv::OpAtomicSMax:
6034 case spv::OpAtomicAnd:
6035 case spv::OpAtomicOr:
6036 case spv::OpAtomicXor:
6037 case spv::OpDot: {
6038 WriteWordCountAndOpcode(Inst);
6039 WriteOperand(Ops[0]);
6040 WriteResultID(Inst);
6041 for (uint32_t i = 1; i < Ops.size(); i++) {
6042 WriteOperand(Ops[i]);
6043 }
6044 break;
6045 }
6046 }
6047 }
6048}