blob: 3a038529e7b508e89cdfa9a7c1b516fae079e634 [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;
David Netofb9a7972017-08-25 17:08:24 -0400104 typedef UniqueVector<Value *> ValueList;
David Neto22f144c2017-06-12 14:26:21 -0400105 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()) {
David Netofb9a7972017-08-25 17:08:24 -0400345 getEntryPointInterfacesVec().insert(&GV);
David Neto22f144c2017-06-12 14:26:21 -0400346 }
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
David Netofb9a7972017-08-25 17:08:24 -04001161 // If V is already tracked, ignore it.
1162 if (0 != CstList.idFor(V)) {
David Neto22f144c2017-06-12 14:26:21 -04001163 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)) {
David Netofb9a7972017-08-25 17:08:24 -04001172 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001173 }
1174 }
1175
1176 if (Cst->getNumOperands()) {
1177 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end(); I != E;
1178 ++I) {
1179 FindConstant(*I);
1180 }
1181
David Netofb9a7972017-08-25 17:08:24 -04001182 CstList.insert(Cst);
David Neto22f144c2017-06-12 14:26:21 -04001183 return;
1184 } else if (const ConstantDataSequential *CDS =
1185 dyn_cast<ConstantDataSequential>(Cst)) {
1186 // Add constants for each element to constant list.
1187 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
1188 Constant *EleCst = CDS->getElementAsConstant(i);
1189 FindConstant(EleCst);
1190 }
1191 }
1192
1193 if (!isa<GlobalValue>(V)) {
David Netofb9a7972017-08-25 17:08:24 -04001194 CstList.insert(V);
David Neto22f144c2017-06-12 14:26:21 -04001195 }
1196}
1197
1198spv::StorageClass SPIRVProducerPass::GetStorageClass(unsigned AddrSpace) const {
1199 switch (AddrSpace) {
1200 default:
1201 llvm_unreachable("Unsupported OpenCL address space");
1202 case AddressSpace::Private:
1203 return spv::StorageClassFunction;
1204 case AddressSpace::Global:
1205 case AddressSpace::Constant:
1206 return spv::StorageClassStorageBuffer;
1207 case AddressSpace::Input:
1208 return spv::StorageClassInput;
1209 case AddressSpace::Local:
1210 return spv::StorageClassWorkgroup;
1211 case AddressSpace::UniformConstant:
1212 return spv::StorageClassUniformConstant;
1213 case AddressSpace::ModuleScopePrivate:
1214 return spv::StorageClassPrivate;
1215 }
1216}
1217
1218spv::BuiltIn SPIRVProducerPass::GetBuiltin(StringRef Name) const {
1219 return StringSwitch<spv::BuiltIn>(Name)
1220 .Case("__spirv_GlobalInvocationId", spv::BuiltInGlobalInvocationId)
1221 .Case("__spirv_LocalInvocationId", spv::BuiltInLocalInvocationId)
1222 .Case("__spirv_WorkgroupSize", spv::BuiltInWorkgroupSize)
1223 .Case("__spirv_NumWorkgroups", spv::BuiltInNumWorkgroups)
1224 .Case("__spirv_WorkgroupId", spv::BuiltInWorkgroupId)
1225 .Default(spv::BuiltInMax);
1226}
1227
1228void SPIRVProducerPass::GenerateExtInstImport() {
1229 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1230 uint32_t &ExtInstImportID = getOpExtInstImportID();
1231
1232 //
1233 // Generate OpExtInstImport.
1234 //
1235 // Ops[0] ... Ops[n] = Name (Literal String)
1236 SPIRVOperandList Ops;
1237
1238 SPIRVOperand *Name =
1239 new SPIRVOperand(SPIRVOperandType::LITERAL_STRING, "GLSL.std.450");
1240 Ops.push_back(Name);
1241
1242 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
1243 assert(NameWordSize < (UINT16_MAX - 2));
1244 if ((Name->getLiteralStr().size() + 1) % 4) {
1245 NameWordSize += 1;
1246 }
1247
1248 uint16_t WordCount = static_cast<uint16_t>(2 + NameWordSize);
1249 ExtInstImportID = nextID;
1250
1251 SPIRVInstruction *Inst =
1252 new SPIRVInstruction(WordCount, spv::OpExtInstImport, nextID++, Ops);
1253 SPIRVInstList.push_back(Inst);
1254}
1255
1256void SPIRVProducerPass::GenerateSPIRVTypes(const DataLayout &DL) {
1257 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1258 ValueMapType &VMap = getValueMap();
1259 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1260 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
1261
1262 // Map for OpTypeRuntimeArray. If argument has pointer type, 2 spirv type
1263 // instructions are generated. They are OpTypePointer and OpTypeRuntimeArray.
1264 DenseMap<Type *, uint32_t> OpRuntimeTyMap;
1265
1266 for (Type *Ty : getTypeList()) {
1267 // Update TypeMap with nextID for reference later.
1268 TypeMap[Ty] = nextID;
1269
1270 switch (Ty->getTypeID()) {
1271 default: {
1272 Ty->print(errs());
1273 llvm_unreachable("Unsupported type???");
1274 break;
1275 }
1276 case Type::MetadataTyID:
1277 case Type::LabelTyID: {
1278 // Ignore these types.
1279 break;
1280 }
1281 case Type::PointerTyID: {
1282 PointerType *PTy = cast<PointerType>(Ty);
1283 unsigned AddrSpace = PTy->getAddressSpace();
1284
1285 // For the purposes of our Vulkan SPIR-V type system, constant and global
1286 // are conflated.
1287 bool UseExistingOpTypePointer = false;
1288 if (AddressSpace::Constant == AddrSpace) {
1289 AddrSpace = AddressSpace::Global;
1290
1291 // Check to see if we already created this type (for instance, if we had
1292 // a constant <type>* and a global <type>*, the type would be created by
1293 // one of these types, and shared by both).
1294 auto GlobalTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1295 if (0 < TypeMap.count(GlobalTy)) {
1296 TypeMap[PTy] = TypeMap[GlobalTy];
1297 break;
1298 }
1299 } else if (AddressSpace::Global == AddrSpace) {
1300 AddrSpace = AddressSpace::Constant;
1301
1302 // Check to see if we already created this type (for instance, if we had
1303 // a constant <type>* and a global <type>*, the type would be created by
1304 // one of these types, and shared by both).
1305 auto ConstantTy = PTy->getPointerElementType()->getPointerTo(AddrSpace);
1306 if (0 < TypeMap.count(ConstantTy)) {
1307 TypeMap[PTy] = TypeMap[ConstantTy];
1308 UseExistingOpTypePointer = true;
1309 }
1310 }
1311
1312 bool IsOpTypeRuntimeArray = false;
1313 bool HasArgUser = false;
1314
1315 for (auto ArgGV : ArgGVMap) {
1316 auto Arg = ArgGV.first;
1317
1318 Type *ArgTy = Arg->getType();
1319 if (ArgTy == PTy) {
1320 if (AddrSpace != AddressSpace::UniformConstant) {
1321 IsOpTypeRuntimeArray = true;
1322 }
1323
1324 for (auto U : Arg->users()) {
1325 if (!isa<GetElementPtrInst>(U) || (U->getType() == PTy)) {
1326 HasArgUser = true;
1327 break;
1328 }
1329 }
1330 }
1331 }
1332
1333 if ((!IsOpTypeRuntimeArray || HasArgUser) && !UseExistingOpTypePointer) {
1334 //
1335 // Generate OpTypePointer.
1336 //
1337
1338 // OpTypePointer
1339 // Ops[0] = Storage Class
1340 // Ops[1] = Element Type ID
1341 SPIRVOperandList Ops;
1342
1343 spv::StorageClass StorageClass = GetStorageClass(AddrSpace);
1344
1345 SPIRVOperand *StorageClassOp =
1346 new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass);
1347 Ops.push_back(StorageClassOp);
1348
1349 uint32_t EleTyID = lookupType(PTy->getElementType());
1350 SPIRVOperand *EleTyOp =
1351 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1352 Ops.push_back(EleTyOp);
1353
1354 spv::Op Opcode = spv::OpTypePointer;
1355 uint16_t WordCount = 4;
1356
1357 SPIRVInstruction *Inst =
1358 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
1359 SPIRVInstList.push_back(Inst);
1360 }
1361
1362 if (IsOpTypeRuntimeArray) {
1363 //
1364 // Generate OpTypeRuntimeArray.
1365 //
1366
1367 // OpTypeRuntimeArray
1368 // Ops[0] = Element Type ID
1369 SPIRVOperandList Ops;
1370
1371 uint32_t EleTyID = lookupType(PTy->getElementType());
1372 SPIRVOperand *EleTyOp =
1373 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1374 Ops.push_back(EleTyOp);
1375
1376 spv::Op Opcode = spv::OpTypeRuntimeArray;
1377 uint16_t WordCount = 3;
1378
1379 uint32_t OpTypeRuntimeArrayID = nextID;
1380 assert(0 == OpRuntimeTyMap.count(Ty));
1381 OpRuntimeTyMap[Ty] = nextID;
1382
1383 SPIRVInstruction *Inst =
1384 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
1385 SPIRVInstList.push_back(Inst);
1386
1387 // Generate OpDecorate.
1388 auto DecoInsertPoint =
1389 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1390 [](SPIRVInstruction *Inst) -> bool {
1391 return Inst->getOpcode() != spv::OpDecorate &&
1392 Inst->getOpcode() != spv::OpMemberDecorate &&
1393 Inst->getOpcode() != spv::OpExtInstImport;
1394 });
1395
1396 // Ops[0] = Target ID
1397 // Ops[1] = Decoration (ArrayStride)
1398 // Ops[2] = Stride Number(Literal Number)
1399 Ops.clear();
1400
1401 SPIRVOperand *PTyIDOp =
1402 new SPIRVOperand(SPIRVOperandType::NUMBERID, OpTypeRuntimeArrayID);
1403 Ops.push_back(PTyIDOp);
1404
1405 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID,
1406 spv::DecorationArrayStride);
1407 Ops.push_back(DecoOp);
1408
1409 std::vector<uint32_t> LiteralNum;
1410 Type *EleTy = PTy->getElementType();
David Neto25018082017-07-07 13:21:46 -04001411 const unsigned ArrayStride = DL.getTypeAllocSize(EleTy);
David Neto22f144c2017-06-12 14:26:21 -04001412 LiteralNum.push_back(ArrayStride);
1413 SPIRVOperand *ArrayStrideOp =
1414 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1415 Ops.push_back(ArrayStrideOp);
1416
1417 SPIRVInstruction *DecoInst =
1418 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
1419 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1420 }
1421 break;
1422 }
1423 case Type::StructTyID: {
1424 LLVMContext &Context = Ty->getContext();
1425
1426 StructType *STy = cast<StructType>(Ty);
1427
1428 // Handle sampler type.
1429 if (STy->isOpaque()) {
1430 if (STy->getName().equals("opencl.sampler_t")) {
1431 //
1432 // Generate OpTypeSampler
1433 //
1434 // Empty Ops.
1435 SPIRVOperandList Ops;
1436
1437 SPIRVInstruction *Inst =
1438 new SPIRVInstruction(2, spv::OpTypeSampler, nextID++, Ops);
1439 SPIRVInstList.push_back(Inst);
1440 break;
1441 } else if (STy->getName().equals("opencl.image2d_ro_t") ||
1442 STy->getName().equals("opencl.image2d_wo_t") ||
1443 STy->getName().equals("opencl.image3d_ro_t") ||
1444 STy->getName().equals("opencl.image3d_wo_t")) {
1445 //
1446 // Generate OpTypeImage
1447 //
1448 // Ops[0] = Sampled Type ID
1449 // Ops[1] = Dim ID
1450 // Ops[2] = Depth (Literal Number)
1451 // Ops[3] = Arrayed (Literal Number)
1452 // Ops[4] = MS (Literal Number)
1453 // Ops[5] = Sampled (Literal Number)
1454 // Ops[6] = Image Format ID
1455 //
1456 SPIRVOperandList Ops;
1457
1458 // TODO: Changed Sampled Type according to situations.
1459 uint32_t SampledTyID = lookupType(Type::getFloatTy(Context));
1460 SPIRVOperand *SampledTyIDOp =
1461 new SPIRVOperand(SPIRVOperandType::NUMBERID, SampledTyID);
1462 Ops.push_back(SampledTyIDOp);
1463
1464 spv::Dim DimID = spv::Dim2D;
1465 if (STy->getName().equals("opencl.image3d_ro_t") ||
1466 STy->getName().equals("opencl.image3d_wo_t")) {
1467 DimID = spv::Dim3D;
1468 }
1469 SPIRVOperand *DimIDOp =
1470 new SPIRVOperand(SPIRVOperandType::NUMBERID, DimID);
1471 Ops.push_back(DimIDOp);
1472
1473 // TODO: Set up Depth.
1474 std::vector<uint32_t> LiteralNum;
1475 LiteralNum.push_back(0);
1476 SPIRVOperand *DepthOp =
1477 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1478 Ops.push_back(DepthOp);
1479
1480 // TODO: Set up Arrayed.
1481 LiteralNum.clear();
1482 LiteralNum.push_back(0);
1483 SPIRVOperand *ArrayedOp =
1484 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1485 Ops.push_back(ArrayedOp);
1486
1487 // TODO: Set up MS.
1488 LiteralNum.clear();
1489 LiteralNum.push_back(0);
1490 SPIRVOperand *MSOp =
1491 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1492 Ops.push_back(MSOp);
1493
1494 // TODO: Set up Sampled.
1495 //
1496 // From Spec
1497 //
1498 // 0 indicates this is only known at run time, not at compile time
1499 // 1 indicates will be used with sampler
1500 // 2 indicates will be used without a sampler (a storage image)
1501 uint32_t Sampled = 1;
1502 if (STy->getName().equals("opencl.image2d_wo_t") ||
1503 STy->getName().equals("opencl.image3d_wo_t")) {
1504 Sampled = 2;
1505 }
1506 LiteralNum.clear();
1507 LiteralNum.push_back(Sampled);
1508 SPIRVOperand *SampledOp =
1509 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1510 Ops.push_back(SampledOp);
1511
1512 // TODO: Set up Image Format.
1513 SPIRVOperand *ImageFormatOp = new SPIRVOperand(
1514 SPIRVOperandType::NUMBERID, spv::ImageFormatUnknown);
1515 Ops.push_back(ImageFormatOp);
1516
1517 SPIRVInstruction *Inst =
1518 new SPIRVInstruction(9, spv::OpTypeImage, nextID++, Ops);
1519 SPIRVInstList.push_back(Inst);
1520 break;
1521 }
1522 }
1523
1524 //
1525 // Generate OpTypeStruct
1526 //
1527 // Ops[0] ... Ops[n] = Member IDs
1528 SPIRVOperandList Ops;
1529
1530 for (auto *EleTy : STy->elements()) {
1531 uint32_t EleTyID = lookupType(EleTy);
1532
1533 // Check OpTypeRuntimeArray.
1534 if (isa<PointerType>(EleTy)) {
1535 for (auto ArgGV : ArgGVMap) {
1536 Type *ArgTy = ArgGV.first->getType();
1537 if (ArgTy == EleTy) {
1538 assert(0 != OpRuntimeTyMap.count(EleTy));
1539 EleTyID = OpRuntimeTyMap[EleTy];
1540 }
1541 }
1542 }
1543
1544 SPIRVOperand *EleTyOp =
1545 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1546 Ops.push_back(EleTyOp);
1547 }
1548
1549 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
1550 uint32_t STyID = nextID;
1551
1552 SPIRVInstruction *Inst =
1553 new SPIRVInstruction(WordCount, spv::OpTypeStruct, nextID++, Ops);
1554 SPIRVInstList.push_back(Inst);
1555
1556 // Generate OpMemberDecorate.
1557 auto DecoInsertPoint =
1558 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
1559 [](SPIRVInstruction *Inst) -> bool {
1560 return Inst->getOpcode() != spv::OpDecorate &&
1561 Inst->getOpcode() != spv::OpMemberDecorate &&
1562 Inst->getOpcode() != spv::OpExtInstImport;
1563 });
1564
David Netoc463b372017-08-10 15:32:21 -04001565 const auto StructLayout = DL.getStructLayout(STy);
1566
David Neto22f144c2017-06-12 14:26:21 -04001567 for (unsigned MemberIdx = 0; MemberIdx < STy->getNumElements();
1568 MemberIdx++) {
1569 // Ops[0] = Structure Type ID
1570 // Ops[1] = Member Index(Literal Number)
1571 // Ops[2] = Decoration (Offset)
1572 // Ops[3] = Byte Offset (Literal Number)
1573 Ops.clear();
1574
1575 SPIRVOperand *STyIDOp =
1576 new SPIRVOperand(SPIRVOperandType::NUMBERID, STyID);
1577 Ops.push_back(STyIDOp);
1578
1579 std::vector<uint32_t> LiteralNum;
1580 LiteralNum.push_back(MemberIdx);
1581 SPIRVOperand *MemberIdxOp =
1582 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1583 Ops.push_back(MemberIdxOp);
1584
1585 SPIRVOperand *DecoOp =
1586 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationOffset);
1587 Ops.push_back(DecoOp);
1588
1589 LiteralNum.clear();
David Netoc463b372017-08-10 15:32:21 -04001590 const auto ByteOffset =
1591 uint32_t(StructLayout->getElementOffset(MemberIdx));
David Neto22f144c2017-06-12 14:26:21 -04001592 LiteralNum.push_back(ByteOffset);
1593 SPIRVOperand *ByteOffsetOp =
1594 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1595 Ops.push_back(ByteOffsetOp);
1596
1597 SPIRVInstruction *DecoInst =
1598 new SPIRVInstruction(5, spv::OpMemberDecorate, 0 /* No id */, Ops);
1599 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
David Neto22f144c2017-06-12 14:26:21 -04001600 }
1601
1602 // Generate OpDecorate.
1603 for (auto ArgGV : ArgGVMap) {
1604 Type *ArgGVTy = ArgGV.second->getType();
1605 PointerType *PTy = cast<PointerType>(ArgGVTy);
1606 Type *ArgTy = PTy->getElementType();
1607
1608 // Struct type from argument is already distinguished with the other
1609 // struct types on llvm types. As a result, if current processing struct
1610 // type is same with argument type, we can generate OpDecorate with
1611 // Block or BufferBlock.
1612 if (ArgTy == STy) {
1613 // Ops[0] = Target ID
1614 // Ops[1] = Decoration (Block or BufferBlock)
1615 Ops.clear();
1616
1617 SPIRVOperand *STyIDOp =
1618 new SPIRVOperand(SPIRVOperandType::NUMBERID, STyID);
1619 Ops.push_back(STyIDOp);
1620
David Neto6e392822017-08-04 14:06:10 -04001621 // Use Block decorations with StorageBuffer storage class.
1622 const spv::Decoration Deco = spv::DecorationBlock;
David Neto22f144c2017-06-12 14:26:21 -04001623
1624 SPIRVOperand *DecoOp =
1625 new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
1626 Ops.push_back(DecoOp);
1627
1628 SPIRVInstruction *DecoInst =
1629 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
1630 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
1631 break;
1632 }
1633 }
1634 break;
1635 }
1636 case Type::IntegerTyID: {
1637 unsigned BitWidth = Ty->getPrimitiveSizeInBits();
1638
1639 if (BitWidth == 1) {
1640 SPIRVInstruction *Inst =
1641 new SPIRVInstruction(2, spv::OpTypeBool, nextID++, {});
1642 SPIRVInstList.push_back(Inst);
1643 } else {
1644 // i8 is added to TypeMap as i32.
David Neto391aeb12017-08-26 15:51:58 -04001645 // No matter what LLVM type is requested first, always alias the
1646 // second one's SPIR-V type to be the same as the one we generated
1647 // first.
1648 int aliasToWidth = 0;
David Neto22f144c2017-06-12 14:26:21 -04001649 if (BitWidth == 8) {
David Neto391aeb12017-08-26 15:51:58 -04001650 aliasToWidth = 32;
David Neto22f144c2017-06-12 14:26:21 -04001651 BitWidth = 32;
David Neto391aeb12017-08-26 15:51:58 -04001652 } else if (BitWidth == 32) {
1653 aliasToWidth = 8;
1654 }
1655 if (aliasToWidth) {
1656 Type* otherType = Type::getIntNTy(Ty->getContext(), aliasToWidth);
1657 auto where = TypeMap.find(otherType);
1658 if (where == TypeMap.end()) {
1659 // Go ahead and make it, but also map the other type to it.
1660 TypeMap[otherType] = nextID;
1661 } else {
1662 // Alias this SPIR-V type the existing type.
1663 TypeMap[Ty] = where->second;
1664 break;
1665 }
David Neto22f144c2017-06-12 14:26:21 -04001666 }
1667
1668 SPIRVOperand *Ops[2] = {
1669 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, BitWidth),
1670 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, 0u)};
1671
1672 SPIRVInstList.push_back(
1673 new SPIRVInstruction(4, spv::OpTypeInt, nextID++, Ops));
1674 }
1675 break;
1676 }
1677 case Type::HalfTyID:
1678 case Type::FloatTyID:
1679 case Type::DoubleTyID: {
1680 SPIRVOperand *WidthOp = new SPIRVOperand(
1681 SPIRVOperandType::LITERAL_INTEGER, Ty->getPrimitiveSizeInBits());
1682
1683 SPIRVInstList.push_back(
1684 new SPIRVInstruction(3, spv::OpTypeFloat, nextID++, WidthOp));
1685 break;
1686 }
1687 case Type::ArrayTyID: {
1688 LLVMContext &Context = Ty->getContext();
1689 ArrayType *ArrTy = cast<ArrayType>(Ty);
1690 //
1691 // Generate OpConstant and OpTypeArray.
1692 //
1693
1694 //
1695 // Generate OpConstant for array length.
1696 //
1697 // Ops[0] = Result Type ID
1698 // Ops[1] .. Ops[n] = Values LiteralNumber
1699 SPIRVOperandList Ops;
1700
1701 Type *LengthTy = Type::getInt32Ty(Context);
1702 uint32_t ResTyID = lookupType(LengthTy);
1703 SPIRVOperand *ResTyOp =
1704 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
1705 Ops.push_back(ResTyOp);
1706
1707 uint64_t Length = ArrTy->getArrayNumElements();
1708 assert(Length < UINT32_MAX);
1709 std::vector<uint32_t> LiteralNum;
1710 LiteralNum.push_back(static_cast<uint32_t>(Length));
1711 SPIRVOperand *ValOp =
1712 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1713 Ops.push_back(ValOp);
1714
1715 // Add constant for length to constant list.
1716 Constant *CstLength = ConstantInt::get(LengthTy, Length);
1717 AllocatedVMap[CstLength] = nextID;
1718 VMap[CstLength] = nextID;
1719 uint32_t LengthID = nextID;
1720
1721 SPIRVInstruction *CstInst =
1722 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
1723 SPIRVInstList.push_back(CstInst);
1724
1725 //
1726 // Generate OpTypeArray.
1727 //
1728 // Ops[0] = Element Type ID
1729 // Ops[1] = Array Length Constant ID
1730 Ops.clear();
1731
1732 uint32_t EleTyID = lookupType(ArrTy->getElementType());
1733 SPIRVOperand *EleTyOp =
1734 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleTyID);
1735 Ops.push_back(EleTyOp);
1736
1737 SPIRVOperand *LengthOp =
1738 new SPIRVOperand(SPIRVOperandType::NUMBERID, LengthID);
1739 Ops.push_back(LengthOp);
1740
1741 // Update TypeMap with nextID.
1742 TypeMap[Ty] = nextID;
1743
1744 SPIRVInstruction *ArrayInst =
1745 new SPIRVInstruction(4, spv::OpTypeArray, nextID++, Ops);
1746 SPIRVInstList.push_back(ArrayInst);
1747 break;
1748 }
1749 case Type::VectorTyID: {
1750 // <4 x i8> is changed to i32.
1751 LLVMContext &Context = Ty->getContext();
1752 if (Ty->getVectorElementType() == Type::getInt8Ty(Context)) {
1753 if (Ty->getVectorNumElements() == 4) {
1754 TypeMap[Ty] = lookupType(Ty->getVectorElementType());
1755 break;
1756 } else {
1757 Ty->print(errs());
1758 llvm_unreachable("Support above i8 vector type");
1759 }
1760 }
1761
1762 // Ops[0] = Component Type ID
1763 // Ops[1] = Component Count (Literal Number)
1764 SPIRVOperand *Ops[2] = {
1765 new SPIRVOperand(SPIRVOperandType::NUMBERID,
1766 lookupType(Ty->getVectorElementType())),
1767 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER,
1768 Ty->getVectorNumElements())};
1769
1770 SPIRVInstList.push_back(
1771 new SPIRVInstruction(4, spv::OpTypeVector, nextID++, Ops));
1772 break;
1773 }
1774 case Type::VoidTyID: {
1775 SPIRVInstruction *Inst =
1776 new SPIRVInstruction(2, spv::OpTypeVoid, nextID++, {});
1777 SPIRVInstList.push_back(Inst);
1778 break;
1779 }
1780 case Type::FunctionTyID: {
1781 // Generate SPIRV instruction for function type.
1782 FunctionType *FTy = cast<FunctionType>(Ty);
1783
1784 // Ops[0] = Return Type ID
1785 // Ops[1] ... Ops[n] = Parameter Type IDs
1786 SPIRVOperandList Ops;
1787
1788 // Find SPIRV instruction for return type
1789 uint32_t RetTyID = lookupType(FTy->getReturnType());
1790
1791 SPIRVOperand *RetTyOp =
1792 new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
1793 Ops.push_back(RetTyOp);
1794
1795 // Find SPIRV instructions for parameter types
1796 for (unsigned k = 0; k < FTy->getNumParams(); k++) {
1797 // Find SPIRV instruction for parameter type.
1798 auto ParamTy = FTy->getParamType(k);
1799 if (ParamTy->isPointerTy()) {
1800 auto PointeeTy = ParamTy->getPointerElementType();
1801 if (PointeeTy->isStructTy() &&
1802 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
1803 ParamTy = PointeeTy;
1804 }
1805 }
1806
1807 uint32_t ParamTyID = lookupType(ParamTy);
1808 SPIRVOperand *ParamTyOp =
1809 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParamTyID);
1810 Ops.push_back(ParamTyOp);
1811 }
1812
1813 // Return type id is included in operand list.
1814 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
1815
1816 SPIRVInstruction *Inst =
1817 new SPIRVInstruction(WordCount, spv::OpTypeFunction, nextID++, Ops);
1818 SPIRVInstList.push_back(Inst);
1819 break;
1820 }
1821 }
1822 }
1823
1824 // Generate OpTypeSampledImage.
1825 TypeMapType &OpImageTypeMap = getImageTypeMap();
1826 for (auto &ImageType : OpImageTypeMap) {
1827 //
1828 // Generate OpTypeSampledImage.
1829 //
1830 // Ops[0] = Image Type ID
1831 //
1832 SPIRVOperandList Ops;
1833
1834 Type *ImgTy = ImageType.first;
1835 uint32_t ImgTyID = TypeMap[ImgTy];
1836 SPIRVOperand *ImgTyOp =
1837 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImgTyID);
1838 Ops.push_back(ImgTyOp);
1839
1840 // Update OpImageTypeMap.
1841 ImageType.second = nextID;
1842
1843 SPIRVInstruction *Inst =
1844 new SPIRVInstruction(3, spv::OpTypeSampledImage, nextID++, Ops);
1845 SPIRVInstList.push_back(Inst);
1846 }
1847}
1848
1849void SPIRVProducerPass::GenerateSPIRVConstants() {
1850 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
1851 ValueMapType &VMap = getValueMap();
1852 ValueMapType &AllocatedVMap = getAllocatedValueMap();
1853 ValueList &CstList = getConstantList();
1854
1855 for (uint32_t i = 0; i < CstList.size(); i++) {
David Netofb9a7972017-08-25 17:08:24 -04001856 // UniqueVector ids are 1-based.
1857 Constant *Cst = cast<Constant>(CstList[i+1]);
David Neto22f144c2017-06-12 14:26:21 -04001858
1859 // OpTypeArray's constant was already generated.
David Netofb9a7972017-08-25 17:08:24 -04001860 if (AllocatedVMap.find_as(Cst) != AllocatedVMap.end()) {
David Neto22f144c2017-06-12 14:26:21 -04001861 continue;
1862 }
1863
David Netofb9a7972017-08-25 17:08:24 -04001864 // Set ValueMap with nextID for reference later.
David Neto22f144c2017-06-12 14:26:21 -04001865 VMap[Cst] = nextID;
1866
1867 //
1868 // Generate OpConstant.
1869 //
1870
1871 // Ops[0] = Result Type ID
1872 // Ops[1] .. Ops[n] = Values LiteralNumber
1873 SPIRVOperandList Ops;
1874
1875 uint32_t ResTyID = lookupType(Cst->getType());
1876 SPIRVOperand *ResTyIDOp =
1877 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
1878 Ops.push_back(ResTyIDOp);
1879
1880 std::vector<uint32_t> LiteralNum;
1881 uint16_t WordCount = 0;
1882 spv::Op Opcode = spv::OpNop;
1883
1884 if (isa<UndefValue>(Cst)) {
1885 // Ops[0] = Result Type ID
1886 Opcode = spv::OpUndef;
1887 WordCount = 3;
1888 } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(Cst)) {
1889 unsigned BitWidth = CI->getBitWidth();
1890 if (BitWidth == 1) {
1891 // If the bitwidth of constant is 1, generate OpConstantTrue or
1892 // OpConstantFalse.
1893 if (CI->getZExtValue()) {
1894 // Ops[0] = Result Type ID
1895 Opcode = spv::OpConstantTrue;
1896 } else {
1897 // Ops[0] = Result Type ID
1898 Opcode = spv::OpConstantFalse;
1899 }
1900 WordCount = 3;
1901 } else {
1902 auto V = CI->getZExtValue();
1903 LiteralNum.push_back(V & 0xFFFFFFFF);
1904
1905 if (BitWidth > 32) {
1906 LiteralNum.push_back(V >> 32);
1907 }
1908
1909 Opcode = spv::OpConstant;
1910 WordCount = static_cast<uint16_t>(3 + LiteralNum.size());
1911
1912 SPIRVOperand *CstValue =
1913 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1914 Ops.push_back(CstValue);
1915 }
1916 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Cst)) {
1917 uint64_t FPVal = CFP->getValueAPF().bitcastToAPInt().getZExtValue();
1918 Type *CFPTy = CFP->getType();
1919 if (CFPTy->isFloatTy()) {
1920 LiteralNum.push_back(FPVal & 0xFFFFFFFF);
1921 } else {
1922 CFPTy->print(errs());
1923 llvm_unreachable("Implement this ConstantFP Type");
1924 }
1925
1926 Opcode = spv::OpConstant;
1927 WordCount = static_cast<uint16_t>(3 + LiteralNum.size());
1928
1929 SPIRVOperand *CstValue =
1930 new SPIRVOperand(SPIRVOperandType::LITERAL_FLOAT, LiteralNum);
1931 Ops.push_back(CstValue);
1932 } else if (isa<ConstantDataSequential>(Cst) &&
1933 cast<ConstantDataSequential>(Cst)->isString()) {
1934 Cst->print(errs());
1935 llvm_unreachable("Implement this Constant");
1936
1937 } else if (const ConstantDataSequential *CDS =
1938 dyn_cast<ConstantDataSequential>(Cst)) {
David Neto49351ac2017-08-26 17:32:20 -04001939 // Let's convert <4 x i8> constant to int constant specially.
1940 // This case occurs when all the values are specified as constant
1941 // ints.
1942 Type *CstTy = Cst->getType();
1943 if (is4xi8vec(CstTy)) {
1944 LLVMContext &Context = CstTy->getContext();
1945
1946 //
1947 // Generate OpConstant with OpTypeInt 32 0.
1948 //
1949 uint64_t IntValue = 0;
1950 for (int i = 0; i < 4; i++) {
1951 const uint64_t Val = CDS->getElementAsInteger(i);
1952 IntValue = (IntValue << 8) | (Val & 0xffu);
1953 }
1954
1955 Type *i32 = Type::getInt32Ty(Context);
1956 Constant *CstInt = ConstantInt::get(i32, IntValue);
1957 // If this constant is already registered on VMap, use it.
1958 if (VMap.count(CstInt)) {
1959 uint32_t CstID = VMap[CstInt];
1960 VMap[Cst] = CstID;
1961 continue;
1962 }
1963
1964 LiteralNum.push_back(IntValue);
1965 SPIRVOperand *CstValue =
1966 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
1967 Ops.push_back(CstValue);
1968
1969 SPIRVInstruction *CstInst =
1970 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
1971 SPIRVInstList.push_back(CstInst);
1972
1973 continue;
1974 }
1975
1976 // A normal constant-data-sequential case.
David Neto22f144c2017-06-12 14:26:21 -04001977 for (unsigned k = 0; k < CDS->getNumElements(); k++) {
1978 Constant *EleCst = CDS->getElementAsConstant(k);
1979 uint32_t EleCstID = VMap[EleCst];
1980 SPIRVOperand *EleCstIDOp =
1981 new SPIRVOperand(SPIRVOperandType::NUMBERID, EleCstID);
1982 Ops.push_back(EleCstIDOp);
1983 }
1984
1985 Opcode = spv::OpConstantComposite;
1986 WordCount = static_cast<uint16_t>(3 + CDS->getNumElements());
1987 } else if (const ConstantAggregate *CA = dyn_cast<ConstantAggregate>(Cst)) {
1988 // Let's convert <4 x i8> constant to int constant specially.
David Neto49351ac2017-08-26 17:32:20 -04001989 // This case occurs when at least one of the values is an undef.
David Neto22f144c2017-06-12 14:26:21 -04001990 Type *CstTy = Cst->getType();
1991 if (is4xi8vec(CstTy)) {
1992 LLVMContext &Context = CstTy->getContext();
1993
1994 //
1995 // Generate OpConstant with OpTypeInt 32 0.
1996 //
1997 uint64_t IntValue = 0;
1998 uint32_t Idx = 0;
1999 for (User::const_op_iterator I = Cst->op_begin(), E = Cst->op_end();
2000 I != E; ++I) {
2001 uint64_t Val = 0;
David Neto49351ac2017-08-26 17:32:20 -04002002 const Value* CV = *I;
2003 if (auto* CI = dyn_cast<ConstantInt>(CV)) {
2004 Val = CI->getZExtValue();
David Neto22f144c2017-06-12 14:26:21 -04002005 }
David Neto49351ac2017-08-26 17:32:20 -04002006 IntValue = (IntValue << 8) | (Val & 0xffu);
David Neto22f144c2017-06-12 14:26:21 -04002007 }
2008
David Neto49351ac2017-08-26 17:32:20 -04002009 Type *i32 = Type::getInt32Ty(Context);
2010 Constant *CstInt = ConstantInt::get(i32, IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002011 // If this constant is already registered on VMap, use it.
2012 if (VMap.count(CstInt)) {
2013 uint32_t CstID = VMap[CstInt];
2014 VMap[Cst] = CstID;
David Neto19a1bad2017-08-25 15:01:41 -04002015 continue;
David Neto22f144c2017-06-12 14:26:21 -04002016 }
2017
David Neto49351ac2017-08-26 17:32:20 -04002018 LiteralNum.push_back(IntValue);
David Neto22f144c2017-06-12 14:26:21 -04002019 SPIRVOperand *CstValue =
2020 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2021 Ops.push_back(CstValue);
2022
2023 SPIRVInstruction *CstInst =
2024 new SPIRVInstruction(4, spv::OpConstant, nextID++, Ops);
2025 SPIRVInstList.push_back(CstInst);
2026
David Neto19a1bad2017-08-25 15:01:41 -04002027 continue;
David Neto22f144c2017-06-12 14:26:21 -04002028 }
2029
2030 // We use a constant composite in SPIR-V for our constant aggregate in
2031 // LLVM.
2032 Opcode = spv::OpConstantComposite;
2033 WordCount = static_cast<uint16_t>(3 + CA->getNumOperands());
2034
2035 for (unsigned k = 0; k < CA->getNumOperands(); k++) {
2036 // Look up the ID of the element of this aggregate (which we will
2037 // previously have created a constant for).
2038 uint32_t ElementConstantID = VMap[CA->getAggregateElement(k)];
2039
2040 // And add an operand to the composite we are constructing
2041 Ops.push_back(
2042 new SPIRVOperand(SPIRVOperandType::NUMBERID, ElementConstantID));
2043 }
2044 } else if (Cst->isNullValue()) {
2045 Opcode = spv::OpConstantNull;
2046 WordCount = 3;
2047 } else {
2048 Cst->print(errs());
2049 llvm_unreachable("Unsupported Constant???");
2050 }
2051
2052 SPIRVInstruction *CstInst =
2053 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
2054 SPIRVInstList.push_back(CstInst);
2055 }
2056}
2057
2058void SPIRVProducerPass::GenerateSamplers(Module &M) {
2059 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2060 ValueMapType &VMap = getValueMap();
2061
2062 DenseMap<unsigned, unsigned> SamplerLiteralToIDMap;
2063
2064 unsigned BindingIdx = 0;
2065
2066 // Generate the sampler map.
2067 for (auto SamplerLiteral : getSamplerMap()) {
2068 // Generate OpVariable.
2069 //
2070 // GIDOps[0] : Result Type ID
2071 // GIDOps[1] : Storage Class
2072 SPIRVOperandList Ops;
2073
2074 Ops.push_back(
2075 new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(SamplerTy)));
2076
2077 spv::StorageClass StorageClass = spv::StorageClassUniformConstant;
2078 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass));
2079
2080 SPIRVInstruction *Inst = new SPIRVInstruction(
2081 static_cast<uint16_t>(2 + Ops.size()), spv::OpVariable, nextID, Ops);
2082 SPIRVInstList.push_back(Inst);
2083
David Neto44795152017-07-13 15:45:28 -04002084 SamplerLiteralToIDMap[SamplerLiteral.first] = nextID++;
David Neto22f144c2017-06-12 14:26:21 -04002085
2086 // Find Insert Point for OpDecorate.
2087 auto DecoInsertPoint =
2088 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2089 [](SPIRVInstruction *Inst) -> bool {
2090 return Inst->getOpcode() != spv::OpDecorate &&
2091 Inst->getOpcode() != spv::OpMemberDecorate &&
2092 Inst->getOpcode() != spv::OpExtInstImport;
2093 });
2094
2095 // Ops[0] = Target ID
2096 // Ops[1] = Decoration (DescriptorSet)
2097 // Ops[2] = LiteralNumber according to Decoration
2098 Ops.clear();
2099
David Neto44795152017-07-13 15:45:28 -04002100 SPIRVOperand *ArgIDOp =
2101 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2102 SamplerLiteralToIDMap[SamplerLiteral.first]);
David Neto22f144c2017-06-12 14:26:21 -04002103 Ops.push_back(ArgIDOp);
2104
2105 spv::Decoration Deco = spv::DecorationDescriptorSet;
2106 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2107 Ops.push_back(DecoOp);
2108
David Neto44795152017-07-13 15:45:28 -04002109 descriptorMapOut << "sampler," << SamplerLiteral.first << ",samplerExpr,\""
2110 << SamplerLiteral.second << "\",descriptorSet,0,binding,"
David Netoc2c368d2017-06-30 16:50:17 -04002111 << BindingIdx << "\n";
2112
David Neto22f144c2017-06-12 14:26:21 -04002113 std::vector<uint32_t> LiteralNum;
2114 LiteralNum.push_back(0);
2115 SPIRVOperand *DescSet =
2116 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2117 Ops.push_back(DescSet);
2118
2119 SPIRVInstruction *DescDecoInst =
2120 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2121 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2122
2123 // Ops[0] = Target ID
2124 // Ops[1] = Decoration (Binding)
2125 // Ops[2] = LiteralNumber according to Decoration
2126 Ops.clear();
2127
2128 Ops.push_back(ArgIDOp);
2129
2130 Deco = spv::DecorationBinding;
2131 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2132 Ops.push_back(DecoOp);
2133
2134 LiteralNum.clear();
2135 LiteralNum.push_back(BindingIdx++);
2136 SPIRVOperand *Binding =
2137 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2138 Ops.push_back(Binding);
2139
2140 SPIRVInstruction *BindDecoInst =
2141 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2142 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2143 }
2144
2145 const char *TranslateSamplerFunctionName = "__translate_sampler_initializer";
2146
2147 auto SamplerFunction = M.getFunction(TranslateSamplerFunctionName);
2148
2149 // If there are no uses of the sampler function, no work to do!
2150 if (!SamplerFunction) {
2151 return;
2152 }
2153
2154 // Iterate through the users of the sampler function.
2155 for (auto User : SamplerFunction->users()) {
2156 if (auto CI = dyn_cast<CallInst>(User)) {
2157 // Get the literal used to initialize the sampler.
2158 auto Constant = dyn_cast<ConstantInt>(CI->getArgOperand(0));
2159
2160 if (!Constant) {
2161 CI->getArgOperand(0)->print(errs());
2162 llvm_unreachable("Argument of sampler initializer was non-constant!");
2163 }
2164
2165 auto SamplerLiteral = static_cast<unsigned>(Constant->getZExtValue());
2166
2167 if (0 == SamplerLiteralToIDMap.count(SamplerLiteral)) {
2168 Constant->print(errs());
2169 llvm_unreachable("Sampler literal was not found in sampler map!");
2170 }
2171
2172 // Calls to the sampler literal function to initialize a sampler are
2173 // re-routed to the global variables declared for the sampler.
2174 VMap[CI] = SamplerLiteralToIDMap[SamplerLiteral];
2175 }
2176 }
2177}
2178
2179void SPIRVProducerPass::GenerateGlobalVar(GlobalVariable &GV) {
2180 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2181 ValueMapType &VMap = getValueMap();
2182 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2183
2184 const spv::BuiltIn BuiltinType = GetBuiltin(GV.getName());
2185 Type *Ty = GV.getType();
2186 PointerType *PTy = cast<PointerType>(Ty);
2187
2188 uint32_t InitializerID = 0;
2189
2190 // Workgroup size is handled differently (it goes into a constant)
2191 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2192 std::vector<bool> HasMDVec;
2193 uint32_t PrevXDimCst = 0xFFFFFFFF;
2194 uint32_t PrevYDimCst = 0xFFFFFFFF;
2195 uint32_t PrevZDimCst = 0xFFFFFFFF;
2196 for (Function &Func : *GV.getParent()) {
2197 if (Func.isDeclaration()) {
2198 continue;
2199 }
2200
2201 // We only need to check kernels.
2202 if (Func.getCallingConv() != CallingConv::SPIR_KERNEL) {
2203 continue;
2204 }
2205
2206 if (const MDNode *MD =
2207 dyn_cast<Function>(&Func)->getMetadata("reqd_work_group_size")) {
2208 uint32_t CurXDimCst = static_cast<uint32_t>(
2209 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2210 uint32_t CurYDimCst = static_cast<uint32_t>(
2211 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2212 uint32_t CurZDimCst = static_cast<uint32_t>(
2213 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2214
2215 if (PrevXDimCst == 0xFFFFFFFF && PrevYDimCst == 0xFFFFFFFF &&
2216 PrevZDimCst == 0xFFFFFFFF) {
2217 PrevXDimCst = CurXDimCst;
2218 PrevYDimCst = CurYDimCst;
2219 PrevZDimCst = CurZDimCst;
2220 } else if (CurXDimCst != PrevXDimCst || CurYDimCst != PrevYDimCst ||
2221 CurZDimCst != PrevZDimCst) {
2222 llvm_unreachable(
2223 "reqd_work_group_size must be the same across all kernels");
2224 } else {
2225 continue;
2226 }
2227
2228 //
2229 // Generate OpConstantComposite.
2230 //
2231 // Ops[0] : Result Type ID
2232 // Ops[1] : Constant size for x dimension.
2233 // Ops[2] : Constant size for y dimension.
2234 // Ops[3] : Constant size for z dimension.
2235 SPIRVOperandList Ops;
2236
2237 uint32_t XDimCstID =
2238 VMap[mdconst::extract<ConstantInt>(MD->getOperand(0))];
2239 uint32_t YDimCstID =
2240 VMap[mdconst::extract<ConstantInt>(MD->getOperand(1))];
2241 uint32_t ZDimCstID =
2242 VMap[mdconst::extract<ConstantInt>(MD->getOperand(2))];
2243
2244 InitializerID = nextID;
2245
2246 Ops.push_back(
2247 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2248 lookupType(Ty->getPointerElementType())));
2249
2250 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XDimCstID));
2251 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, YDimCstID));
2252 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ZDimCstID));
2253
2254 SPIRVInstruction *Inst =
2255 new SPIRVInstruction(6, spv::OpConstantComposite, nextID++, Ops);
2256 SPIRVInstList.push_back(Inst);
2257
2258 HasMDVec.push_back(true);
2259 } else {
2260 HasMDVec.push_back(false);
2261 }
2262 }
2263
2264 // Check all kernels have same definitions for work_group_size.
2265 bool HasMD = false;
2266 if (!HasMDVec.empty()) {
2267 HasMD = HasMDVec[0];
2268 for (uint32_t i = 1; i < HasMDVec.size(); i++) {
2269 if (HasMD != HasMDVec[i]) {
2270 llvm_unreachable(
2271 "Kernels should have consistent work group size definition");
2272 }
2273 }
2274 }
2275
2276 // If all kernels do not have metadata for reqd_work_group_size, generate
2277 // OpSpecConstants for x/y/z dimension.
2278 if (!HasMD) {
2279 //
2280 // Generate OpSpecConstants for x/y/z dimension.
2281 //
2282 // Ops[0] : Result Type ID
2283 // Ops[1] : Constant size for x/y/z dimension (Literal Number).
2284 uint32_t XDimCstID = 0;
2285 uint32_t YDimCstID = 0;
2286 uint32_t ZDimCstID = 0;
2287
2288 // X Dimension
2289 SPIRVOperandList Ops;
2290
2291 Ops.push_back(new SPIRVOperand(
2292 SPIRVOperandType::NUMBERID,
2293 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2294
2295 std::vector<uint32_t> LiteralNum;
2296 LiteralNum.push_back(1);
2297 SPIRVOperand *XDim =
2298 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2299 Ops.push_back(XDim);
2300
2301 XDimCstID = nextID;
2302 BuiltinDimVec.push_back(XDimCstID);
2303
2304 SPIRVInstruction *XDimCstInst =
2305 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2306 SPIRVInstList.push_back(XDimCstInst);
2307
2308 // Y Dimension
2309 Ops.clear();
2310
2311 Ops.push_back(new SPIRVOperand(
2312 SPIRVOperandType::NUMBERID,
2313 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2314
2315 LiteralNum.clear();
2316 LiteralNum.push_back(1);
2317 SPIRVOperand *YDim =
2318 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2319 Ops.push_back(YDim);
2320
2321 YDimCstID = nextID;
2322 BuiltinDimVec.push_back(YDimCstID);
2323
2324 SPIRVInstruction *YDimCstInst =
2325 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2326 SPIRVInstList.push_back(YDimCstInst);
2327
2328 // Z Dimension
2329 Ops.clear();
2330
2331 Ops.push_back(new SPIRVOperand(
2332 SPIRVOperandType::NUMBERID,
2333 lookupType(Ty->getPointerElementType()->getSequentialElementType())));
2334
2335 LiteralNum.clear();
2336 LiteralNum.push_back(1);
2337 SPIRVOperand *ZDim =
2338 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2339 Ops.push_back(ZDim);
2340
2341 ZDimCstID = nextID;
2342 BuiltinDimVec.push_back(ZDimCstID);
2343
2344 SPIRVInstruction *ZDimCstInst =
2345 new SPIRVInstruction(4, spv::OpSpecConstant, nextID++, Ops);
2346 SPIRVInstList.push_back(ZDimCstInst);
2347
2348 //
2349 // Generate OpSpecConstantComposite.
2350 //
2351 // Ops[0] : Result Type ID
2352 // Ops[1] : Constant size for x dimension.
2353 // Ops[2] : Constant size for y dimension.
2354 // Ops[3] : Constant size for z dimension.
2355 InitializerID = nextID;
2356
2357 Ops.clear();
2358
2359 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
2360 lookupType(Ty->getPointerElementType())));
2361
2362 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XDimCstID));
2363 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, YDimCstID));
2364 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ZDimCstID));
2365
2366 SPIRVInstruction *Inst =
2367 new SPIRVInstruction(6, spv::OpSpecConstantComposite, nextID++, Ops);
2368 SPIRVInstList.push_back(Inst);
2369 }
2370 }
2371
2372 if (GV.hasInitializer()) {
2373 InitializerID = VMap[GV.getInitializer()];
2374 }
2375
2376 VMap[&GV] = nextID;
2377
2378 //
2379 // Generate OpVariable.
2380 //
2381 // GIDOps[0] : Result Type ID
2382 // GIDOps[1] : Storage Class
2383 SPIRVOperandList Ops;
2384
2385 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(Ty)));
2386
2387 spv::StorageClass StorageClass = GetStorageClass(PTy->getAddressSpace());
2388 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass));
2389
2390 if (0 != InitializerID) {
2391 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, InitializerID));
2392 }
2393
2394 SPIRVInstruction *Inst = new SPIRVInstruction(
2395 static_cast<uint16_t>(2 + Ops.size()), spv::OpVariable, nextID++, Ops);
2396 SPIRVInstList.push_back(Inst);
2397
2398 // If we have a builtin.
2399 if (spv::BuiltInMax != BuiltinType) {
2400 // Find Insert Point for OpDecorate.
2401 auto DecoInsertPoint =
2402 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2403 [](SPIRVInstruction *Inst) -> bool {
2404 return Inst->getOpcode() != spv::OpDecorate &&
2405 Inst->getOpcode() != spv::OpMemberDecorate &&
2406 Inst->getOpcode() != spv::OpExtInstImport;
2407 });
2408 //
2409 // Generate OpDecorate.
2410 //
2411 // DOps[0] = Target ID
2412 // DOps[1] = Decoration (Builtin)
2413 // DOps[2] = BuiltIn ID
2414 uint32_t ResultID;
2415
2416 // WorkgroupSize is different, we decorate the constant composite that has
2417 // its value, rather than the variable that we use to access the value.
2418 if (spv::BuiltInWorkgroupSize == BuiltinType) {
2419 ResultID = InitializerID;
2420 } else {
2421 ResultID = VMap[&GV];
2422 }
2423
2424 SPIRVOperandList DOps;
2425 SPIRVOperand *ResultIDOp =
2426 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResultID);
2427 DOps.push_back(ResultIDOp);
2428
2429 spv::Decoration Deco = spv::DecorationBuiltIn;
2430 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2431 DOps.push_back(DecoOp);
2432
2433 SPIRVOperand *Builtin =
2434 new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinType);
2435 DOps.push_back(Builtin);
2436
2437 SPIRVInstruction *DescDecoInst =
2438 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, DOps);
2439 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2440 }
2441}
2442
2443void SPIRVProducerPass::GenerateFuncPrologue(Function &F) {
2444 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2445 ValueMapType &VMap = getValueMap();
2446 EntryPointVecType &EntryPoints = getEntryPointVec();
2447 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
2448 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
2449 auto &GlobalConstFuncTyMap = getGlobalConstFuncTypeMap();
2450 auto &GlobalConstArgSet = getGlobalConstArgSet();
David Netoc2c368d2017-06-30 16:50:17 -04002451 const DataLayout& dataLayout(F.getParent()->getDataLayout());
David Neto22f144c2017-06-12 14:26:21 -04002452
2453 FunctionType *FTy = F.getFunctionType();
2454
2455 //
2456 // Generate OpVariable and OpDecorate for kernel function with arguments.
2457 //
2458 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2459
2460 // Find Insert Point for OpDecorate.
2461 auto DecoInsertPoint =
2462 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
2463 [](SPIRVInstruction *Inst) -> bool {
2464 return Inst->getOpcode() != spv::OpDecorate &&
2465 Inst->getOpcode() != spv::OpMemberDecorate &&
2466 Inst->getOpcode() != spv::OpExtInstImport;
2467 });
2468
2469 uint32_t DescriptorSetIdx = (0 < getSamplerMap().size()) ? 1u : 0u;
2470 for (Function &Func : *F.getParent()) {
2471 if (Func.isDeclaration()) {
2472 continue;
2473 }
2474
2475 if (Func.getCallingConv() == CallingConv::SPIR_KERNEL) {
2476 if (&Func == &F) {
2477 break;
2478 }
2479 DescriptorSetIdx++;
2480 }
2481 }
2482
David Neto156783e2017-07-05 15:39:41 -04002483 const auto *ArgMap = F.getMetadata("kernel_arg_map");
2484 // Emit descriptor map entries, if there was explicit metadata
2485 // attached.
2486 if (ArgMap) {
2487 for (const auto &arg : ArgMap->operands()) {
2488 const MDNode *arg_node = dyn_cast<MDNode>(arg.get());
2489 assert(arg_node->getNumOperands() == 4);
2490 const auto name =
2491 dyn_cast<MDString>(arg_node->getOperand(0))->getString();
2492 const auto old_index =
2493 dyn_extract<ConstantInt>(arg_node->getOperand(1))->getZExtValue();
2494 const auto new_index =
2495 dyn_extract<ConstantInt>(arg_node->getOperand(2))->getZExtValue();
2496 const auto offset =
2497 dyn_extract<ConstantInt>(arg_node->getOperand(3))->getZExtValue();
2498 descriptorMapOut << "kernel," << F.getName() << ",arg," << name
2499 << ",argOrdinal," << old_index << ",descriptorSet,"
2500 << DescriptorSetIdx << ",binding," << new_index
2501 << ",offset," << offset << "\n";
2502 }
2503 }
2504
David Neto22f144c2017-06-12 14:26:21 -04002505 uint32_t BindingIdx = 0;
2506 for (auto &Arg : F.args()) {
2507 Value *NewGV = ArgGVMap[&Arg];
2508 VMap[&Arg] = VMap[NewGV];
2509 ArgGVIDMap[&Arg] = VMap[&Arg];
2510
David Neto156783e2017-07-05 15:39:41 -04002511 // Emit a descriptor map entry for this arg, in case there was no explicit
2512 // kernel arg mapping metadata.
2513 if (!ArgMap) {
2514 descriptorMapOut << "kernel," << F.getName() << ",arg," << Arg.getName()
2515 << ",argOrdinal," << BindingIdx << ",descriptorSet,"
2516 << DescriptorSetIdx << ",binding," << BindingIdx
2517 << ",offset,0\n";
David Netoc2c368d2017-06-30 16:50:17 -04002518 }
2519
David Neto22f144c2017-06-12 14:26:21 -04002520 // Ops[0] = Target ID
2521 // Ops[1] = Decoration (DescriptorSet)
2522 // Ops[2] = LiteralNumber according to Decoration
2523 SPIRVOperandList Ops;
2524
2525 SPIRVOperand *ArgIDOp =
2526 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[&Arg]);
2527 Ops.push_back(ArgIDOp);
2528
2529 spv::Decoration Deco = spv::DecorationDescriptorSet;
2530 SPIRVOperand *DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2531 Ops.push_back(DecoOp);
2532
2533 std::vector<uint32_t> LiteralNum;
2534 LiteralNum.push_back(DescriptorSetIdx);
2535 SPIRVOperand *DescSet =
2536 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2537 Ops.push_back(DescSet);
2538
2539 SPIRVInstruction *DescDecoInst =
2540 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2541 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2542
2543 // Ops[0] = Target ID
2544 // Ops[1] = Decoration (Binding)
2545 // Ops[2] = LiteralNumber according to Decoration
2546 Ops.clear();
2547
2548 Ops.push_back(ArgIDOp);
2549
2550 Deco = spv::DecorationBinding;
2551 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2552 Ops.push_back(DecoOp);
2553
2554 LiteralNum.clear();
2555 LiteralNum.push_back(BindingIdx++);
2556 SPIRVOperand *Binding =
2557 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2558 Ops.push_back(Binding);
2559
2560 SPIRVInstruction *BindDecoInst =
2561 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
2562 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2563
2564 // Handle image type argument.
2565 bool HasReadOnlyImageType = false;
2566 bool HasWriteOnlyImageType = false;
2567 if (PointerType *ArgPTy = dyn_cast<PointerType>(Arg.getType())) {
2568 if (StructType *STy = dyn_cast<StructType>(ArgPTy->getElementType())) {
2569 if (STy->isOpaque()) {
2570 if (STy->getName().equals("opencl.image2d_ro_t") ||
2571 STy->getName().equals("opencl.image3d_ro_t")) {
2572 HasReadOnlyImageType = true;
2573 } else if (STy->getName().equals("opencl.image2d_wo_t") ||
2574 STy->getName().equals("opencl.image3d_wo_t")) {
2575 HasWriteOnlyImageType = true;
2576 }
2577 }
2578 }
2579 }
2580
2581 if (HasReadOnlyImageType || HasWriteOnlyImageType) {
2582 // Ops[0] = Target ID
2583 // Ops[1] = Decoration (NonReadable or NonWritable)
2584 Ops.clear();
2585
2586 ArgIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[&Arg]);
2587 Ops.push_back(ArgIDOp);
2588
2589 Deco = spv::DecorationNonReadable;
2590 if (HasReadOnlyImageType) {
2591 Deco = spv::DecorationNonWritable;
2592 }
2593 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2594 Ops.push_back(DecoOp);
2595
2596 DescDecoInst =
2597 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
2598 SPIRVInstList.insert(DecoInsertPoint, DescDecoInst);
2599 }
2600
2601 // Handle const address space.
2602 if (NewGV->getType()->getPointerAddressSpace() ==
2603 AddressSpace::Constant) {
2604 // Ops[0] = Target ID
2605 // Ops[1] = Decoration (NonWriteable)
2606 Ops.clear();
2607
2608 Ops.push_back(ArgIDOp);
2609
2610 Deco = spv::DecorationNonWritable;
2611 DecoOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Deco);
2612 Ops.push_back(DecoOp);
2613
2614 BindDecoInst =
2615 new SPIRVInstruction(3, spv::OpDecorate, 0 /* No id */, Ops);
2616 SPIRVInstList.insert(DecoInsertPoint, BindDecoInst);
2617 }
2618 }
2619 }
2620
2621 //
2622 // Generate OPFunction.
2623 //
2624
2625 // FOps[0] : Result Type ID
2626 // FOps[1] : Function Control
2627 // FOps[2] : Function Type ID
2628 SPIRVOperandList FOps;
2629
2630 // Find SPIRV instruction for return type.
2631 uint32_t RetTyID = lookupType(FTy->getReturnType());
2632 SPIRVOperand *RetTyOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
2633 FOps.push_back(RetTyOp);
2634
2635 // Check function attributes for SPIRV Function Control.
2636 uint32_t FuncControl = spv::FunctionControlMaskNone;
2637 if (F.hasFnAttribute(Attribute::AlwaysInline)) {
2638 FuncControl |= spv::FunctionControlInlineMask;
2639 }
2640 if (F.hasFnAttribute(Attribute::NoInline)) {
2641 FuncControl |= spv::FunctionControlDontInlineMask;
2642 }
2643 // TODO: Check llvm attribute for Function Control Pure.
2644 if (F.hasFnAttribute(Attribute::ReadOnly)) {
2645 FuncControl |= spv::FunctionControlPureMask;
2646 }
2647 // TODO: Check llvm attribute for Function Control Const.
2648 if (F.hasFnAttribute(Attribute::ReadNone)) {
2649 FuncControl |= spv::FunctionControlConstMask;
2650 }
2651
2652 SPIRVOperand *FunctionControlOp =
2653 new SPIRVOperand(SPIRVOperandType::NUMBERID, FuncControl);
2654 FOps.push_back(FunctionControlOp);
2655
2656 uint32_t FTyID;
2657 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2658 SmallVector<Type *, 4> NewFuncParamTys;
2659 FunctionType *NewFTy =
2660 FunctionType::get(FTy->getReturnType(), NewFuncParamTys, false);
2661 FTyID = lookupType(NewFTy);
2662 } else {
2663 // Handle function with global constant parameters.
2664 if (GlobalConstFuncTyMap.count(FTy)) {
2665 FTyID = lookupType(GlobalConstFuncTyMap[FTy].first);
2666 } else {
2667 FTyID = lookupType(FTy);
2668 }
2669 }
2670
2671 SPIRVOperand *FTyOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, FTyID);
2672 FOps.push_back(FTyOp);
2673
2674 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
2675 EntryPoints.push_back(std::make_pair(&F, nextID));
2676 }
2677
2678 VMap[&F] = nextID;
2679
2680 // Generate SPIRV instruction for function.
2681 SPIRVInstruction *FuncInst =
2682 new SPIRVInstruction(5, spv::OpFunction, nextID++, FOps);
2683 SPIRVInstList.push_back(FuncInst);
2684
2685 //
2686 // Generate OpFunctionParameter for Normal function.
2687 //
2688
2689 if (F.getCallingConv() != CallingConv::SPIR_KERNEL) {
2690 // Iterate Argument for name instead of param type from function type.
2691 unsigned ArgIdx = 0;
2692 for (Argument &Arg : F.args()) {
2693 VMap[&Arg] = nextID;
2694
2695 // ParamOps[0] : Result Type ID
2696 SPIRVOperandList ParamOps;
2697
2698 // Find SPIRV instruction for parameter type.
2699 uint32_t ParamTyID = lookupType(Arg.getType());
2700 if (PointerType *PTy = dyn_cast<PointerType>(Arg.getType())) {
2701 if (GlobalConstFuncTyMap.count(FTy)) {
2702 if (ArgIdx == GlobalConstFuncTyMap[FTy].second) {
2703 Type *EleTy = PTy->getPointerElementType();
2704 Type *ArgTy =
2705 PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
2706 ParamTyID = lookupType(ArgTy);
2707 GlobalConstArgSet.insert(&Arg);
2708 }
2709 }
2710 }
2711 SPIRVOperand *ParamTyOp =
2712 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParamTyID);
2713 ParamOps.push_back(ParamTyOp);
2714
2715 // Generate SPIRV instruction for parameter.
2716 SPIRVInstruction *ParamInst =
2717 new SPIRVInstruction(3, spv::OpFunctionParameter, nextID++, ParamOps);
2718 SPIRVInstList.push_back(ParamInst);
2719
2720 ArgIdx++;
2721 }
2722 }
2723}
2724
2725void SPIRVProducerPass::GenerateModuleInfo() {
2726 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
2727 EntryPointVecType &EntryPoints = getEntryPointVec();
2728 ValueMapType &VMap = getValueMap();
2729 ValueList &EntryPointInterfaces = getEntryPointInterfacesVec();
2730 uint32_t &ExtInstImportID = getOpExtInstImportID();
2731 std::vector<uint32_t> &BuiltinDimVec = getBuiltinDimVec();
2732
2733 // Set up insert point.
2734 auto InsertPoint = SPIRVInstList.begin();
2735
2736 //
2737 // Generate OpCapability
2738 //
2739 // TODO: Which llvm information is mapped to SPIRV Capapbility?
2740
2741 // Ops[0] = Capability
2742 SPIRVOperandList Ops;
2743
2744 SPIRVInstruction *CapInst = new SPIRVInstruction(
2745 2, spv::OpCapability, 0 /* No id */,
2746 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::CapabilityShader));
2747 SPIRVInstList.insert(InsertPoint, CapInst);
2748
2749 for (Type *Ty : getTypeList()) {
2750 // Find the i16 type.
2751 if (Ty->isIntegerTy(16)) {
2752 // Generate OpCapability for i16 type.
2753 SPIRVInstList.insert(
2754 InsertPoint,
2755 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2756 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2757 spv::CapabilityInt16)));
2758 } else if (Ty->isIntegerTy(64)) {
2759 // Generate OpCapability for i64 type.
2760 SPIRVInstList.insert(
2761 InsertPoint,
2762 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2763 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2764 spv::CapabilityInt64)));
2765 } else if (Ty->isHalfTy()) {
2766 // Generate OpCapability for half type.
2767 SPIRVInstList.insert(
2768 InsertPoint,
2769 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2770 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2771 spv::CapabilityFloat16)));
2772 } else if (Ty->isDoubleTy()) {
2773 // Generate OpCapability for double type.
2774 SPIRVInstList.insert(
2775 InsertPoint,
2776 new SPIRVInstruction(2, spv::OpCapability, 0 /* No id */,
2777 new SPIRVOperand(SPIRVOperandType::NUMBERID,
2778 spv::CapabilityFloat64)));
2779 } else if (auto *STy = dyn_cast<StructType>(Ty)) {
2780 if (STy->isOpaque()) {
David Neto565571c2017-08-21 12:00:05 -04002781 if (STy->getName().equals("opencl.image2d_wo_t") ||
2782 STy->getName().equals("opencl.image3d_wo_t")) {
David Neto22f144c2017-06-12 14:26:21 -04002783 // Generate OpCapability for write only image type.
2784 SPIRVInstList.insert(
2785 InsertPoint,
2786 new SPIRVInstruction(
2787 2, spv::OpCapability, 0 /* No id */,
2788 new SPIRVOperand(
2789 SPIRVOperandType::NUMBERID,
2790 spv::CapabilityStorageImageWriteWithoutFormat)));
2791 }
2792 }
2793 }
2794 }
2795
2796 if (hasVariablePointers()) {
2797 //
2798 // Generate OpCapability and OpExtension
2799 //
2800
2801 //
2802 // Generate OpCapability.
2803 //
2804 // Ops[0] = Capability
2805 //
2806 Ops.clear();
2807
2808 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
2809 spv::CapabilityVariablePointers));
2810
2811 SPIRVInstList.insert(InsertPoint, new SPIRVInstruction(2, spv::OpCapability,
2812 0 /* No id */, Ops));
2813
2814 //
2815 // Generate OpExtension.
2816 //
2817 // Ops[0] = Name (Literal String)
2818 //
David Netoa772fd12017-08-04 14:17:33 -04002819 for (auto extension : {"SPV_KHR_storage_buffer_storage_class",
2820 "SPV_KHR_variable_pointers"}) {
2821 Ops.clear();
David Neto22f144c2017-06-12 14:26:21 -04002822
David Netoa772fd12017-08-04 14:17:33 -04002823 SPIRVOperand *Name =
2824 new SPIRVOperand(SPIRVOperandType::LITERAL_STRING, extension);
2825 Ops.push_back(Name);
David Neto22f144c2017-06-12 14:26:21 -04002826
David Netoa772fd12017-08-04 14:17:33 -04002827 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
2828 if ((Name->getLiteralStr().size() + 1) % 4) {
2829 NameWordSize += 1;
2830 }
2831
2832 assert((NameWordSize + 1) < UINT16_MAX);
2833 uint16_t WordCount = static_cast<uint16_t>(1 + NameWordSize);
2834
2835 SPIRVInstruction *ExtensionInst =
2836 new SPIRVInstruction(WordCount, spv::OpExtension, 0 /* No id */, Ops);
2837 SPIRVInstList.insert(InsertPoint, ExtensionInst);
David Neto22f144c2017-06-12 14:26:21 -04002838 }
David Neto22f144c2017-06-12 14:26:21 -04002839 }
2840
2841 if (ExtInstImportID) {
2842 ++InsertPoint;
2843 }
2844
2845 //
2846 // Generate OpMemoryModel
2847 //
2848 // Memory model for Vulkan will always be GLSL450.
2849
2850 // Ops[0] = Addressing Model
2851 // Ops[1] = Memory Model
2852 Ops.clear();
2853 SPIRVOperand *AddrModel =
2854 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::AddressingModelLogical);
2855 Ops.push_back(AddrModel);
2856
2857 SPIRVOperand *MemModel =
2858 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::MemoryModelGLSL450);
2859 Ops.push_back(MemModel);
2860
2861 SPIRVInstruction *MemModelInst =
2862 new SPIRVInstruction(3, spv::OpMemoryModel, 0 /* No id */, Ops);
2863 SPIRVInstList.insert(InsertPoint, MemModelInst);
2864
2865 //
2866 // Generate OpEntryPoint
2867 //
2868 for (auto EntryPoint : EntryPoints) {
2869 // Ops[0] = Execution Model
2870 // Ops[1] = EntryPoint ID
2871 // Ops[2] = Name (Literal String)
2872 // ...
2873 //
2874 // TODO: Do we need to consider Interface ID for forward references???
2875 Ops.clear();
2876 SPIRVOperand *ExecModel = new SPIRVOperand(SPIRVOperandType::NUMBERID,
2877 spv::ExecutionModelGLCompute);
2878 Ops.push_back(ExecModel);
2879
2880 SPIRVOperand *EntryPointID =
2881 new SPIRVOperand(SPIRVOperandType::NUMBERID, EntryPoint.second);
2882 Ops.push_back(EntryPointID);
2883
2884 SPIRVOperand *Name = new SPIRVOperand(SPIRVOperandType::LITERAL_STRING,
2885 EntryPoint.first->getName());
2886 Ops.push_back(Name);
2887
2888 size_t NameWordSize = (Name->getLiteralStr().size() + 1) / 4;
2889 if ((Name->getLiteralStr().size() + 1) % 4) {
2890 NameWordSize += 1;
2891 }
2892
2893 assert((3 + NameWordSize) < UINT16_MAX);
2894 uint16_t WordCount = static_cast<uint16_t>(3 + NameWordSize);
2895
2896 for (Value *Interface : EntryPointInterfaces) {
2897 SPIRVOperand *GIDOp =
2898 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[Interface]);
2899 Ops.push_back(GIDOp);
2900 WordCount++;
2901 }
2902
2903 SPIRVInstruction *EntryPointInst =
2904 new SPIRVInstruction(WordCount, spv::OpEntryPoint, 0 /* No id */, Ops);
2905 SPIRVInstList.insert(InsertPoint, EntryPointInst);
2906 }
2907
2908 for (auto EntryPoint : EntryPoints) {
2909 if (const MDNode *MD = dyn_cast<Function>(EntryPoint.first)
2910 ->getMetadata("reqd_work_group_size")) {
2911
2912 if (!BuiltinDimVec.empty()) {
2913 llvm_unreachable(
2914 "Kernels should have consistent work group size definition");
2915 }
2916
2917 //
2918 // Generate OpExecutionMode
2919 //
2920
2921 // Ops[0] = Entry Point ID
2922 // Ops[1] = Execution Mode
2923 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
2924 Ops.clear();
2925 SPIRVOperand *EntryPointID =
2926 new SPIRVOperand(SPIRVOperandType::NUMBERID, EntryPoint.second);
2927 Ops.push_back(EntryPointID);
2928
2929 SPIRVOperand *ExecMode = new SPIRVOperand(SPIRVOperandType::NUMBERID,
2930 spv::ExecutionModeLocalSize);
2931 Ops.push_back(ExecMode);
2932
2933 uint32_t XDim = static_cast<uint32_t>(
2934 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue());
2935 uint32_t YDim = static_cast<uint32_t>(
2936 mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue());
2937 uint32_t ZDim = static_cast<uint32_t>(
2938 mdconst::extract<ConstantInt>(MD->getOperand(2))->getZExtValue());
2939
2940 std::vector<uint32_t> LiteralNum;
2941 LiteralNum.push_back(XDim);
2942 SPIRVOperand *XDimOp =
2943 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2944 Ops.push_back(XDimOp);
2945
2946 LiteralNum.clear();
2947 LiteralNum.push_back(YDim);
2948 SPIRVOperand *YDimOp =
2949 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2950 Ops.push_back(YDimOp);
2951
2952 LiteralNum.clear();
2953 LiteralNum.push_back(ZDim);
2954 SPIRVOperand *ZDimOp =
2955 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2956 Ops.push_back(ZDimOp);
2957
2958 SPIRVInstruction *ExecModeInst =
2959 new SPIRVInstruction(static_cast<uint16_t>(1 + Ops.size()),
2960 spv::OpExecutionMode, 0 /* No id */, Ops);
2961 SPIRVInstList.insert(InsertPoint, ExecModeInst);
2962 }
2963 }
2964
2965 //
2966 // Generate OpSource.
2967 //
2968 // Ops[0] = SourceLanguage ID
2969 // Ops[1] = Version (LiteralNum)
2970 //
2971 Ops.clear();
2972 SPIRVOperand *SourceLanguage =
2973 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::SourceLanguageOpenCL_C);
2974 Ops.push_back(SourceLanguage);
2975
2976 std::vector<uint32_t> LiteralNum;
2977 LiteralNum.push_back(120);
2978 SPIRVOperand *Version =
2979 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
2980 Ops.push_back(Version);
2981
2982 SPIRVInstruction *OpenSourceInst =
2983 new SPIRVInstruction(3, spv::OpSource, 0 /* No id */, Ops);
2984 SPIRVInstList.insert(InsertPoint, OpenSourceInst);
2985
2986 if (!BuiltinDimVec.empty()) {
2987 //
2988 // Generate OpDecorates for x/y/z dimension.
2989 //
2990 // Ops[0] = Target ID
2991 // Ops[1] = Decoration (SpecId)
2992 // Ops[2] = Specialization Cosntant ID (Literal Number)
2993
2994 // X Dimension
2995 Ops.clear();
2996
2997 SPIRVOperand *TargetID =
2998 new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[0]);
2999 Ops.push_back(TargetID);
3000
3001 SPIRVOperand *DecoOp =
3002 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
3003 Ops.push_back(DecoOp);
3004
3005 LiteralNum.clear();
3006 LiteralNum.push_back(0);
3007 SPIRVOperand *XDim =
3008 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3009 Ops.push_back(XDim);
3010
3011 SPIRVInstruction *XDimDecoInst =
3012 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
3013 SPIRVInstList.insert(InsertPoint, XDimDecoInst);
3014
3015 // Y Dimension
3016 Ops.clear();
3017
3018 TargetID = new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[1]);
3019 Ops.push_back(TargetID);
3020
3021 DecoOp =
3022 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
3023 Ops.push_back(DecoOp);
3024
3025 LiteralNum.clear();
3026 LiteralNum.push_back(1);
3027 SPIRVOperand *YDim =
3028 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3029 Ops.push_back(YDim);
3030
3031 SPIRVInstruction *YDimDecoInst =
3032 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
3033 SPIRVInstList.insert(InsertPoint, YDimDecoInst);
3034
3035 // Z Dimension
3036 Ops.clear();
3037
3038 TargetID = new SPIRVOperand(SPIRVOperandType::NUMBERID, BuiltinDimVec[2]);
3039 Ops.push_back(TargetID);
3040
3041 DecoOp =
3042 new SPIRVOperand(SPIRVOperandType::NUMBERID, spv::DecorationSpecId);
3043 Ops.push_back(DecoOp);
3044
3045 LiteralNum.clear();
3046 LiteralNum.push_back(2);
3047 SPIRVOperand *ZDim =
3048 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3049 Ops.push_back(ZDim);
3050
3051 SPIRVInstruction *ZDimDecoInst =
3052 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
3053 SPIRVInstList.insert(InsertPoint, ZDimDecoInst);
3054 }
3055}
3056
3057void SPIRVProducerPass::GenerateInstForArg(Function &F) {
3058 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3059 ValueMapType &VMap = getValueMap();
3060 Module *Module = F.getParent();
3061 LLVMContext &Context = Module->getContext();
3062 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3063
3064 for (Argument &Arg : F.args()) {
3065 if (Arg.use_empty()) {
3066 continue;
3067 }
3068
3069 // Check the type of users of arguments.
3070 bool HasOnlyGEPUse = true;
3071 for (auto *U : Arg.users()) {
3072 if (!isa<GetElementPtrInst>(U) && isa<Instruction>(U)) {
3073 HasOnlyGEPUse = false;
3074 break;
3075 }
3076 }
3077
3078 Type *ArgTy = Arg.getType();
3079
3080 if (PointerType *PTy = dyn_cast<PointerType>(ArgTy)) {
3081 if (StructType *STy = dyn_cast<StructType>(PTy->getElementType())) {
3082 if (STy->isOpaque()) {
3083 // Generate OpLoad for sampler and image types.
3084 if (STy->getName().equals("opencl.sampler_t") ||
3085 STy->getName().equals("opencl.image2d_ro_t") ||
3086 STy->getName().equals("opencl.image2d_wo_t") ||
3087 STy->getName().equals("opencl.image3d_ro_t") ||
3088 STy->getName().equals("opencl.image3d_wo_t")) {
3089 //
3090 // Generate OpLoad.
3091 //
3092 // Ops[0] = Result Type ID
3093 // Ops[1] = Pointer ID
3094 // Ops[2] ... Ops[n] = Optional Memory Access
3095 //
3096 // TODO: Do we need to implement Optional Memory Access???
3097 SPIRVOperandList Ops;
3098
3099 // Use type with address space modified.
3100 ArgTy = ArgGVMap[&Arg]->getType()->getPointerElementType();
3101
3102 uint32_t ResTyID = lookupType(ArgTy);
3103 SPIRVOperand *ResTyIDOp =
3104 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3105 Ops.push_back(ResTyIDOp);
3106
3107 uint32_t PointerID = VMap[&Arg];
3108 SPIRVOperand *PointerIDOp =
3109 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
3110 Ops.push_back(PointerIDOp);
3111
3112 VMap[&Arg] = nextID;
3113 SPIRVInstruction *Inst =
3114 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
3115 SPIRVInstList.push_back(Inst);
3116 continue;
3117 }
3118 }
3119 }
3120
3121 if (!HasOnlyGEPUse) {
3122 //
3123 // Generate OpAccessChain.
3124 //
3125 // Ops[0] = Result Type ID
3126 // Ops[1] = Base ID
3127 // Ops[2] ... Ops[n] = Indexes ID
3128 SPIRVOperandList Ops;
3129
3130 uint32_t ResTyID = lookupType(ArgTy);
3131 if (!isa<PointerType>(ArgTy)) {
3132 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3133 }
3134 SPIRVOperand *ResTyOp =
3135 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3136 Ops.push_back(ResTyOp);
3137
3138 uint32_t BaseID = VMap[&Arg];
3139 SPIRVOperand *BaseOp =
3140 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3141 Ops.push_back(BaseOp);
3142
3143 Type *IdxTy = Type::getInt32Ty(Context);
3144 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3145 SPIRVOperand *IndexIDOp =
3146 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3147 Ops.push_back(IndexIDOp);
3148 Ops.push_back(IndexIDOp);
3149
3150 // Generate SPIRV instruction for argument.
3151 VMap[&Arg] = nextID;
3152 SPIRVInstruction *ArgInst =
3153 new SPIRVInstruction(6, spv::OpAccessChain, nextID++, Ops);
3154 SPIRVInstList.push_back(ArgInst);
3155 } else {
3156 // For GEP uses, generate OpAccessChain with folding GEP ahead of GEP.
3157 // Nothing to do here.
3158 }
3159 } else {
3160 //
3161 // Generate OpAccessChain and OpLoad for non-pointer type argument.
3162 //
3163
3164 //
3165 // Generate OpAccessChain.
3166 //
3167 // Ops[0] = Result Type ID
3168 // Ops[1] = Base ID
3169 // Ops[2] ... Ops[n] = Indexes ID
3170 SPIRVOperandList Ops;
3171
3172 uint32_t ResTyID = lookupType(ArgTy);
3173 if (!isa<PointerType>(ArgTy)) {
3174 ResTyID = lookupType(PointerType::get(ArgTy, AddressSpace::Global));
3175 }
3176 SPIRVOperand *ResTyIDOp =
3177 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3178 Ops.push_back(ResTyIDOp);
3179
3180 uint32_t BaseID = VMap[&Arg];
3181 SPIRVOperand *BaseOp =
3182 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3183 Ops.push_back(BaseOp);
3184
3185 Type *IdxTy = Type::getInt32Ty(Context);
3186 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3187 SPIRVOperand *IndexIDOp =
3188 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3189 Ops.push_back(IndexIDOp);
3190
3191 // Generate SPIRV instruction for argument.
3192 uint32_t PointerID = nextID;
3193 VMap[&Arg] = nextID;
3194 SPIRVInstruction *ArgInst =
3195 new SPIRVInstruction(5, spv::OpAccessChain, nextID++, Ops);
3196 SPIRVInstList.push_back(ArgInst);
3197
3198 //
3199 // Generate OpLoad.
3200 //
3201
3202 // Ops[0] = Result Type ID
3203 // Ops[1] = Pointer ID
3204 // Ops[2] ... Ops[n] = Optional Memory Access
3205 //
3206 // TODO: Do we need to implement Optional Memory Access???
3207 Ops.clear();
3208
3209 ResTyID = lookupType(ArgTy);
3210 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3211 Ops.push_back(ResTyIDOp);
3212
3213 SPIRVOperand *PointerIDOp =
3214 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
3215 Ops.push_back(PointerIDOp);
3216
3217 VMap[&Arg] = nextID;
3218 SPIRVInstruction *Inst =
3219 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
3220 SPIRVInstList.push_back(Inst);
3221 }
3222 }
3223}
3224
3225void SPIRVProducerPass::GenerateFuncBody(Function &F) {
3226 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3227 ValueMapType &VMap = getValueMap();
3228
3229 bool IsKernel = false;
3230 if (F.getCallingConv() == CallingConv::SPIR_KERNEL) {
3231 IsKernel = true;
3232 }
3233
3234 for (BasicBlock &BB : F) {
3235 // Register BasicBlock to ValueMap.
3236 VMap[&BB] = nextID;
3237
3238 //
3239 // Generate OpLabel for Basic Block.
3240 //
3241 SPIRVOperandList Ops;
3242 SPIRVInstruction *Inst =
3243 new SPIRVInstruction(2, spv::OpLabel, nextID++, Ops);
3244 SPIRVInstList.push_back(Inst);
3245
David Neto6dcd4712017-06-23 11:06:47 -04003246 // OpVariable instructions must come first.
3247 for (Instruction &I : BB) {
3248 if (isa<AllocaInst>(I)) {
3249 GenerateInstruction(I);
3250 }
3251 }
3252
David Neto22f144c2017-06-12 14:26:21 -04003253 if (&BB == &F.getEntryBlock() && IsKernel) {
3254 GenerateInstForArg(F);
3255 }
3256
3257 for (Instruction &I : BB) {
David Neto6dcd4712017-06-23 11:06:47 -04003258 if (!isa<AllocaInst>(I)) {
3259 GenerateInstruction(I);
3260 }
David Neto22f144c2017-06-12 14:26:21 -04003261 }
3262 }
3263}
3264
3265spv::Op SPIRVProducerPass::GetSPIRVCmpOpcode(CmpInst *I) {
3266 const std::map<CmpInst::Predicate, spv::Op> Map = {
3267 {CmpInst::ICMP_EQ, spv::OpIEqual},
3268 {CmpInst::ICMP_NE, spv::OpINotEqual},
3269 {CmpInst::ICMP_UGT, spv::OpUGreaterThan},
3270 {CmpInst::ICMP_UGE, spv::OpUGreaterThanEqual},
3271 {CmpInst::ICMP_ULT, spv::OpULessThan},
3272 {CmpInst::ICMP_ULE, spv::OpULessThanEqual},
3273 {CmpInst::ICMP_SGT, spv::OpSGreaterThan},
3274 {CmpInst::ICMP_SGE, spv::OpSGreaterThanEqual},
3275 {CmpInst::ICMP_SLT, spv::OpSLessThan},
3276 {CmpInst::ICMP_SLE, spv::OpSLessThanEqual},
3277 {CmpInst::FCMP_OEQ, spv::OpFOrdEqual},
3278 {CmpInst::FCMP_OGT, spv::OpFOrdGreaterThan},
3279 {CmpInst::FCMP_OGE, spv::OpFOrdGreaterThanEqual},
3280 {CmpInst::FCMP_OLT, spv::OpFOrdLessThan},
3281 {CmpInst::FCMP_OLE, spv::OpFOrdLessThanEqual},
3282 {CmpInst::FCMP_ONE, spv::OpFOrdNotEqual},
3283 {CmpInst::FCMP_UEQ, spv::OpFUnordEqual},
3284 {CmpInst::FCMP_UGT, spv::OpFUnordGreaterThan},
3285 {CmpInst::FCMP_UGE, spv::OpFUnordGreaterThanEqual},
3286 {CmpInst::FCMP_ULT, spv::OpFUnordLessThan},
3287 {CmpInst::FCMP_ULE, spv::OpFUnordLessThanEqual},
3288 {CmpInst::FCMP_UNE, spv::OpFUnordNotEqual}};
3289
3290 assert(0 != Map.count(I->getPredicate()));
3291
3292 return Map.at(I->getPredicate());
3293}
3294
3295spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
3296 const std::map<unsigned, spv::Op> Map{
3297 {Instruction::Trunc, spv::OpUConvert},
3298 {Instruction::ZExt, spv::OpUConvert},
3299 {Instruction::SExt, spv::OpSConvert},
3300 {Instruction::FPToUI, spv::OpConvertFToU},
3301 {Instruction::FPToSI, spv::OpConvertFToS},
3302 {Instruction::UIToFP, spv::OpConvertUToF},
3303 {Instruction::SIToFP, spv::OpConvertSToF},
3304 {Instruction::FPTrunc, spv::OpFConvert},
3305 {Instruction::FPExt, spv::OpFConvert},
3306 {Instruction::BitCast, spv::OpBitcast}};
3307
3308 assert(0 != Map.count(I.getOpcode()));
3309
3310 return Map.at(I.getOpcode());
3311}
3312
3313spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
3314 if (I.getType()->isIntegerTy(1)) {
3315 switch (I.getOpcode()) {
3316 default:
3317 break;
3318 case Instruction::Or:
3319 return spv::OpLogicalOr;
3320 case Instruction::And:
3321 return spv::OpLogicalAnd;
3322 case Instruction::Xor:
3323 return spv::OpLogicalNotEqual;
3324 }
3325 }
3326
3327 const std::map<unsigned, spv::Op> Map {
3328 {Instruction::Add, spv::OpIAdd},
3329 {Instruction::FAdd, spv::OpFAdd},
3330 {Instruction::Sub, spv::OpISub},
3331 {Instruction::FSub, spv::OpFSub},
3332 {Instruction::Mul, spv::OpIMul},
3333 {Instruction::FMul, spv::OpFMul},
3334 {Instruction::UDiv, spv::OpUDiv},
3335 {Instruction::SDiv, spv::OpSDiv},
3336 {Instruction::FDiv, spv::OpFDiv},
3337 {Instruction::URem, spv::OpUMod},
3338 {Instruction::SRem, spv::OpSRem},
3339 {Instruction::FRem, spv::OpFRem},
3340 {Instruction::Or, spv::OpBitwiseOr},
3341 {Instruction::Xor, spv::OpBitwiseXor},
3342 {Instruction::And, spv::OpBitwiseAnd},
3343 {Instruction::Shl, spv::OpShiftLeftLogical},
3344 {Instruction::LShr, spv::OpShiftRightLogical},
3345 {Instruction::AShr, spv::OpShiftRightArithmetic}};
3346
3347 assert(0 != Map.count(I.getOpcode()));
3348
3349 return Map.at(I.getOpcode());
3350}
3351
3352void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
3353 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
3354 ValueMapType &VMap = getValueMap();
3355 ValueToValueMapTy &ArgGVMap = getArgumentGVMap();
3356 ValueMapType &ArgGVIDMap = getArgumentGVIDMap();
3357 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
3358 LLVMContext &Context = I.getParent()->getParent()->getParent()->getContext();
3359
3360 // Register Instruction to ValueMap.
3361 if (0 == VMap[&I]) {
3362 VMap[&I] = nextID;
3363 }
3364
3365 switch (I.getOpcode()) {
3366 default: {
3367 if (Instruction::isCast(I.getOpcode())) {
3368 //
3369 // Generate SPIRV instructions for cast operators.
3370 //
3371
3372 auto OpTy = I.getOperand(0)->getType();
3373 // Handle zext, sext and uitofp with i1 type specially.
3374 if ((I.getOpcode() == Instruction::ZExt ||
3375 I.getOpcode() == Instruction::SExt ||
3376 I.getOpcode() == Instruction::UIToFP) &&
3377 (OpTy->isIntegerTy(1) ||
3378 (OpTy->isVectorTy() &&
3379 OpTy->getVectorElementType()->isIntegerTy(1)))) {
3380 //
3381 // Generate OpSelect.
3382 //
3383
3384 // Ops[0] = Result Type ID
3385 // Ops[1] = Condition ID
3386 // Ops[2] = True Constant ID
3387 // Ops[3] = False Constant ID
3388 SPIRVOperandList Ops;
3389
3390 uint32_t ResTyID = lookupType(I.getType());
3391 SPIRVOperand *ResTyIDOp =
3392 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3393 Ops.push_back(ResTyIDOp);
3394
3395 // TODO: zext's first operand should be compare instructions???
3396 uint32_t CondID = VMap[I.getOperand(0)];
3397 SPIRVOperand *CondIDOp =
3398 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3399 Ops.push_back(CondIDOp);
3400
3401 uint32_t TrueID = 0;
3402 if (I.getOpcode() == Instruction::ZExt) {
3403 APInt One(32, 1);
3404 TrueID = VMap[Constant::getIntegerValue(I.getType(), One)];
3405 } else if (I.getOpcode() == Instruction::SExt) {
3406 APInt MinusOne(32, UINT64_MAX, true);
3407 TrueID = VMap[Constant::getIntegerValue(I.getType(), MinusOne)];
3408 } else {
3409 TrueID = VMap[ConstantFP::get(Context, APFloat(1.0f))];
3410 }
3411 SPIRVOperand *TrueIDOp =
3412 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueID);
3413 Ops.push_back(TrueIDOp);
3414
3415 uint32_t FalseID = 0;
3416 if (I.getOpcode() == Instruction::ZExt) {
3417 FalseID = VMap[Constant::getNullValue(I.getType())];
3418 } else if (I.getOpcode() == Instruction::SExt) {
3419 FalseID = VMap[Constant::getNullValue(I.getType())];
3420 } else {
3421 FalseID = VMap[ConstantFP::get(Context, APFloat(0.0f))];
3422 }
3423 SPIRVOperand *FalseIDOp =
3424 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseID);
3425 Ops.push_back(FalseIDOp);
3426
3427 SPIRVInstruction *Inst =
3428 new SPIRVInstruction(6, spv::OpSelect, nextID++, Ops);
3429 SPIRVInstList.push_back(Inst);
3430 } else {
3431 // Ops[0] = Result Type ID
3432 // Ops[1] = Source Value ID
3433 SPIRVOperandList Ops;
3434
3435 uint32_t ResTyID = lookupType(I.getType());
3436 SPIRVOperand *ResTyIDOp =
3437 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3438 Ops.push_back(ResTyIDOp);
3439
3440 uint32_t SrcID = VMap[I.getOperand(0)];
3441 SPIRVOperand *SrcIDOp =
3442 new SPIRVOperand(SPIRVOperandType::NUMBERID, SrcID);
3443 Ops.push_back(SrcIDOp);
3444
3445 SPIRVInstruction *Inst =
3446 new SPIRVInstruction(4, GetSPIRVCastOpcode(I), nextID++, Ops);
3447 SPIRVInstList.push_back(Inst);
3448 }
3449 } else if (isa<BinaryOperator>(I)) {
3450 //
3451 // Generate SPIRV instructions for binary operators.
3452 //
3453
3454 // Handle xor with i1 type specially.
3455 if (I.getOpcode() == Instruction::Xor &&
3456 I.getType() == Type::getInt1Ty(Context) &&
3457 (isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
3458 //
3459 // Generate OpLogicalNot.
3460 //
3461 // Ops[0] = Result Type ID
3462 // Ops[1] = Operand
3463 SPIRVOperandList Ops;
3464
3465 uint32_t ResTyID = lookupType(I.getType());
3466 SPIRVOperand *ResTyIDOp =
3467 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3468 Ops.push_back(ResTyIDOp);
3469
3470 Value *CondV = I.getOperand(0);
3471 if (isa<Constant>(I.getOperand(0))) {
3472 CondV = I.getOperand(1);
3473 }
3474 uint32_t CondID = VMap[CondV];
3475 SPIRVOperand *CondIDOp =
3476 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3477 Ops.push_back(CondIDOp);
3478
3479 SPIRVInstruction *Inst =
3480 new SPIRVInstruction(4, spv::OpLogicalNot, nextID++, Ops);
3481 SPIRVInstList.push_back(Inst);
3482 } else {
3483 // Ops[0] = Result Type ID
3484 // Ops[1] = Operand 0
3485 // Ops[2] = Operand 1
3486 SPIRVOperandList Ops;
3487
3488 uint32_t ResTyID = lookupType(I.getType());
3489 SPIRVOperand *ResTyIDOp =
3490 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3491 Ops.push_back(ResTyIDOp);
3492
3493 uint32_t Op0ID = VMap[I.getOperand(0)];
3494 SPIRVOperand *Op0IDOp =
3495 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3496 Ops.push_back(Op0IDOp);
3497
3498 uint32_t Op1ID = VMap[I.getOperand(1)];
3499 SPIRVOperand *Op1IDOp =
3500 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3501 Ops.push_back(Op1IDOp);
3502
3503 SPIRVInstruction *Inst =
3504 new SPIRVInstruction(5, GetSPIRVBinaryOpcode(I), nextID++, Ops);
3505 SPIRVInstList.push_back(Inst);
3506 }
3507 } else {
3508 I.print(errs());
3509 llvm_unreachable("Unsupported instruction???");
3510 }
3511 break;
3512 }
3513 case Instruction::GetElementPtr: {
3514 auto &GlobalConstArgSet = getGlobalConstArgSet();
3515
3516 //
3517 // Generate OpAccessChain.
3518 //
3519 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&I);
3520
3521 //
3522 // Generate OpAccessChain.
3523 //
3524
3525 // Ops[0] = Result Type ID
3526 // Ops[1] = Base ID
3527 // Ops[2] ... Ops[n] = Indexes ID
3528 SPIRVOperandList Ops;
3529
David Neto1a1a0582017-07-07 12:01:44 -04003530 PointerType* ResultType = cast<PointerType>(GEP->getType());
David Neto22f144c2017-06-12 14:26:21 -04003531 if (GEP->getPointerAddressSpace() == AddressSpace::ModuleScopePrivate ||
3532 GlobalConstArgSet.count(GEP->getPointerOperand())) {
3533 // Use pointer type with private address space for global constant.
3534 Type *EleTy = I.getType()->getPointerElementType();
David Neto1a1a0582017-07-07 12:01:44 -04003535 ResultType = PointerType::get(EleTy, AddressSpace::ModuleScopePrivate);
David Neto22f144c2017-06-12 14:26:21 -04003536 }
David Neto1a1a0582017-07-07 12:01:44 -04003537 const uint32_t ResTyID = lookupType(ResultType);
David Neto22f144c2017-06-12 14:26:21 -04003538 SPIRVOperand *ResTyIDOp =
3539 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3540 Ops.push_back(ResTyIDOp);
3541
3542 // Check whether GEP's pointer operand is pointer argument.
3543 bool HasArgBasePointer = false;
3544 for (auto ArgGV : ArgGVMap) {
3545 if (ArgGV.first == GEP->getPointerOperand()) {
3546 if (isa<PointerType>(ArgGV.first->getType())) {
3547 HasArgBasePointer = true;
3548 } else {
3549 llvm_unreachable(
3550 "GEP's pointer operand is argument of non-poninter type???");
3551 }
3552 }
3553 }
3554
3555 uint32_t BaseID;
3556 if (HasArgBasePointer) {
3557 // Point to global variable for argument directly.
3558 BaseID = ArgGVIDMap[GEP->getPointerOperand()];
3559 } else {
3560 BaseID = VMap[GEP->getPointerOperand()];
3561 }
3562
3563 SPIRVOperand *BaseIDOp =
3564 new SPIRVOperand(SPIRVOperandType::NUMBERID, BaseID);
3565 Ops.push_back(BaseIDOp);
3566
3567 uint16_t WordCount = 4;
3568
3569 if (HasArgBasePointer) {
3570 // If GEP's pointer operand is argument, add one more index for struct
3571 // type to wrap up argument type.
3572 Type *IdxTy = Type::getInt32Ty(Context);
3573 uint32_t IndexID = VMap[ConstantInt::get(IdxTy, 0)];
3574 SPIRVOperand *IndexIDOp =
3575 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3576 Ops.push_back(IndexIDOp);
3577
3578 WordCount++;
3579 }
3580
3581 //
3582 // Follows below rules for gep.
3583 //
3584 // 1. If gep's first index is 0 and gep's base is not kernel function's
3585 // argument, generate OpAccessChain and ignore gep's first index.
3586 // 2. If gep's first index is not 0, generate OpPtrAccessChain and use gep's
3587 // first index.
3588 // 3. If gep's first index is not constant, generate OpPtrAccessChain and
3589 // use gep's first index.
3590 // 4. If it is not above case 1, 2 and 3, generate OpAccessChain and use
3591 // gep's first index.
3592 //
3593 spv::Op Opcode = spv::OpAccessChain;
3594 unsigned offset = 0;
3595 if (ConstantInt *CstInt = dyn_cast<ConstantInt>(GEP->getOperand(1))) {
3596 if (CstInt->getZExtValue() == 0 && !HasArgBasePointer) {
3597 offset = 1;
3598 } else if (CstInt->getZExtValue() != 0 && !HasArgBasePointer) {
3599 Opcode = spv::OpPtrAccessChain;
David Neto22f144c2017-06-12 14:26:21 -04003600 }
3601 } else if (!HasArgBasePointer) {
3602 Opcode = spv::OpPtrAccessChain;
David Neto1a1a0582017-07-07 12:01:44 -04003603 }
3604
3605 if (Opcode == spv::OpPtrAccessChain) {
David Neto22f144c2017-06-12 14:26:21 -04003606 setVariablePointers(true);
David Neto1a1a0582017-07-07 12:01:44 -04003607 // Do we need to generate ArrayStride? Check against the GEP result type
3608 // rather than the pointer type of the base because when indexing into
3609 // an OpenCL program-scope constant, we'll swap out the LLVM base pointer
3610 // for something else in the SPIR-V.
3611 // E.g. see test/PointerAccessChain/pointer_index_is_constant_1.cl
3612 if (GetStorageClass(ResultType->getAddressSpace()) ==
3613 spv::StorageClassStorageBuffer) {
3614 // Save the need to generate an ArrayStride decoration. But defer
3615 // generation until later, so we only make one decoration.
3616 getPointerTypesNeedingArrayStride().insert(ResultType);
3617 }
David Neto22f144c2017-06-12 14:26:21 -04003618 }
3619
3620 for (auto II = GEP->idx_begin() + offset; II != GEP->idx_end(); II++) {
3621 uint32_t IndexID = VMap[*II];
3622 SPIRVOperand *IndexIDOp =
3623 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3624 Ops.push_back(IndexIDOp);
3625
3626 WordCount++;
3627 }
3628
3629 SPIRVInstruction *Inst =
3630 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
3631 SPIRVInstList.push_back(Inst);
3632 break;
3633 }
3634 case Instruction::ExtractValue: {
3635 ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
3636 // Ops[0] = Result Type ID
3637 // Ops[1] = Composite ID
3638 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3639 SPIRVOperandList Ops;
3640
3641 uint32_t ResTyID = lookupType(I.getType());
3642 SPIRVOperand *ResTyIDOp =
3643 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3644 Ops.push_back(ResTyIDOp);
3645
3646 uint32_t CompositeID = VMap[EVI->getAggregateOperand()];
3647 SPIRVOperand *CompositeIDOp =
3648 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3649 Ops.push_back(CompositeIDOp);
3650
3651 for (auto &Index : EVI->indices()) {
3652 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, Index));
3653 }
3654
3655 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
3656 SPIRVInstruction *Inst =
3657 new SPIRVInstruction(WordCount, spv::OpCompositeExtract, nextID++, Ops);
3658 SPIRVInstList.push_back(Inst);
3659 break;
3660 }
3661 case Instruction::InsertValue: {
3662 InsertValueInst *IVI = cast<InsertValueInst>(&I);
3663 // Ops[0] = Result Type ID
3664 // Ops[1] = Object ID
3665 // Ops[2] = Composite ID
3666 // Ops[3] ... Ops[n] = Indexes (Literal Number)
3667 SPIRVOperandList Ops;
3668
3669 uint32_t ResTyID = lookupType(I.getType());
3670 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID));
3671
3672 uint32_t ObjectID = VMap[IVI->getInsertedValueOperand()];
3673 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID));
3674
3675 uint32_t CompositeID = VMap[IVI->getAggregateOperand()];
3676 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID));
3677
3678 for (auto &Index : IVI->indices()) {
3679 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, Index));
3680 }
3681
3682 uint16_t WordCount = static_cast<uint16_t>(2 + Ops.size());
3683 SPIRVInstruction *Inst =
3684 new SPIRVInstruction(WordCount, spv::OpCompositeInsert, nextID++, Ops);
3685 SPIRVInstList.push_back(Inst);
3686 break;
3687 }
3688 case Instruction::Select: {
3689 //
3690 // Generate OpSelect.
3691 //
3692
3693 // Ops[0] = Result Type ID
3694 // Ops[1] = Condition ID
3695 // Ops[2] = True Constant ID
3696 // Ops[3] = False Constant ID
3697 SPIRVOperandList Ops;
3698
3699 // Find SPIRV instruction for parameter type.
3700 auto Ty = I.getType();
3701 if (Ty->isPointerTy()) {
3702 auto PointeeTy = Ty->getPointerElementType();
3703 if (PointeeTy->isStructTy() &&
3704 dyn_cast<StructType>(PointeeTy)->isOpaque()) {
3705 Ty = PointeeTy;
3706 }
3707 }
3708
3709 uint32_t ResTyID = lookupType(Ty);
3710 SPIRVOperand *ResTyIDOp =
3711 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3712 Ops.push_back(ResTyIDOp);
3713
3714 uint32_t CondID = VMap[I.getOperand(0)];
3715 SPIRVOperand *CondIDOp =
3716 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
3717 Ops.push_back(CondIDOp);
3718
3719 uint32_t TrueID = VMap[I.getOperand(1)];
3720 SPIRVOperand *TrueIDOp =
3721 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueID);
3722 Ops.push_back(TrueIDOp);
3723
3724 uint32_t FalseID = VMap[I.getOperand(2)];
3725 SPIRVOperand *FalseIDOp =
3726 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseID);
3727 Ops.push_back(FalseIDOp);
3728
3729 SPIRVInstruction *Inst =
3730 new SPIRVInstruction(6, spv::OpSelect, nextID++, Ops);
3731 SPIRVInstList.push_back(Inst);
3732 break;
3733 }
3734 case Instruction::ExtractElement: {
3735 // Handle <4 x i8> type manually.
3736 Type *CompositeTy = I.getOperand(0)->getType();
3737 if (is4xi8vec(CompositeTy)) {
3738 //
3739 // Generate OpShiftRightLogical and OpBitwiseAnd for extractelement with
3740 // <4 x i8>.
3741 //
3742
3743 //
3744 // Generate OpShiftRightLogical
3745 //
3746 // Ops[0] = Result Type ID
3747 // Ops[1] = Operand 0
3748 // Ops[2] = Operand 1
3749 //
3750 SPIRVOperandList Ops;
3751
3752 uint32_t ResTyID = lookupType(CompositeTy);
3753 SPIRVOperand *ResTyIDOp =
3754 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3755 Ops.push_back(ResTyIDOp);
3756
3757 uint32_t Op0ID = VMap[I.getOperand(0)];
3758 SPIRVOperand *Op0IDOp =
3759 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3760 Ops.push_back(Op0IDOp);
3761
3762 uint32_t Op1ID = 0;
3763 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3764 // Handle constant index.
3765 uint64_t Idx = CI->getZExtValue();
3766 Value *ShiftAmount =
3767 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3768 Op1ID = VMap[ShiftAmount];
3769 } else {
3770 // Handle variable index.
3771 SPIRVOperandList TmpOps;
3772
3773 uint32_t TmpResTyID = lookupType(Type::getInt32Ty(Context));
3774 SPIRVOperand *TmpResTyIDOp =
3775 new SPIRVOperand(SPIRVOperandType::NUMBERID, TmpResTyID);
3776 TmpOps.push_back(TmpResTyIDOp);
3777
3778 uint32_t IdxID = VMap[I.getOperand(1)];
3779 SPIRVOperand *TmpOp0IDOp =
3780 new SPIRVOperand(SPIRVOperandType::NUMBERID, IdxID);
3781 TmpOps.push_back(TmpOp0IDOp);
3782
3783 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
3784 uint32_t Cst8ID = VMap[Cst8];
3785 SPIRVOperand *TmpOp1IDOp =
3786 new SPIRVOperand(SPIRVOperandType::NUMBERID, Cst8ID);
3787 TmpOps.push_back(TmpOp1IDOp);
3788
3789 Op1ID = nextID;
3790
3791 SPIRVInstruction *TmpInst =
3792 new SPIRVInstruction(5, spv::OpIMul, nextID++, TmpOps);
3793 SPIRVInstList.push_back(TmpInst);
3794 }
3795 SPIRVOperand *Op1IDOp =
3796 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3797 Ops.push_back(Op1IDOp);
3798
3799 uint32_t ShiftID = nextID;
3800
3801 SPIRVInstruction *Inst =
3802 new SPIRVInstruction(5, spv::OpShiftRightLogical, nextID++, Ops);
3803 SPIRVInstList.push_back(Inst);
3804
3805 //
3806 // Generate OpBitwiseAnd
3807 //
3808 // Ops[0] = Result Type ID
3809 // Ops[1] = Operand 0
3810 // Ops[2] = Operand 1
3811 //
3812 Ops.clear();
3813
3814 ResTyID = lookupType(CompositeTy);
3815 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3816 Ops.push_back(ResTyIDOp);
3817
3818 Op0ID = ShiftID;
3819 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3820 Ops.push_back(Op0IDOp);
3821
3822 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3823 Op1ID = VMap[CstFF];
3824 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3825 Ops.push_back(Op1IDOp);
3826
3827 Inst = new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
3828 SPIRVInstList.push_back(Inst);
3829 break;
3830 }
3831
3832 // Ops[0] = Result Type ID
3833 // Ops[1] = Composite ID
3834 // Ops[2] ... Ops[n] = Indexes (Literal Number)
3835 SPIRVOperandList Ops;
3836
3837 uint32_t ResTyID = lookupType(I.getType());
3838 SPIRVOperand *ResTyIDOp =
3839 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3840 Ops.push_back(ResTyIDOp);
3841
3842 uint32_t CompositeID = VMap[I.getOperand(0)];
3843 SPIRVOperand *CompositeIDOp =
3844 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
3845 Ops.push_back(CompositeIDOp);
3846
3847 spv::Op Opcode = spv::OpCompositeExtract;
3848 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(1))) {
3849 std::vector<uint32_t> LiteralNum;
3850 assert(CI->getZExtValue() < UINT32_MAX);
3851 LiteralNum.push_back(static_cast<uint32_t>(CI->getZExtValue()));
3852 SPIRVOperand *Indexes =
3853 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
3854 Ops.push_back(Indexes);
3855 } else {
3856 uint32_t IndexID = VMap[I.getOperand(1)];
3857 SPIRVOperand *IndexIDOp =
3858 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
3859 Ops.push_back(IndexIDOp);
3860 Opcode = spv::OpVectorExtractDynamic;
3861 }
3862
3863 uint16_t WordCount = 5;
3864 SPIRVInstruction *Inst =
3865 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
3866 SPIRVInstList.push_back(Inst);
3867 break;
3868 }
3869 case Instruction::InsertElement: {
3870 // Handle <4 x i8> type manually.
3871 Type *CompositeTy = I.getOperand(0)->getType();
3872 if (is4xi8vec(CompositeTy)) {
3873 Constant *CstFF = ConstantInt::get(Type::getInt32Ty(Context), 0xFF);
3874 uint32_t CstFFID = VMap[CstFF];
3875
3876 uint32_t ShiftAmountID = 0;
3877 if (ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
3878 // Handle constant index.
3879 uint64_t Idx = CI->getZExtValue();
3880 Value *ShiftAmount =
3881 ConstantInt::get(Type::getInt32Ty(Context), Idx * 8);
3882 ShiftAmountID = VMap[ShiftAmount];
3883 } else {
3884 // Handle variable index.
3885 SPIRVOperandList TmpOps;
3886
3887 uint32_t TmpResTyID = lookupType(Type::getInt32Ty(Context));
3888 SPIRVOperand *TmpResTyIDOp =
3889 new SPIRVOperand(SPIRVOperandType::NUMBERID, TmpResTyID);
3890 TmpOps.push_back(TmpResTyIDOp);
3891
3892 uint32_t IdxID = VMap[I.getOperand(2)];
3893 SPIRVOperand *TmpOp0IDOp =
3894 new SPIRVOperand(SPIRVOperandType::NUMBERID, IdxID);
3895 TmpOps.push_back(TmpOp0IDOp);
3896
3897 ConstantInt *Cst8 = ConstantInt::get(Type::getInt32Ty(Context), 8);
3898 uint32_t Cst8ID = VMap[Cst8];
3899 SPIRVOperand *TmpOp1IDOp =
3900 new SPIRVOperand(SPIRVOperandType::NUMBERID, Cst8ID);
3901 TmpOps.push_back(TmpOp1IDOp);
3902
3903 ShiftAmountID = nextID;
3904
3905 SPIRVInstruction *TmpInst =
3906 new SPIRVInstruction(5, spv::OpIMul, nextID++, TmpOps);
3907 SPIRVInstList.push_back(TmpInst);
3908 }
3909
3910 //
3911 // Generate mask operations.
3912 //
3913
3914 // ShiftLeft mask according to index of insertelement.
3915 SPIRVOperandList Ops;
3916
3917 uint32_t ResTyID = lookupType(CompositeTy);
3918 SPIRVOperand *ResTyIDOp =
3919 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
3920 Ops.push_back(ResTyIDOp);
3921
3922 uint32_t Op0ID = CstFFID;
3923 SPIRVOperand *Op0IDOp =
3924 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3925 Ops.push_back(Op0IDOp);
3926
3927 uint32_t Op1ID = ShiftAmountID;
3928 SPIRVOperand *Op1IDOp =
3929 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3930 Ops.push_back(Op1IDOp);
3931
3932 uint32_t MaskID = nextID;
3933
3934 SPIRVInstruction *Inst =
3935 new SPIRVInstruction(5, spv::OpShiftLeftLogical, nextID++, Ops);
3936 SPIRVInstList.push_back(Inst);
3937
3938 // Inverse mask.
3939 Ops.clear();
3940
3941 Ops.push_back(ResTyIDOp);
3942
3943 Op0ID = MaskID;
3944 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3945 Ops.push_back(Op0IDOp);
3946
3947 uint32_t InvMaskID = nextID;
3948
3949 Inst = new SPIRVInstruction(4, spv::OpLogicalNot, nextID++, Ops);
3950 SPIRVInstList.push_back(Inst);
3951
3952 // Apply mask.
3953 Ops.clear();
3954
3955 Ops.push_back(ResTyIDOp);
3956
3957 Op0ID = VMap[I.getOperand(0)];
3958 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3959 Ops.push_back(Op0IDOp);
3960
3961 Op1ID = InvMaskID;
3962 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3963 Ops.push_back(Op1IDOp);
3964
3965 uint32_t OrgValID = nextID;
3966
3967 Inst = new SPIRVInstruction(5, spv::OpBitwiseAnd, nextID++, Ops);
3968 SPIRVInstList.push_back(Inst);
3969
3970 // Create correct value according to index of insertelement.
3971 Ops.clear();
3972
3973 Ops.push_back(ResTyIDOp);
3974
3975 Op0ID = VMap[I.getOperand(1)];
3976 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3977 Ops.push_back(Op0IDOp);
3978
3979 Op1ID = ShiftAmountID;
3980 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3981 Ops.push_back(Op1IDOp);
3982
3983 uint32_t InsertValID = nextID;
3984
3985 Inst = new SPIRVInstruction(5, spv::OpShiftLeftLogical, nextID++, Ops);
3986 SPIRVInstList.push_back(Inst);
3987
3988 // Insert value to original value.
3989 Ops.clear();
3990
3991 Ops.push_back(ResTyIDOp);
3992
3993 Op0ID = OrgValID;
3994 Op0IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
3995 Ops.push_back(Op0IDOp);
3996
3997 Op1ID = InsertValID;
3998 Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
3999 Ops.push_back(Op1IDOp);
4000
4001 Inst = new SPIRVInstruction(5, spv::OpBitwiseOr, nextID++, Ops);
4002 SPIRVInstList.push_back(Inst);
4003
4004 break;
4005 }
4006
4007 // Ops[0] = Result Type ID
4008 // Ops[1] = Object ID
4009 // Ops[2] = Composite ID
4010 // Ops[3] ... Ops[n] = Indexes (Literal Number)
4011 SPIRVOperandList Ops;
4012
4013 uint32_t ResTyID = lookupType(I.getType());
4014 SPIRVOperand *ResTyIDOp =
4015 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4016 Ops.push_back(ResTyIDOp);
4017
4018 uint32_t ObjectID = VMap[I.getOperand(1)];
4019 SPIRVOperand *ObjectIDOp =
4020 new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID);
4021 Ops.push_back(ObjectIDOp);
4022
4023 uint32_t CompositeID = VMap[I.getOperand(0)];
4024 SPIRVOperand *CompositeIDOp =
4025 new SPIRVOperand(SPIRVOperandType::NUMBERID, CompositeID);
4026 Ops.push_back(CompositeIDOp);
4027
4028 spv::Op Opcode = spv::OpCompositeInsert;
4029 if (const ConstantInt *CI = dyn_cast<ConstantInt>(I.getOperand(2))) {
4030 std::vector<uint32_t> LiteralNum;
4031 assert(CI->getZExtValue() < UINT32_MAX);
4032 LiteralNum.push_back(static_cast<uint32_t>(CI->getZExtValue()));
4033 SPIRVOperand *Indexes =
4034 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4035 Ops.push_back(Indexes);
4036 } else {
4037 uint32_t IndexID = VMap[I.getOperand(1)];
4038 SPIRVOperand *IndexIDOp =
4039 new SPIRVOperand(SPIRVOperandType::NUMBERID, IndexID);
4040 Ops.push_back(IndexIDOp);
4041 Opcode = spv::OpVectorInsertDynamic;
4042 }
4043
4044 uint16_t WordCount = 6;
4045 SPIRVInstruction *Inst =
4046 new SPIRVInstruction(WordCount, Opcode, nextID++, Ops);
4047 SPIRVInstList.push_back(Inst);
4048 break;
4049 }
4050 case Instruction::ShuffleVector: {
4051 // Ops[0] = Result Type ID
4052 // Ops[1] = Vector 1 ID
4053 // Ops[2] = Vector 2 ID
4054 // Ops[3] ... Ops[n] = Components (Literal Number)
4055 SPIRVOperandList Ops;
4056
4057 uint32_t ResTyID = lookupType(I.getType());
4058 SPIRVOperand *ResTyIDOp =
4059 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4060 Ops.push_back(ResTyIDOp);
4061
4062 uint32_t Vec1ID = VMap[I.getOperand(0)];
4063 SPIRVOperand *Vec1IDOp =
4064 new SPIRVOperand(SPIRVOperandType::NUMBERID, Vec1ID);
4065 Ops.push_back(Vec1IDOp);
4066
4067 uint32_t Vec2ID = VMap[I.getOperand(1)];
4068 SPIRVOperand *Vec2IDOp =
4069 new SPIRVOperand(SPIRVOperandType::NUMBERID, Vec2ID);
4070 Ops.push_back(Vec2IDOp);
4071
4072 uint64_t NumElements = 0;
4073 if (Constant *Cst = dyn_cast<Constant>(I.getOperand(2))) {
4074 NumElements = cast<VectorType>(Cst->getType())->getNumElements();
4075
4076 if (Cst->isNullValue()) {
4077 for (unsigned i = 0; i < NumElements; i++) {
4078 std::vector<uint32_t> LiteralNum;
4079 LiteralNum.push_back(0);
4080 SPIRVOperand *Component =
4081 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4082 Ops.push_back(Component);
4083 }
4084 } else if (const ConstantDataSequential *CDS =
4085 dyn_cast<ConstantDataSequential>(Cst)) {
4086 for (unsigned i = 0; i < CDS->getNumElements(); i++) {
4087 std::vector<uint32_t> LiteralNum;
4088 assert(CDS->getElementAsInteger(i) < UINT32_MAX);
4089 LiteralNum.push_back(
4090 static_cast<uint32_t>(CDS->getElementAsInteger(i)));
4091 SPIRVOperand *Component =
4092 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4093 Ops.push_back(Component);
4094 }
4095 } else if (const ConstantVector *CV = dyn_cast<ConstantVector>(Cst)) {
4096 for (unsigned i = 0; i < CV->getNumOperands(); i++) {
4097 auto Op = CV->getOperand(i);
4098
4099 uint32_t literal = 0;
4100
4101 if (auto CI = dyn_cast<ConstantInt>(Op)) {
4102 literal = static_cast<uint32_t>(CI->getZExtValue());
4103 } else if (auto UI = dyn_cast<UndefValue>(Op)) {
4104 literal = 0xFFFFFFFFu;
4105 } else {
4106 Op->print(errs());
4107 llvm_unreachable("Unsupported element in ConstantVector!");
4108 }
4109
4110 std::vector<uint32_t> LiteralNum;
4111 LiteralNum.push_back(literal);
4112 SPIRVOperand *Component =
4113 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4114 Ops.push_back(Component);
4115 }
4116 } else {
4117 Cst->print(errs());
4118 llvm_unreachable("Unsupported constant mask in ShuffleVector!");
4119 }
4120 }
4121
4122 uint16_t WordCount = static_cast<uint16_t>(5 + NumElements);
4123 SPIRVInstruction *Inst =
4124 new SPIRVInstruction(WordCount, spv::OpVectorShuffle, nextID++, Ops);
4125 SPIRVInstList.push_back(Inst);
4126 break;
4127 }
4128 case Instruction::ICmp:
4129 case Instruction::FCmp: {
4130 CmpInst *CmpI = cast<CmpInst>(&I);
4131
4132 // Ops[0] = Result Type ID
4133 // Ops[1] = Operand 1 ID
4134 // Ops[2] = Operand 2 ID
4135 SPIRVOperandList Ops;
4136
4137 uint32_t ResTyID = lookupType(CmpI->getType());
4138 SPIRVOperand *ResTyIDOp =
4139 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4140 Ops.push_back(ResTyIDOp);
4141
David Netod4ca2e62017-07-06 18:47:35 -04004142 // Pointer equality is invalid.
4143 Type* ArgTy = CmpI->getOperand(0)->getType();
4144 if (isa<PointerType>(ArgTy)) {
4145 CmpI->print(errs());
4146 std::string name = I.getParent()->getParent()->getName();
4147 errs()
4148 << "\nPointer equality test is not supported by SPIR-V for Vulkan, "
4149 << "in function " << name << "\n";
4150 llvm_unreachable("Pointer equality check is invalid");
4151 break;
4152 }
4153
David Neto22f144c2017-06-12 14:26:21 -04004154 uint32_t Op1ID = VMap[CmpI->getOperand(0)];
4155 SPIRVOperand *Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op1ID);
4156 Ops.push_back(Op1IDOp);
4157
4158 uint32_t Op2ID = VMap[CmpI->getOperand(1)];
4159 SPIRVOperand *Op2IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, Op2ID);
4160 Ops.push_back(Op2IDOp);
4161
4162 spv::Op Opcode = GetSPIRVCmpOpcode(CmpI);
4163 SPIRVInstruction *Inst = new SPIRVInstruction(5, Opcode, nextID++, Ops);
4164 SPIRVInstList.push_back(Inst);
4165 break;
4166 }
4167 case Instruction::Br: {
4168 // Branch instrucion is deferred because it needs label's ID. Record slot's
4169 // location on SPIRVInstructionList.
4170 DeferredInsts.push_back(
4171 std::make_tuple(&I, --SPIRVInstList.end(), 0 /* No id */));
4172 break;
4173 }
4174 case Instruction::Switch: {
4175 I.print(errs());
4176 llvm_unreachable("Unsupported instruction???");
4177 break;
4178 }
4179 case Instruction::IndirectBr: {
4180 I.print(errs());
4181 llvm_unreachable("Unsupported instruction???");
4182 break;
4183 }
4184 case Instruction::PHI: {
4185 // Branch instrucion is deferred because it needs label's ID. Record slot's
4186 // location on SPIRVInstructionList.
4187 DeferredInsts.push_back(
4188 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4189 break;
4190 }
4191 case Instruction::Alloca: {
4192 //
4193 // Generate OpVariable.
4194 //
4195 // Ops[0] : Result Type ID
4196 // Ops[1] : Storage Class
4197 SPIRVOperandList Ops;
4198
4199 Type *ResTy = I.getType();
4200 uint32_t ResTyID = lookupType(ResTy);
4201 SPIRVOperand *ResTyOp =
4202 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4203 Ops.push_back(ResTyOp);
4204
4205 spv::StorageClass StorageClass = spv::StorageClassFunction;
4206 SPIRVOperand *StorageClassOp =
4207 new SPIRVOperand(SPIRVOperandType::NUMBERID, StorageClass);
4208 Ops.push_back(StorageClassOp);
4209
4210 SPIRVInstruction *Inst =
4211 new SPIRVInstruction(4, spv::OpVariable, nextID++, Ops);
4212 SPIRVInstList.push_back(Inst);
4213 break;
4214 }
4215 case Instruction::Load: {
4216 LoadInst *LD = cast<LoadInst>(&I);
4217 //
4218 // Generate OpLoad.
4219 //
4220
4221 // Ops[0] = Result Type ID
4222 // Ops[1] = Pointer ID
4223 // Ops[2] ... Ops[n] = Optional Memory Access
4224 //
4225 // TODO: Do we need to implement Optional Memory Access???
4226 SPIRVOperandList Ops;
4227
4228 uint32_t ResTyID = lookupType(LD->getType());
4229 SPIRVOperand *ResTyIDOp =
4230 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4231 Ops.push_back(ResTyIDOp);
4232
4233 uint32_t PointerID = VMap[LD->getPointerOperand()];
4234 SPIRVOperand *PointerIDOp =
4235 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4236 Ops.push_back(PointerIDOp);
4237
4238 SPIRVInstruction *Inst =
4239 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
4240 SPIRVInstList.push_back(Inst);
4241 break;
4242 }
4243 case Instruction::Store: {
4244 StoreInst *ST = cast<StoreInst>(&I);
4245 //
4246 // Generate OpStore.
4247 //
4248
4249 // Ops[0] = Pointer ID
4250 // Ops[1] = Object ID
4251 // Ops[2] ... Ops[n] = Optional Memory Access (later???)
4252 //
4253 // TODO: Do we need to implement Optional Memory Access???
4254 SPIRVOperand *Ops[2] = {new SPIRVOperand(SPIRVOperandType::NUMBERID,
4255 VMap[ST->getPointerOperand()]),
4256 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4257 VMap[ST->getValueOperand()])};
4258
4259 SPIRVInstruction *Inst =
4260 new SPIRVInstruction(3, spv::OpStore, 0 /* No id */, Ops);
4261 SPIRVInstList.push_back(Inst);
4262 break;
4263 }
4264 case Instruction::AtomicCmpXchg: {
4265 I.print(errs());
4266 llvm_unreachable("Unsupported instruction???");
4267 break;
4268 }
4269 case Instruction::AtomicRMW: {
4270 I.print(errs());
4271 llvm_unreachable("Unsupported instruction???");
4272 break;
4273 }
4274 case Instruction::Fence: {
4275 I.print(errs());
4276 llvm_unreachable("Unsupported instruction???");
4277 break;
4278 }
4279 case Instruction::Call: {
4280 CallInst *Call = dyn_cast<CallInst>(&I);
4281 Function *Callee = Call->getCalledFunction();
4282
4283 // Sampler initializers become a load of the corresponding sampler.
4284 if (Callee->getName().equals("__translate_sampler_initializer")) {
4285 // Check that the sampler map was definitely used though.
4286 if (0 == getSamplerMap().size()) {
4287 llvm_unreachable("Sampler literal in source without sampler map!");
4288 }
4289
4290 SPIRVOperandList Ops;
4291
4292 uint32_t ResTyID = lookupType(SamplerTy->getPointerElementType());
4293 SPIRVOperand *ResTyIDOp =
4294 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
4295 Ops.push_back(ResTyIDOp);
4296
4297 uint32_t PointerID = VMap[Call];
4298 SPIRVOperand *PointerIDOp =
4299 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4300 Ops.push_back(PointerIDOp);
4301
4302 VMap[Call] = nextID;
4303 SPIRVInstruction *Inst =
4304 new SPIRVInstruction(4, spv::OpLoad, nextID++, Ops);
4305 SPIRVInstList.push_back(Inst);
4306
4307 break;
4308 }
4309
4310 if (Callee->getName().startswith("spirv.atomic")) {
4311 spv::Op opcode = StringSwitch<spv::Op>(Callee->getName())
4312 .Case("spirv.atomic_add", spv::OpAtomicIAdd)
4313 .Case("spirv.atomic_sub", spv::OpAtomicISub)
4314 .Case("spirv.atomic_exchange", spv::OpAtomicExchange)
4315 .Case("spirv.atomic_inc", spv::OpAtomicIIncrement)
4316 .Case("spirv.atomic_dec", spv::OpAtomicIDecrement)
4317 .Case("spirv.atomic_compare_exchange",
4318 spv::OpAtomicCompareExchange)
4319 .Case("spirv.atomic_umin", spv::OpAtomicUMin)
4320 .Case("spirv.atomic_smin", spv::OpAtomicSMin)
4321 .Case("spirv.atomic_umax", spv::OpAtomicUMax)
4322 .Case("spirv.atomic_smax", spv::OpAtomicSMax)
4323 .Case("spirv.atomic_and", spv::OpAtomicAnd)
4324 .Case("spirv.atomic_or", spv::OpAtomicOr)
4325 .Case("spirv.atomic_xor", spv::OpAtomicXor)
4326 .Default(spv::OpNop);
4327
4328 //
4329 // Generate OpAtomic*.
4330 //
4331 SPIRVOperandList Ops;
4332
4333 uint32_t TyID = lookupType(I.getType());
4334 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4335
4336 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4337 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4338 VMap[Call->getArgOperand(i)]));
4339 }
4340
4341 VMap[&I] = nextID;
4342
4343 SPIRVInstruction *Inst = new SPIRVInstruction(
4344 static_cast<uint16_t>(2 + Ops.size()), opcode, nextID++, Ops);
4345 SPIRVInstList.push_back(Inst);
4346 break;
4347 }
4348
4349 if (Callee->getName().startswith("_Z3dot")) {
4350 // If the argument is a vector type, generate OpDot
4351 if (Call->getArgOperand(0)->getType()->isVectorTy()) {
4352 //
4353 // Generate OpDot.
4354 //
4355 SPIRVOperandList Ops;
4356
4357 uint32_t TyID = lookupType(I.getType());
4358 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4359
4360 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4361 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4362 VMap[Call->getArgOperand(i)]));
4363 }
4364
4365 VMap[&I] = nextID;
4366
4367 SPIRVInstruction *Inst = new SPIRVInstruction(
4368 static_cast<uint16_t>(2 + Ops.size()), spv::OpDot, nextID++, Ops);
4369 SPIRVInstList.push_back(Inst);
4370 } else {
4371 //
4372 // Generate OpFMul.
4373 //
4374 SPIRVOperandList Ops;
4375
4376 uint32_t TyID = lookupType(I.getType());
4377 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID));
4378
4379 for (unsigned i = 0; i < Call->getNumArgOperands(); i++) {
4380 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
4381 VMap[Call->getArgOperand(i)]));
4382 }
4383
4384 VMap[&I] = nextID;
4385
4386 SPIRVInstruction *Inst = new SPIRVInstruction(
4387 static_cast<uint16_t>(2 + Ops.size()), spv::OpFMul, nextID++, Ops);
4388 SPIRVInstList.push_back(Inst);
4389 }
4390 break;
4391 }
4392
4393 // spirv.store_null.* intrinsics become OpStore's.
4394 if (Callee->getName().startswith("spirv.store_null")) {
4395 //
4396 // Generate OpStore.
4397 //
4398
4399 // Ops[0] = Pointer ID
4400 // Ops[1] = Object ID
4401 // Ops[2] ... Ops[n]
4402 SPIRVOperandList Ops;
4403
4404 uint32_t PointerID = VMap[Call->getArgOperand(0)];
4405 SPIRVOperand *PointerIDOp =
4406 new SPIRVOperand(SPIRVOperandType::NUMBERID, PointerID);
4407 Ops.push_back(PointerIDOp);
4408
4409 uint32_t ObjectID = VMap[Call->getArgOperand(1)];
4410 SPIRVOperand *ObjectIDOp =
4411 new SPIRVOperand(SPIRVOperandType::NUMBERID, ObjectID);
4412 Ops.push_back(ObjectIDOp);
4413
4414 SPIRVInstruction *Inst =
4415 new SPIRVInstruction(3, spv::OpStore, 0 /* No id */, Ops);
4416 SPIRVInstList.push_back(Inst);
4417
4418 break;
4419 }
4420
4421 // spirv.copy_memory.* intrinsics become OpMemoryMemory's.
4422 if (Callee->getName().startswith("spirv.copy_memory")) {
4423 //
4424 // Generate OpCopyMemory.
4425 //
4426
4427 // Ops[0] = Dst ID
4428 // Ops[1] = Src ID
4429 // Ops[2] = Memory Access
4430 // Ops[3] = Alignment
4431
4432 auto IsVolatile =
4433 dyn_cast<ConstantInt>(Call->getArgOperand(3))->getZExtValue() != 0;
4434
4435 auto VolatileMemoryAccess = (IsVolatile) ? spv::MemoryAccessVolatileMask
4436 : spv::MemoryAccessMaskNone;
4437
4438 auto MemoryAccess = VolatileMemoryAccess | spv::MemoryAccessAlignedMask;
4439
4440 auto Alignment =
4441 dyn_cast<ConstantInt>(Call->getArgOperand(2))->getZExtValue();
4442
4443 SPIRVOperand *Ops[4] = {
4444 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4445 VMap[Call->getArgOperand(0)]),
4446 new SPIRVOperand(SPIRVOperandType::NUMBERID,
4447 VMap[Call->getArgOperand(1)]),
4448 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, MemoryAccess),
4449 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER,
4450 static_cast<uint32_t>(Alignment))};
4451
4452 SPIRVInstruction *Inst =
4453 new SPIRVInstruction(5, spv::OpCopyMemory, 0 /* No id */, Ops);
4454
4455 SPIRVInstList.push_back(Inst);
4456
4457 break;
4458 }
4459
4460 // Nothing to do for abs with uint. Map abs's operand ID to VMap for abs
4461 // with unit.
4462 if (Callee->getName().equals("_Z3absj") ||
4463 Callee->getName().equals("_Z3absDv2_j") ||
4464 Callee->getName().equals("_Z3absDv3_j") ||
4465 Callee->getName().equals("_Z3absDv4_j")) {
4466 VMap[&I] = VMap[Call->getOperand(0)];
4467 break;
4468 }
4469
4470 // barrier is converted to OpControlBarrier
4471 if (Callee->getName().equals("__spirv_control_barrier")) {
4472 //
4473 // Generate OpControlBarrier.
4474 //
4475 // Ops[0] = Execution Scope ID
4476 // Ops[1] = Memory Scope ID
4477 // Ops[2] = Memory Semantics ID
4478 //
4479 Value *ExecutionScope = Call->getArgOperand(0);
4480 Value *MemoryScope = Call->getArgOperand(1);
4481 Value *MemorySemantics = Call->getArgOperand(2);
4482
4483 SPIRVOperand *Ops[3] = {
4484 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[ExecutionScope]),
4485 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[MemoryScope]),
4486 new SPIRVOperand(SPIRVOperandType::NUMBERID, VMap[MemorySemantics])};
4487
4488 SPIRVInstList.push_back(
4489 new SPIRVInstruction(4, spv::OpControlBarrier, 0 /* No id */, Ops));
4490 break;
4491 }
4492
4493 // memory barrier is converted to OpMemoryBarrier
4494 if (Callee->getName().equals("__spirv_memory_barrier")) {
4495 //
4496 // Generate OpMemoryBarrier.
4497 //
4498 // Ops[0] = Memory Scope ID
4499 // Ops[1] = Memory Semantics ID
4500 //
4501 SPIRVOperandList Ops;
4502
4503 Value *MemoryScope = Call->getArgOperand(0);
4504 Value *MemorySemantics = Call->getArgOperand(1);
4505
4506 uint32_t MemoryScopeID = VMap[MemoryScope];
4507 Ops.push_back(
4508 new SPIRVOperand(SPIRVOperandType::NUMBERID, MemoryScopeID));
4509
4510 uint32_t MemorySemanticsID = VMap[MemorySemantics];
4511 Ops.push_back(
4512 new SPIRVOperand(SPIRVOperandType::NUMBERID, MemorySemanticsID));
4513
4514 SPIRVInstruction *Inst =
4515 new SPIRVInstruction(3, spv::OpMemoryBarrier, 0 /* No id */, Ops);
4516 SPIRVInstList.push_back(Inst);
4517 break;
4518 }
4519
4520 // isinf is converted to OpIsInf
4521 if (Callee->getName().equals("__spirv_isinff") ||
4522 Callee->getName().equals("__spirv_isinfDv2_f") ||
4523 Callee->getName().equals("__spirv_isinfDv3_f") ||
4524 Callee->getName().equals("__spirv_isinfDv4_f")) {
4525 //
4526 // Generate OpIsInf.
4527 //
4528 // Ops[0] = Result Type ID
4529 // Ops[1] = X ID
4530 //
4531 SPIRVOperandList Ops;
4532
4533 uint32_t TyID = lookupType(I.getType());
4534 SPIRVOperand *ResTyIDOp =
4535 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4536 Ops.push_back(ResTyIDOp);
4537
4538 uint32_t XID = VMap[Call->getArgOperand(0)];
4539 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XID));
4540
4541 VMap[&I] = nextID;
4542
4543 SPIRVInstruction *Inst =
4544 new SPIRVInstruction(4, spv::OpIsInf, nextID++, Ops);
4545 SPIRVInstList.push_back(Inst);
4546 break;
4547 }
4548
4549 // isnan is converted to OpIsNan
4550 if (Callee->getName().equals("__spirv_isnanf") ||
4551 Callee->getName().equals("__spirv_isnanDv2_f") ||
4552 Callee->getName().equals("__spirv_isnanDv3_f") ||
4553 Callee->getName().equals("__spirv_isnanDv4_f")) {
4554 //
4555 // Generate OpIsInf.
4556 //
4557 // Ops[0] = Result Type ID
4558 // Ops[1] = X ID
4559 //
4560 SPIRVOperandList Ops;
4561
4562 uint32_t TyID = lookupType(I.getType());
4563 SPIRVOperand *ResTyIDOp =
4564 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4565 Ops.push_back(ResTyIDOp);
4566
4567 uint32_t XID = VMap[Call->getArgOperand(0)];
4568 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, XID));
4569
4570 VMap[&I] = nextID;
4571
4572 SPIRVInstruction *Inst =
4573 new SPIRVInstruction(4, spv::OpIsNan, nextID++, Ops);
4574 SPIRVInstList.push_back(Inst);
4575 break;
4576 }
4577
4578 // all is converted to OpAll
4579 if (Callee->getName().equals("__spirv_allDv2_i") ||
4580 Callee->getName().equals("__spirv_allDv3_i") ||
4581 Callee->getName().equals("__spirv_allDv4_i")) {
4582 //
4583 // Generate OpAll.
4584 //
4585 // Ops[0] = Result Type ID
4586 // Ops[1] = Vector ID
4587 //
4588 SPIRVOperandList Ops;
4589
4590 uint32_t TyID = lookupType(I.getType());
4591 SPIRVOperand *ResTyIDOp =
4592 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4593 Ops.push_back(ResTyIDOp);
4594
4595 uint32_t VectorID = VMap[Call->getArgOperand(0)];
4596 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, VectorID));
4597
4598 VMap[&I] = nextID;
4599
4600 SPIRVInstruction *Inst =
4601 new SPIRVInstruction(4, spv::OpAll, nextID++, Ops);
4602 SPIRVInstList.push_back(Inst);
4603 break;
4604 }
4605
4606 // any is converted to OpAny
4607 if (Callee->getName().equals("__spirv_anyDv2_i") ||
4608 Callee->getName().equals("__spirv_anyDv3_i") ||
4609 Callee->getName().equals("__spirv_anyDv4_i")) {
4610 //
4611 // Generate OpAny.
4612 //
4613 // Ops[0] = Result Type ID
4614 // Ops[1] = Vector ID
4615 //
4616 SPIRVOperandList Ops;
4617
4618 uint32_t TyID = lookupType(I.getType());
4619 SPIRVOperand *ResTyIDOp =
4620 new SPIRVOperand(SPIRVOperandType::NUMBERID, TyID);
4621 Ops.push_back(ResTyIDOp);
4622
4623 uint32_t VectorID = VMap[Call->getArgOperand(0)];
4624 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID, VectorID));
4625
4626 VMap[&I] = nextID;
4627
4628 SPIRVInstruction *Inst =
4629 new SPIRVInstruction(4, spv::OpAny, nextID++, Ops);
4630 SPIRVInstList.push_back(Inst);
4631 break;
4632 }
4633
4634 // read_image is converted to OpSampledImage and OpImageSampleExplicitLod.
4635 // Additionally, OpTypeSampledImage is generated.
4636 if (Callee->getName().equals(
4637 "_Z11read_imagef14ocl_image2d_ro11ocl_samplerDv2_f") ||
4638 Callee->getName().equals(
4639 "_Z11read_imagef14ocl_image3d_ro11ocl_samplerDv4_f")) {
4640 //
4641 // Generate OpSampledImage.
4642 //
4643 // Ops[0] = Result Type ID
4644 // Ops[1] = Image ID
4645 // Ops[2] = Sampler ID
4646 //
4647 SPIRVOperandList Ops;
4648
4649 Value *Image = Call->getArgOperand(0);
4650 Value *Sampler = Call->getArgOperand(1);
4651 Value *Coordinate = Call->getArgOperand(2);
4652
4653 TypeMapType &OpImageTypeMap = getImageTypeMap();
4654 Type *ImageTy = Image->getType()->getPointerElementType();
4655 uint32_t ImageTyID = OpImageTypeMap[ImageTy];
4656 SPIRVOperand *ResTyIDOp =
4657 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageTyID);
4658 Ops.push_back(ResTyIDOp);
4659
4660 uint32_t ImageID = VMap[Image];
4661 SPIRVOperand *ImageIDOp =
4662 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageID);
4663 Ops.push_back(ImageIDOp);
4664
4665 uint32_t SamplerID = VMap[Sampler];
4666 SPIRVOperand *SamplerIDOp =
4667 new SPIRVOperand(SPIRVOperandType::NUMBERID, SamplerID);
4668 Ops.push_back(SamplerIDOp);
4669
4670 uint32_t SampledImageID = nextID;
4671
4672 SPIRVInstruction *Inst =
4673 new SPIRVInstruction(5, spv::OpSampledImage, nextID++, Ops);
4674 SPIRVInstList.push_back(Inst);
4675
4676 //
4677 // Generate OpImageSampleExplicitLod.
4678 //
4679 // Ops[0] = Result Type ID
4680 // Ops[1] = Sampled Image ID
4681 // Ops[2] = Coordinate ID
4682 // Ops[3] = Image Operands Type ID
4683 // Ops[4] ... Ops[n] = Operands ID
4684 //
4685 Ops.clear();
4686
4687 uint32_t RetTyID = lookupType(Call->getType());
4688 ResTyIDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID, RetTyID);
4689 Ops.push_back(ResTyIDOp);
4690
4691 SPIRVOperand *SampledImageIDOp =
4692 new SPIRVOperand(SPIRVOperandType::NUMBERID, SampledImageID);
4693 Ops.push_back(SampledImageIDOp);
4694
4695 uint32_t CoordinateID = VMap[Coordinate];
4696 SPIRVOperand *CoordinateIDOp =
4697 new SPIRVOperand(SPIRVOperandType::NUMBERID, CoordinateID);
4698 Ops.push_back(CoordinateIDOp);
4699
4700 std::vector<uint32_t> LiteralNum;
4701 LiteralNum.push_back(spv::ImageOperandsLodMask);
4702 SPIRVOperand *ImageOperandTyIDOp =
4703 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
4704 Ops.push_back(ImageOperandTyIDOp);
4705
4706 Constant *CstFP0 = ConstantFP::get(Context, APFloat(0.0f));
4707 uint32_t OperandID = VMap[CstFP0];
4708 SPIRVOperand *OperandIDOp =
4709 new SPIRVOperand(SPIRVOperandType::NUMBERID, OperandID);
4710 Ops.push_back(OperandIDOp);
4711
4712 VMap[&I] = nextID;
4713
4714 Inst =
4715 new SPIRVInstruction(7, spv::OpImageSampleExplicitLod, nextID++, Ops);
4716 SPIRVInstList.push_back(Inst);
4717 break;
4718 }
4719
4720 // write_imagef is mapped to OpImageWrite.
4721 if (Callee->getName().equals(
4722 "_Z12write_imagef14ocl_image2d_woDv2_iDv4_f") ||
4723 Callee->getName().equals(
4724 "_Z12write_imagef14ocl_image3d_woDv4_iDv4_f")) {
4725 //
4726 // Generate OpImageWrite.
4727 //
4728 // Ops[0] = Image ID
4729 // Ops[1] = Coordinate ID
4730 // Ops[2] = Texel ID
4731 // Ops[3] = (Optional) Image Operands Type (Literal Number)
4732 // Ops[4] ... Ops[n] = (Optional) Operands ID
4733 //
4734 SPIRVOperandList Ops;
4735
4736 Value *Image = Call->getArgOperand(0);
4737 Value *Coordinate = Call->getArgOperand(1);
4738 Value *Texel = Call->getArgOperand(2);
4739
4740 uint32_t ImageID = VMap[Image];
4741 SPIRVOperand *ImageIDOp =
4742 new SPIRVOperand(SPIRVOperandType::NUMBERID, ImageID);
4743 Ops.push_back(ImageIDOp);
4744
4745 uint32_t CoordinateID = VMap[Coordinate];
4746 SPIRVOperand *CoordinateIDOp =
4747 new SPIRVOperand(SPIRVOperandType::NUMBERID, CoordinateID);
4748 Ops.push_back(CoordinateIDOp);
4749
4750 uint32_t TexelID = VMap[Texel];
4751 SPIRVOperand *TexelIDOp =
4752 new SPIRVOperand(SPIRVOperandType::NUMBERID, TexelID);
4753 Ops.push_back(TexelIDOp);
4754
4755 SPIRVInstruction *Inst =
4756 new SPIRVInstruction(4, spv::OpImageWrite, 0 /* No id */, Ops);
4757 SPIRVInstList.push_back(Inst);
4758 break;
4759 }
4760
4761 // Call instrucion is deferred because it needs function's ID. Record
4762 // slot's location on SPIRVInstructionList.
4763 DeferredInsts.push_back(
4764 std::make_tuple(&I, --SPIRVInstList.end(), nextID++));
4765
4766 // Check whether this call is for extend instructions.
4767 glsl::ExtInst EInst = getExtInstEnum(Callee->getName());
4768 if (EInst == glsl::ExtInstFindUMsb) {
4769 // clz needs OpExtInst and OpISub with constant 31. Increase nextID.
4770 VMap[&I] = nextID;
4771 nextID++;
4772 }
4773 break;
4774 }
4775 case Instruction::Ret: {
4776 unsigned NumOps = I.getNumOperands();
4777 if (NumOps == 0) {
4778 //
4779 // Generate OpReturn.
4780 //
4781
4782 // Empty Ops
4783 SPIRVOperandList Ops;
4784 SPIRVInstruction *Inst =
4785 new SPIRVInstruction(1, spv::OpReturn, 0 /* No id */, Ops);
4786 SPIRVInstList.push_back(Inst);
4787 } else {
4788 //
4789 // Generate OpReturnValue.
4790 //
4791
4792 // Ops[0] = Return Value ID
4793 SPIRVOperandList Ops;
4794 uint32_t RetValID = VMap[I.getOperand(0)];
4795 SPIRVOperand *RetValIDOp =
4796 new SPIRVOperand(SPIRVOperandType::NUMBERID, RetValID);
4797 Ops.push_back(RetValIDOp);
4798
4799 SPIRVInstruction *Inst =
4800 new SPIRVInstruction(2, spv::OpReturnValue, 0 /* No id */, Ops);
4801 SPIRVInstList.push_back(Inst);
4802 break;
4803 }
4804 break;
4805 }
4806 }
4807}
4808
4809void SPIRVProducerPass::GenerateFuncEpilogue() {
4810 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4811
4812 //
4813 // Generate OpFunctionEnd
4814 //
4815
4816 // Empty Ops
4817 SPIRVOperandList Ops;
4818 SPIRVInstruction *Inst =
4819 new SPIRVInstruction(1, spv::OpFunctionEnd, 0 /* No id */, Ops);
4820 SPIRVInstList.push_back(Inst);
4821}
4822
4823bool SPIRVProducerPass::is4xi8vec(Type *Ty) const {
4824 LLVMContext &Context = Ty->getContext();
4825 if (Ty->isVectorTy()) {
4826 if (Ty->getVectorElementType() == Type::getInt8Ty(Context) &&
4827 Ty->getVectorNumElements() == 4) {
4828 return true;
4829 }
4830 }
4831
4832 return false;
4833}
4834
4835void SPIRVProducerPass::HandleDeferredInstruction() {
4836 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
4837 ValueMapType &VMap = getValueMap();
4838 DeferredInstVecType &DeferredInsts = getDeferredInstVec();
4839
4840 for (auto DeferredInst = DeferredInsts.rbegin();
4841 DeferredInst != DeferredInsts.rend(); ++DeferredInst) {
4842 Value *Inst = std::get<0>(*DeferredInst);
4843 SPIRVInstructionList::iterator InsertPoint = ++std::get<1>(*DeferredInst);
4844 if (InsertPoint != SPIRVInstList.end()) {
4845 while ((*InsertPoint)->getOpcode() == spv::OpPhi) {
4846 ++InsertPoint;
4847 }
4848 }
4849
4850 if (BranchInst *Br = dyn_cast<BranchInst>(Inst)) {
4851 // Check whether basic block, which has this branch instruction, is loop
4852 // header or not. If it is loop header, generate OpLoopMerge and
4853 // OpBranchConditional.
4854 Function *Func = Br->getParent()->getParent();
4855 DominatorTree &DT =
4856 getAnalysis<DominatorTreeWrapperPass>(*Func).getDomTree();
4857 const LoopInfo &LI =
4858 getAnalysis<LoopInfoWrapperPass>(*Func).getLoopInfo();
4859
4860 BasicBlock *BrBB = Br->getParent();
4861 if (LI.isLoopHeader(BrBB)) {
4862 Value *ContinueBB = nullptr;
4863 Value *MergeBB = nullptr;
4864
4865 Loop *L = LI.getLoopFor(BrBB);
4866 MergeBB = L->getExitBlock();
4867 if (!MergeBB) {
4868 // StructurizeCFG pass converts CFG into triangle shape and the cfg
4869 // has regions with single entry/exit. As a result, loop should not
4870 // have multiple exits.
4871 llvm_unreachable("Loop has multiple exits???");
4872 }
4873
4874 if (L->isLoopLatch(BrBB)) {
4875 ContinueBB = BrBB;
4876 } else {
4877 // From SPIR-V spec 2.11, Continue Target must dominate that back-edge
4878 // block.
4879 BasicBlock *Header = L->getHeader();
4880 BasicBlock *Latch = L->getLoopLatch();
4881 for (BasicBlock *BB : L->blocks()) {
4882 if (BB == Header) {
4883 continue;
4884 }
4885
4886 // Check whether block dominates block with back-edge.
4887 if (DT.dominates(BB, Latch)) {
4888 ContinueBB = BB;
4889 }
4890 }
4891
4892 if (!ContinueBB) {
4893 llvm_unreachable("Wrong continue block from loop");
4894 }
4895 }
4896
4897 //
4898 // Generate OpLoopMerge.
4899 //
4900 // Ops[0] = Merge Block ID
4901 // Ops[1] = Continue Target ID
4902 // Ops[2] = Selection Control
4903 SPIRVOperandList Ops;
4904
4905 // StructurizeCFG pass already manipulated CFG. Just use false block of
4906 // branch instruction as merge block.
4907 uint32_t MergeBBID = VMap[MergeBB];
4908 SPIRVOperand *MergeBBIDOp =
4909 new SPIRVOperand(SPIRVOperandType::NUMBERID, MergeBBID);
4910 Ops.push_back(MergeBBIDOp);
4911
4912 uint32_t ContinueBBID = VMap[ContinueBB];
4913 SPIRVOperand *ContinueBBIDOp =
4914 new SPIRVOperand(SPIRVOperandType::NUMBERID, ContinueBBID);
4915 Ops.push_back(ContinueBBIDOp);
4916
4917 SPIRVOperand *SelectionControlOp = new SPIRVOperand(
4918 SPIRVOperandType::NUMBERID, spv::SelectionControlMaskNone);
4919 Ops.push_back(SelectionControlOp);
4920
4921 SPIRVInstruction *MergeInst =
4922 new SPIRVInstruction(4, spv::OpLoopMerge, 0 /* No id */, Ops);
4923 SPIRVInstList.insert(InsertPoint, MergeInst);
4924
4925 } else if (Br->isConditional()) {
4926 bool HasBackEdge = false;
4927
4928 for (unsigned i = 0; i < Br->getNumSuccessors(); i++) {
4929 if (LI.isLoopHeader(Br->getSuccessor(i))) {
4930 HasBackEdge = true;
4931 }
4932 }
4933 if (!HasBackEdge) {
4934 //
4935 // Generate OpSelectionMerge.
4936 //
4937 // Ops[0] = Merge Block ID
4938 // Ops[1] = Selection Control
4939 SPIRVOperandList Ops;
4940
4941 // StructurizeCFG pass already manipulated CFG. Just use false block
4942 // of branch instruction as merge block.
4943 uint32_t MergeBBID = VMap[Br->getSuccessor(1)];
4944 SPIRVOperand *MergeBBIDOp =
4945 new SPIRVOperand(SPIRVOperandType::NUMBERID, MergeBBID);
4946 Ops.push_back(MergeBBIDOp);
4947
4948 SPIRVOperand *SelectionControlOp = new SPIRVOperand(
4949 SPIRVOperandType::NUMBERID, spv::SelectionControlMaskNone);
4950 Ops.push_back(SelectionControlOp);
4951
4952 SPIRVInstruction *MergeInst = new SPIRVInstruction(
4953 3, spv::OpSelectionMerge, 0 /* No id */, Ops);
4954 SPIRVInstList.insert(InsertPoint, MergeInst);
4955 }
4956 }
4957
4958 if (Br->isConditional()) {
4959 //
4960 // Generate OpBranchConditional.
4961 //
4962 // Ops[0] = Condition ID
4963 // Ops[1] = True Label ID
4964 // Ops[2] = False Label ID
4965 // Ops[3] ... Ops[n] = Branch weights (Literal Number)
4966 SPIRVOperandList Ops;
4967
4968 uint32_t CondID = VMap[Br->getCondition()];
4969 SPIRVOperand *CondIDOp =
4970 new SPIRVOperand(SPIRVOperandType::NUMBERID, CondID);
4971 Ops.push_back(CondIDOp);
4972
4973 uint32_t TrueBBID = VMap[Br->getSuccessor(0)];
4974 SPIRVOperand *TrueBBIDOp =
4975 new SPIRVOperand(SPIRVOperandType::NUMBERID, TrueBBID);
4976 Ops.push_back(TrueBBIDOp);
4977
4978 uint32_t FalseBBID = VMap[Br->getSuccessor(1)];
4979 SPIRVOperand *FalseBBIDOp =
4980 new SPIRVOperand(SPIRVOperandType::NUMBERID, FalseBBID);
4981 Ops.push_back(FalseBBIDOp);
4982
4983 SPIRVInstruction *BrInst = new SPIRVInstruction(
4984 4, spv::OpBranchConditional, 0 /* No id */, Ops);
4985 SPIRVInstList.insert(InsertPoint, BrInst);
4986 } else {
4987 //
4988 // Generate OpBranch.
4989 //
4990 // Ops[0] = Target Label ID
4991 SPIRVOperandList Ops;
4992
4993 uint32_t TargetID = VMap[Br->getSuccessor(0)];
4994 SPIRVOperand *TargetIDOp =
4995 new SPIRVOperand(SPIRVOperandType::NUMBERID, TargetID);
4996 Ops.push_back(TargetIDOp);
4997
4998 SPIRVInstList.insert(
4999 InsertPoint,
5000 new SPIRVInstruction(2, spv::OpBranch, 0 /* No id */, Ops));
5001 }
5002 } else if (PHINode *PHI = dyn_cast<PHINode>(Inst)) {
5003 //
5004 // Generate OpPhi.
5005 //
5006 // Ops[0] = Result Type ID
5007 // Ops[1] ... Ops[n] = (Variable ID, Parent ID) pairs
5008 SPIRVOperandList Ops;
5009
5010 uint32_t ResTyID = lookupType(PHI->getType());
5011 SPIRVOperand *ResTyIDOp =
5012 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5013 Ops.push_back(ResTyIDOp);
5014
5015 uint16_t WordCount = 3;
5016 for (unsigned i = 0; i < PHI->getNumIncomingValues(); i++) {
5017 uint32_t VarID = VMap[PHI->getIncomingValue(i)];
5018 SPIRVOperand *VarIDOp =
5019 new SPIRVOperand(SPIRVOperandType::NUMBERID, VarID);
5020 Ops.push_back(VarIDOp);
5021
5022 uint32_t ParentID = VMap[PHI->getIncomingBlock(i)];
5023 SPIRVOperand *ParentIDOp =
5024 new SPIRVOperand(SPIRVOperandType::NUMBERID, ParentID);
5025 Ops.push_back(ParentIDOp);
5026
5027 WordCount += 2;
5028 }
5029
5030 SPIRVInstList.insert(
5031 InsertPoint, new SPIRVInstruction(WordCount, spv::OpPhi,
5032 std::get<2>(*DeferredInst), Ops));
5033 } else if (CallInst *Call = dyn_cast<CallInst>(Inst)) {
5034 Function *Callee = Call->getCalledFunction();
5035 glsl::ExtInst EInst = getExtInstEnum(Callee->getName());
5036
5037 if (EInst) {
5038 uint32_t &ExtInstImportID = getOpExtInstImportID();
5039
5040 //
5041 // Generate OpExtInst.
5042 //
5043
5044 // Ops[0] = Result Type ID
5045 // Ops[1] = Set ID (OpExtInstImport ID)
5046 // Ops[2] = Instruction Number (Literal Number)
5047 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5048 SPIRVOperandList Ops;
5049
5050 uint32_t ResTyID = lookupType(Call->getType());
5051 SPIRVOperand *ResTyIDOp =
5052 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5053 Ops.push_back(ResTyIDOp);
5054
5055 SPIRVOperand *SetIDOp =
5056 new SPIRVOperand(SPIRVOperandType::NUMBERID, ExtInstImportID);
5057 Ops.push_back(SetIDOp);
5058
5059 std::vector<uint32_t> LiteralNum;
5060 LiteralNum.push_back(EInst);
5061 SPIRVOperand *InstructionOp =
5062 new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, LiteralNum);
5063 Ops.push_back(InstructionOp);
5064
5065 uint16_t WordCount = 5;
5066
5067 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5068 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
5069 uint32_t ArgID = VMap[Call->getOperand(i)];
5070 SPIRVOperand *ArgIDOp =
5071 new SPIRVOperand(SPIRVOperandType::NUMBERID, ArgID);
5072 Ops.push_back(ArgIDOp);
5073 WordCount++;
5074 }
5075
5076 SPIRVInstruction *ExtInst = new SPIRVInstruction(
5077 WordCount, spv::OpExtInst, std::get<2>(*DeferredInst), Ops);
5078 SPIRVInstList.insert(InsertPoint, ExtInst);
5079
5080 // clz needs OpExtInst and OpISub with constant 31.
5081 if (EInst == glsl::ExtInstFindUMsb) {
5082 LLVMContext &Context =
5083 Call->getParent()->getParent()->getParent()->getContext();
5084 //
5085 // Generate OpISub with constant 31.
5086 //
5087 // Ops[0] = Result Type ID
5088 // Ops[1] = Operand 0
5089 // Ops[2] = Operand 1
5090 Ops.clear();
5091
5092 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
5093 lookupType(Call->getType())));
5094
5095 Type *IdxTy = Type::getInt32Ty(Context);
5096 Constant *Cst31 = ConstantInt::get(IdxTy, 31);
5097 uint32_t Op0ID = VMap[Cst31];
5098 SPIRVOperand *Op0IDOp =
5099 new SPIRVOperand(SPIRVOperandType::NUMBERID, Op0ID);
5100 Ops.push_back(Op0IDOp);
5101
5102 SPIRVOperand *Op1IDOp = new SPIRVOperand(SPIRVOperandType::NUMBERID,
5103 std::get<2>(*DeferredInst));
5104 Ops.push_back(Op1IDOp);
5105
5106 SPIRVInstList.insert(
5107 InsertPoint,
5108 new SPIRVInstruction(5, spv::OpISub,
5109 std::get<2>(*DeferredInst) + 1, Ops));
5110 }
5111 } else if (Callee->getName().equals("_Z8popcounti") ||
5112 Callee->getName().equals("_Z8popcountj") ||
5113 Callee->getName().equals("_Z8popcountDv2_i") ||
5114 Callee->getName().equals("_Z8popcountDv3_i") ||
5115 Callee->getName().equals("_Z8popcountDv4_i") ||
5116 Callee->getName().equals("_Z8popcountDv2_j") ||
5117 Callee->getName().equals("_Z8popcountDv3_j") ||
5118 Callee->getName().equals("_Z8popcountDv4_j")) {
5119 //
5120 // Generate OpBitCount
5121 //
5122 // Ops[0] = Result Type ID
5123 // Ops[1] = Base ID
5124 SPIRVOperand *Ops[2]{new SPIRVOperand(SPIRVOperandType::NUMBERID,
5125 lookupType(Call->getType())),
5126 new SPIRVOperand(SPIRVOperandType::NUMBERID,
5127 VMap[Call->getOperand(0)])};
5128
5129 SPIRVInstList.insert(
5130 InsertPoint, new SPIRVInstruction(4, spv::OpBitCount,
5131 std::get<2>(*DeferredInst), Ops));
5132 } else {
5133 //
5134 // Generate OpFunctionCall.
5135 //
5136
5137 // Ops[0] = Result Type ID
5138 // Ops[1] = Callee Function ID
5139 // Ops[2] ... Ops[n] = Argument 0, ... , Argument n
5140 SPIRVOperandList Ops;
5141
5142 uint32_t ResTyID = lookupType(Call->getType());
5143 SPIRVOperand *ResTyIDOp =
5144 new SPIRVOperand(SPIRVOperandType::NUMBERID, ResTyID);
5145 Ops.push_back(ResTyIDOp);
5146
5147 uint32_t CalleeID = VMap[Callee];
5148
5149 SPIRVOperand *CalleeIDOp =
5150 new SPIRVOperand(SPIRVOperandType::NUMBERID, CalleeID);
5151 Ops.push_back(CalleeIDOp);
5152
5153 uint16_t WordCount = 4;
5154
5155 FunctionType *CalleeFTy = cast<FunctionType>(Call->getFunctionType());
5156 for (unsigned i = 0; i < CalleeFTy->getNumParams(); i++) {
5157 uint32_t ArgID = VMap[Call->getOperand(i)];
5158 SPIRVOperand *ArgIDOp =
5159 new SPIRVOperand(SPIRVOperandType::NUMBERID, ArgID);
5160 Ops.push_back(ArgIDOp);
5161 WordCount++;
5162 }
5163
5164 SPIRVInstruction *CallInst = new SPIRVInstruction(
5165 WordCount, spv::OpFunctionCall, std::get<2>(*DeferredInst), Ops);
5166 SPIRVInstList.insert(InsertPoint, CallInst);
5167 }
5168 }
5169 }
5170}
5171
David Neto1a1a0582017-07-07 12:01:44 -04005172void SPIRVProducerPass::HandleDeferredDecorations(const DataLayout &DL) {
5173 // Insert ArrayStride decorations on pointer types, due to OpPtrAccessChain
5174 // instructions we generated earlier.
5175 if (getPointerTypesNeedingArrayStride().empty())
5176 return;
5177
5178 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5179 ValueMapType &VMap = getValueMap();
5180
5181 // Find an iterator pointing just past the last decoration.
5182 bool seen_decorations = false;
5183 auto DecoInsertPoint =
5184 std::find_if(SPIRVInstList.begin(), SPIRVInstList.end(),
5185 [&seen_decorations](SPIRVInstruction *Inst) -> bool {
5186 const bool is_decoration =
5187 Inst->getOpcode() == spv::OpDecorate ||
5188 Inst->getOpcode() == spv::OpMemberDecorate;
5189 if (is_decoration) {
5190 seen_decorations = true;
5191 return false;
5192 } else {
5193 return seen_decorations;
5194 }
5195 });
5196
5197 for (auto *type : getPointerTypesNeedingArrayStride()) {
5198 auto *ptrType = cast<PointerType>(type);
5199
5200 // Ops[0] = Target ID
5201 // Ops[1] = Decoration (ArrayStride)
5202 // Ops[2] = Stride number (Literal Number)
5203 SPIRVOperandList Ops;
5204
5205 Ops.push_back(
5206 new SPIRVOperand(SPIRVOperandType::NUMBERID, lookupType(ptrType)));
5207 Ops.push_back(new SPIRVOperand(SPIRVOperandType::NUMBERID,
5208 spv::DecorationArrayStride));
5209 Type *elemTy = ptrType->getElementType();
5210 // Same as DL.getIndexedOfffsetInType( elemTy, { 1 } );
5211 const unsigned stride = DL.getTypeAllocSize(elemTy);
5212 Ops.push_back(new SPIRVOperand(SPIRVOperandType::LITERAL_INTEGER, stride));
5213
5214 SPIRVInstruction *DecoInst =
5215 new SPIRVInstruction(4, spv::OpDecorate, 0 /* No id */, Ops);
5216 SPIRVInstList.insert(DecoInsertPoint, DecoInst);
5217 }
5218}
5219
David Neto22f144c2017-06-12 14:26:21 -04005220glsl::ExtInst SPIRVProducerPass::getExtInstEnum(StringRef Name) {
5221 return StringSwitch<glsl::ExtInst>(Name)
5222 .Case("_Z3absi", glsl::ExtInst::ExtInstSAbs)
5223 .Case("_Z3absDv2_i", glsl::ExtInst::ExtInstSAbs)
5224 .Case("_Z3absDv3_i", glsl::ExtInst::ExtInstSAbs)
5225 .Case("_Z3absDv4_i", glsl::ExtInst::ExtInstSAbs)
5226 .Case("_Z5clampiii", glsl::ExtInst::ExtInstSClamp)
5227 .Case("_Z5clampDv2_iS_S_", glsl::ExtInst::ExtInstSClamp)
5228 .Case("_Z5clampDv3_iS_S_", glsl::ExtInst::ExtInstSClamp)
5229 .Case("_Z5clampDv4_iS_S_", glsl::ExtInst::ExtInstSClamp)
5230 .Case("_Z5clampjjj", glsl::ExtInst::ExtInstUClamp)
5231 .Case("_Z5clampDv2_jS_S_", glsl::ExtInst::ExtInstUClamp)
5232 .Case("_Z5clampDv3_jS_S_", glsl::ExtInst::ExtInstUClamp)
5233 .Case("_Z5clampDv4_jS_S_", glsl::ExtInst::ExtInstUClamp)
5234 .Case("_Z5clampfff", glsl::ExtInst::ExtInstFClamp)
5235 .Case("_Z5clampDv2_fS_S_", glsl::ExtInst::ExtInstFClamp)
5236 .Case("_Z5clampDv3_fS_S_", glsl::ExtInst::ExtInstFClamp)
5237 .Case("_Z5clampDv4_fS_S_", glsl::ExtInst::ExtInstFClamp)
5238 .StartsWith("_Z3clz", glsl::ExtInst::ExtInstFindUMsb)
5239 .Case("_Z3maxii", glsl::ExtInst::ExtInstSMax)
5240 .Case("_Z3maxDv2_iS_", glsl::ExtInst::ExtInstSMax)
5241 .Case("_Z3maxDv3_iS_", glsl::ExtInst::ExtInstSMax)
5242 .Case("_Z3maxDv4_iS_", glsl::ExtInst::ExtInstSMax)
5243 .Case("_Z3maxjj", glsl::ExtInst::ExtInstUMax)
5244 .Case("_Z3maxDv2_jS_", glsl::ExtInst::ExtInstUMax)
5245 .Case("_Z3maxDv3_jS_", glsl::ExtInst::ExtInstUMax)
5246 .Case("_Z3maxDv4_jS_", glsl::ExtInst::ExtInstUMax)
5247 .Case("_Z3maxff", glsl::ExtInst::ExtInstFMax)
5248 .Case("_Z3maxDv2_fS_", glsl::ExtInst::ExtInstFMax)
5249 .Case("_Z3maxDv3_fS_", glsl::ExtInst::ExtInstFMax)
5250 .Case("_Z3maxDv4_fS_", glsl::ExtInst::ExtInstFMax)
5251 .StartsWith("_Z4fmax", glsl::ExtInst::ExtInstFMax)
5252 .Case("_Z3minii", glsl::ExtInst::ExtInstSMin)
5253 .Case("_Z3minDv2_iS_", glsl::ExtInst::ExtInstSMin)
5254 .Case("_Z3minDv3_iS_", glsl::ExtInst::ExtInstSMin)
5255 .Case("_Z3minDv4_iS_", glsl::ExtInst::ExtInstSMin)
5256 .Case("_Z3minjj", glsl::ExtInst::ExtInstUMin)
5257 .Case("_Z3minDv2_jS_", glsl::ExtInst::ExtInstUMin)
5258 .Case("_Z3minDv3_jS_", glsl::ExtInst::ExtInstUMin)
5259 .Case("_Z3minDv4_jS_", glsl::ExtInst::ExtInstUMin)
5260 .Case("_Z3minff", glsl::ExtInst::ExtInstFMin)
5261 .Case("_Z3minDv2_fS_", glsl::ExtInst::ExtInstFMin)
5262 .Case("_Z3minDv3_fS_", glsl::ExtInst::ExtInstFMin)
5263 .Case("_Z3minDv4_fS_", glsl::ExtInst::ExtInstFMin)
5264 .StartsWith("_Z4fmin", glsl::ExtInst::ExtInstFMin)
5265 .StartsWith("_Z7degrees", glsl::ExtInst::ExtInstDegrees)
5266 .StartsWith("_Z7radians", glsl::ExtInst::ExtInstRadians)
5267 .StartsWith("_Z3mix", glsl::ExtInst::ExtInstFMix)
5268 .StartsWith("_Z4acos", glsl::ExtInst::ExtInstAcos)
5269 .StartsWith("_Z5acosh", glsl::ExtInst::ExtInstAcosh)
5270 .StartsWith("_Z4asin", glsl::ExtInst::ExtInstAsin)
5271 .StartsWith("_Z5asinh", glsl::ExtInst::ExtInstAsinh)
5272 .StartsWith("_Z4atan", glsl::ExtInst::ExtInstAtan)
5273 .StartsWith("_Z5atan2", glsl::ExtInst::ExtInstAtan2)
5274 .StartsWith("_Z5atanh", glsl::ExtInst::ExtInstAtanh)
5275 .StartsWith("_Z4ceil", glsl::ExtInst::ExtInstCeil)
5276 .StartsWith("_Z3sin", glsl::ExtInst::ExtInstSin)
5277 .StartsWith("_Z4sinh", glsl::ExtInst::ExtInstSinh)
5278 .StartsWith("_Z8half_sin", glsl::ExtInst::ExtInstSin)
5279 .StartsWith("_Z10native_sin", glsl::ExtInst::ExtInstSin)
5280 .StartsWith("_Z3cos", glsl::ExtInst::ExtInstCos)
5281 .StartsWith("_Z4cosh", glsl::ExtInst::ExtInstCosh)
5282 .StartsWith("_Z8half_cos", glsl::ExtInst::ExtInstCos)
5283 .StartsWith("_Z10native_cos", glsl::ExtInst::ExtInstCos)
5284 .StartsWith("_Z3tan", glsl::ExtInst::ExtInstTan)
5285 .StartsWith("_Z4tanh", glsl::ExtInst::ExtInstTanh)
5286 .StartsWith("_Z8half_tan", glsl::ExtInst::ExtInstTan)
5287 .StartsWith("_Z10native_tan", glsl::ExtInst::ExtInstTan)
5288 .StartsWith("_Z3exp", glsl::ExtInst::ExtInstExp)
5289 .StartsWith("_Z8half_exp", glsl::ExtInst::ExtInstExp)
5290 .StartsWith("_Z10native_exp", glsl::ExtInst::ExtInstExp)
5291 .StartsWith("_Z4exp2", glsl::ExtInst::ExtInstExp2)
5292 .StartsWith("_Z9half_exp2", glsl::ExtInst::ExtInstExp2)
5293 .StartsWith("_Z11native_exp2", glsl::ExtInst::ExtInstExp2)
5294 .StartsWith("_Z3log", glsl::ExtInst::ExtInstLog)
5295 .StartsWith("_Z8half_log", glsl::ExtInst::ExtInstLog)
5296 .StartsWith("_Z10native_log", glsl::ExtInst::ExtInstLog)
5297 .StartsWith("_Z4log2", glsl::ExtInst::ExtInstLog2)
5298 .StartsWith("_Z9half_log2", glsl::ExtInst::ExtInstLog2)
5299 .StartsWith("_Z11native_log2", glsl::ExtInst::ExtInstLog2)
5300 .StartsWith("_Z4fabs", glsl::ExtInst::ExtInstFAbs)
5301 .StartsWith("_Z5floor", glsl::ExtInst::ExtInstFloor)
5302 .StartsWith("_Z5ldexp", glsl::ExtInst::ExtInstLdexp)
5303 .StartsWith("_Z3pow", glsl::ExtInst::ExtInstPow)
5304 .StartsWith("_Z4powr", glsl::ExtInst::ExtInstPow)
5305 .StartsWith("_Z9half_powr", glsl::ExtInst::ExtInstPow)
5306 .StartsWith("_Z11native_powr", glsl::ExtInst::ExtInstPow)
5307 .StartsWith("_Z5round", glsl::ExtInst::ExtInstRound)
5308 .StartsWith("_Z4sqrt", glsl::ExtInst::ExtInstSqrt)
5309 .StartsWith("_Z9half_sqrt", glsl::ExtInst::ExtInstSqrt)
5310 .StartsWith("_Z11native_sqrt", glsl::ExtInst::ExtInstSqrt)
5311 .StartsWith("_Z5rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5312 .StartsWith("_Z10half_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5313 .StartsWith("_Z12native_rsqrt", glsl::ExtInst::ExtInstInverseSqrt)
5314 .StartsWith("_Z5trunc", glsl::ExtInst::ExtInstTrunc)
5315 .StartsWith("_Z5frexp", glsl::ExtInst::ExtInstFrexp)
5316 .StartsWith("_Z4sign", glsl::ExtInst::ExtInstFSign)
5317 .StartsWith("_Z6length", glsl::ExtInst::ExtInstLength)
5318 .StartsWith("_Z8distance", glsl::ExtInst::ExtInstDistance)
5319 .Case("_Z5crossDv3_fS_", glsl::ExtInst::ExtInstCross)
5320 .StartsWith("_Z9normalize", glsl::ExtInst::ExtInstNormalize)
5321 .StartsWith("llvm.fmuladd.", glsl::ExtInst::ExtInstFma)
5322 .Case("spirv.unpack.v2f16", glsl::ExtInst::ExtInstUnpackHalf2x16)
5323 .Case("spirv.pack.v2f16", glsl::ExtInst::ExtInstPackHalf2x16)
5324 .Default(static_cast<glsl::ExtInst>(0));
5325}
5326
5327void SPIRVProducerPass::PrintResID(SPIRVInstruction *Inst) {
5328 out << "%" << Inst->getResultID();
5329}
5330
5331void SPIRVProducerPass::PrintOpcode(SPIRVInstruction *Inst) {
5332 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5333 out << "\t" << spv::getOpName(Opcode);
5334}
5335
5336void SPIRVProducerPass::PrintOperand(SPIRVOperand *Op) {
5337 SPIRVOperandType OpTy = Op->getType();
5338 switch (OpTy) {
5339 default: {
5340 llvm_unreachable("Unsupported SPIRV Operand Type???");
5341 break;
5342 }
5343 case SPIRVOperandType::NUMBERID: {
5344 out << "%" << Op->getNumID();
5345 break;
5346 }
5347 case SPIRVOperandType::LITERAL_STRING: {
5348 out << "\"" << Op->getLiteralStr() << "\"";
5349 break;
5350 }
5351 case SPIRVOperandType::LITERAL_INTEGER: {
5352 // TODO: Handle LiteralNum carefully.
5353 for (auto Word : Op->getLiteralNum()) {
5354 out << Word;
5355 }
5356 break;
5357 }
5358 case SPIRVOperandType::LITERAL_FLOAT: {
5359 // TODO: Handle LiteralNum carefully.
5360 for (auto Word : Op->getLiteralNum()) {
5361 APFloat APF = APFloat(APFloat::IEEEsingle(), APInt(32, Word));
5362 SmallString<8> Str;
5363 APF.toString(Str, 6, 2);
5364 out << Str;
5365 }
5366 break;
5367 }
5368 }
5369}
5370
5371void SPIRVProducerPass::PrintCapability(SPIRVOperand *Op) {
5372 spv::Capability Cap = static_cast<spv::Capability>(Op->getNumID());
5373 out << spv::getCapabilityName(Cap);
5374}
5375
5376void SPIRVProducerPass::PrintExtInst(SPIRVOperand *Op) {
5377 auto LiteralNum = Op->getLiteralNum();
5378 glsl::ExtInst Ext = static_cast<glsl::ExtInst>(LiteralNum[0]);
5379 out << glsl::getExtInstName(Ext);
5380}
5381
5382void SPIRVProducerPass::PrintAddrModel(SPIRVOperand *Op) {
5383 spv::AddressingModel AddrModel =
5384 static_cast<spv::AddressingModel>(Op->getNumID());
5385 out << spv::getAddressingModelName(AddrModel);
5386}
5387
5388void SPIRVProducerPass::PrintMemModel(SPIRVOperand *Op) {
5389 spv::MemoryModel MemModel = static_cast<spv::MemoryModel>(Op->getNumID());
5390 out << spv::getMemoryModelName(MemModel);
5391}
5392
5393void SPIRVProducerPass::PrintExecModel(SPIRVOperand *Op) {
5394 spv::ExecutionModel ExecModel =
5395 static_cast<spv::ExecutionModel>(Op->getNumID());
5396 out << spv::getExecutionModelName(ExecModel);
5397}
5398
5399void SPIRVProducerPass::PrintExecMode(SPIRVOperand *Op) {
5400 spv::ExecutionMode ExecMode = static_cast<spv::ExecutionMode>(Op->getNumID());
5401 out << spv::getExecutionModeName(ExecMode);
5402}
5403
5404void SPIRVProducerPass::PrintSourceLanguage(SPIRVOperand *Op) {
5405 spv::SourceLanguage SourceLang = static_cast<spv::SourceLanguage>(Op->getNumID());
5406 out << spv::getSourceLanguageName(SourceLang);
5407}
5408
5409void SPIRVProducerPass::PrintFuncCtrl(SPIRVOperand *Op) {
5410 spv::FunctionControlMask FuncCtrl =
5411 static_cast<spv::FunctionControlMask>(Op->getNumID());
5412 out << spv::getFunctionControlName(FuncCtrl);
5413}
5414
5415void SPIRVProducerPass::PrintStorageClass(SPIRVOperand *Op) {
5416 spv::StorageClass StClass = static_cast<spv::StorageClass>(Op->getNumID());
5417 out << getStorageClassName(StClass);
5418}
5419
5420void SPIRVProducerPass::PrintDecoration(SPIRVOperand *Op) {
5421 spv::Decoration Deco = static_cast<spv::Decoration>(Op->getNumID());
5422 out << getDecorationName(Deco);
5423}
5424
5425void SPIRVProducerPass::PrintBuiltIn(SPIRVOperand *Op) {
5426 spv::BuiltIn BIn = static_cast<spv::BuiltIn>(Op->getNumID());
5427 out << getBuiltInName(BIn);
5428}
5429
5430void SPIRVProducerPass::PrintSelectionControl(SPIRVOperand *Op) {
5431 spv::SelectionControlMask BIn =
5432 static_cast<spv::SelectionControlMask>(Op->getNumID());
5433 out << getSelectionControlName(BIn);
5434}
5435
5436void SPIRVProducerPass::PrintLoopControl(SPIRVOperand *Op) {
5437 spv::LoopControlMask BIn = static_cast<spv::LoopControlMask>(Op->getNumID());
5438 out << getLoopControlName(BIn);
5439}
5440
5441void SPIRVProducerPass::PrintDimensionality(SPIRVOperand *Op) {
5442 spv::Dim DIM = static_cast<spv::Dim>(Op->getNumID());
5443 out << getDimName(DIM);
5444}
5445
5446void SPIRVProducerPass::PrintImageFormat(SPIRVOperand *Op) {
5447 spv::ImageFormat Format = static_cast<spv::ImageFormat>(Op->getNumID());
5448 out << getImageFormatName(Format);
5449}
5450
5451void SPIRVProducerPass::PrintMemoryAccess(SPIRVOperand *Op) {
5452 out << spv::getMemoryAccessName(
5453 static_cast<spv::MemoryAccessMask>(Op->getNumID()));
5454}
5455
5456void SPIRVProducerPass::PrintImageOperandsType(SPIRVOperand *Op) {
5457 auto LiteralNum = Op->getLiteralNum();
5458 spv::ImageOperandsMask Type =
5459 static_cast<spv::ImageOperandsMask>(LiteralNum[0]);
5460 out << getImageOperandsName(Type);
5461}
5462
5463void SPIRVProducerPass::WriteSPIRVAssembly() {
5464 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5465
5466 for (auto Inst : SPIRVInstList) {
5467 SPIRVOperandList Ops = Inst->getOperands();
5468 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5469
5470 switch (Opcode) {
5471 default: {
5472 llvm_unreachable("Unsupported SPIRV instruction");
5473 break;
5474 }
5475 case spv::OpCapability: {
5476 // Ops[0] = Capability
5477 PrintOpcode(Inst);
5478 out << " ";
5479 PrintCapability(Ops[0]);
5480 out << "\n";
5481 break;
5482 }
5483 case spv::OpMemoryModel: {
5484 // Ops[0] = Addressing Model
5485 // Ops[1] = Memory Model
5486 PrintOpcode(Inst);
5487 out << " ";
5488 PrintAddrModel(Ops[0]);
5489 out << " ";
5490 PrintMemModel(Ops[1]);
5491 out << "\n";
5492 break;
5493 }
5494 case spv::OpEntryPoint: {
5495 // Ops[0] = Execution Model
5496 // Ops[1] = EntryPoint ID
5497 // Ops[2] = Name (Literal String)
5498 // Ops[3] ... Ops[n] = Interface ID
5499 PrintOpcode(Inst);
5500 out << " ";
5501 PrintExecModel(Ops[0]);
5502 for (uint32_t i = 1; i < Ops.size(); i++) {
5503 out << " ";
5504 PrintOperand(Ops[i]);
5505 }
5506 out << "\n";
5507 break;
5508 }
5509 case spv::OpExecutionMode: {
5510 // Ops[0] = Entry Point ID
5511 // Ops[1] = Execution Mode
5512 // Ops[2] ... Ops[n] = Optional literals according to Execution Mode
5513 PrintOpcode(Inst);
5514 out << " ";
5515 PrintOperand(Ops[0]);
5516 out << " ";
5517 PrintExecMode(Ops[1]);
5518 for (uint32_t i = 2; i < Ops.size(); i++) {
5519 out << " ";
5520 PrintOperand(Ops[i]);
5521 }
5522 out << "\n";
5523 break;
5524 }
5525 case spv::OpSource: {
5526 // Ops[0] = SourceLanguage ID
5527 // Ops[1] = Version (LiteralNum)
5528 PrintOpcode(Inst);
5529 out << " ";
5530 PrintSourceLanguage(Ops[0]);
5531 out << " ";
5532 PrintOperand(Ops[1]);
5533 out << "\n";
5534 break;
5535 }
5536 case spv::OpDecorate: {
5537 // Ops[0] = Target ID
5538 // Ops[1] = Decoration (Block or BufferBlock)
5539 // Ops[2] ... Ops[n] = Optional literals according to Decoration
5540 PrintOpcode(Inst);
5541 out << " ";
5542 PrintOperand(Ops[0]);
5543 out << " ";
5544 PrintDecoration(Ops[1]);
5545 // Handle BuiltIn OpDecorate specially.
5546 if (Ops[1]->getNumID() == spv::DecorationBuiltIn) {
5547 out << " ";
5548 PrintBuiltIn(Ops[2]);
5549 } else {
5550 for (uint32_t i = 2; i < Ops.size(); i++) {
5551 out << " ";
5552 PrintOperand(Ops[i]);
5553 }
5554 }
5555 out << "\n";
5556 break;
5557 }
5558 case spv::OpMemberDecorate: {
5559 // Ops[0] = Structure Type ID
5560 // Ops[1] = Member Index(Literal Number)
5561 // Ops[2] = Decoration
5562 // Ops[3] ... Ops[n] = Optional literals according to Decoration
5563 PrintOpcode(Inst);
5564 out << " ";
5565 PrintOperand(Ops[0]);
5566 out << " ";
5567 PrintOperand(Ops[1]);
5568 out << " ";
5569 PrintDecoration(Ops[2]);
5570 for (uint32_t i = 3; i < Ops.size(); i++) {
5571 out << " ";
5572 PrintOperand(Ops[i]);
5573 }
5574 out << "\n";
5575 break;
5576 }
5577 case spv::OpTypePointer: {
5578 // Ops[0] = Storage Class
5579 // Ops[1] = Element Type ID
5580 PrintResID(Inst);
5581 out << " = ";
5582 PrintOpcode(Inst);
5583 out << " ";
5584 PrintStorageClass(Ops[0]);
5585 out << " ";
5586 PrintOperand(Ops[1]);
5587 out << "\n";
5588 break;
5589 }
5590 case spv::OpTypeImage: {
5591 // Ops[0] = Sampled Type ID
5592 // Ops[1] = Dim ID
5593 // Ops[2] = Depth (Literal Number)
5594 // Ops[3] = Arrayed (Literal Number)
5595 // Ops[4] = MS (Literal Number)
5596 // Ops[5] = Sampled (Literal Number)
5597 // Ops[6] = Image Format ID
5598 PrintResID(Inst);
5599 out << " = ";
5600 PrintOpcode(Inst);
5601 out << " ";
5602 PrintOperand(Ops[0]);
5603 out << " ";
5604 PrintDimensionality(Ops[1]);
5605 out << " ";
5606 PrintOperand(Ops[2]);
5607 out << " ";
5608 PrintOperand(Ops[3]);
5609 out << " ";
5610 PrintOperand(Ops[4]);
5611 out << " ";
5612 PrintOperand(Ops[5]);
5613 out << " ";
5614 PrintImageFormat(Ops[6]);
5615 out << "\n";
5616 break;
5617 }
5618 case spv::OpFunction: {
5619 // Ops[0] : Result Type ID
5620 // Ops[1] : Function Control
5621 // Ops[2] : Function Type ID
5622 PrintResID(Inst);
5623 out << " = ";
5624 PrintOpcode(Inst);
5625 out << " ";
5626 PrintOperand(Ops[0]);
5627 out << " ";
5628 PrintFuncCtrl(Ops[1]);
5629 out << " ";
5630 PrintOperand(Ops[2]);
5631 out << "\n";
5632 break;
5633 }
5634 case spv::OpSelectionMerge: {
5635 // Ops[0] = Merge Block ID
5636 // Ops[1] = Selection Control
5637 PrintOpcode(Inst);
5638 out << " ";
5639 PrintOperand(Ops[0]);
5640 out << " ";
5641 PrintSelectionControl(Ops[1]);
5642 out << "\n";
5643 break;
5644 }
5645 case spv::OpLoopMerge: {
5646 // Ops[0] = Merge Block ID
5647 // Ops[1] = Continue Target ID
5648 // Ops[2] = Selection Control
5649 PrintOpcode(Inst);
5650 out << " ";
5651 PrintOperand(Ops[0]);
5652 out << " ";
5653 PrintOperand(Ops[1]);
5654 out << " ";
5655 PrintLoopControl(Ops[2]);
5656 out << "\n";
5657 break;
5658 }
5659 case spv::OpImageSampleExplicitLod: {
5660 // Ops[0] = Result Type ID
5661 // Ops[1] = Sampled Image ID
5662 // Ops[2] = Coordinate ID
5663 // Ops[3] = Image Operands Type ID
5664 // Ops[4] ... Ops[n] = Operands ID
5665 PrintResID(Inst);
5666 out << " = ";
5667 PrintOpcode(Inst);
5668 for (uint32_t i = 0; i < 3; i++) {
5669 out << " ";
5670 PrintOperand(Ops[i]);
5671 }
5672 out << " ";
5673 PrintImageOperandsType(Ops[3]);
5674 for (uint32_t i = 4; i < Ops.size(); i++) {
5675 out << " ";
5676 PrintOperand(Ops[i]);
5677 }
5678 out << "\n";
5679 break;
5680 }
5681 case spv::OpVariable: {
5682 // Ops[0] : Result Type ID
5683 // Ops[1] : Storage Class
5684 // Ops[2] ... Ops[n] = Initializer IDs
5685 PrintResID(Inst);
5686 out << " = ";
5687 PrintOpcode(Inst);
5688 out << " ";
5689 PrintOperand(Ops[0]);
5690 out << " ";
5691 PrintStorageClass(Ops[1]);
5692 for (uint32_t i = 2; i < Ops.size(); i++) {
5693 out << " ";
5694 PrintOperand(Ops[i]);
5695 }
5696 out << "\n";
5697 break;
5698 }
5699 case spv::OpExtInst: {
5700 // Ops[0] = Result Type ID
5701 // Ops[1] = Set ID (OpExtInstImport ID)
5702 // Ops[2] = Instruction Number (Literal Number)
5703 // Ops[3] ... Ops[n] = Operand 1, ... , Operand n
5704 PrintResID(Inst);
5705 out << " = ";
5706 PrintOpcode(Inst);
5707 out << " ";
5708 PrintOperand(Ops[0]);
5709 out << " ";
5710 PrintOperand(Ops[1]);
5711 out << " ";
5712 PrintExtInst(Ops[2]);
5713 for (uint32_t i = 3; i < Ops.size(); i++) {
5714 out << " ";
5715 PrintOperand(Ops[i]);
5716 }
5717 out << "\n";
5718 break;
5719 }
5720 case spv::OpCopyMemory: {
5721 // Ops[0] = Addressing Model
5722 // Ops[1] = Memory Model
5723 PrintOpcode(Inst);
5724 out << " ";
5725 PrintOperand(Ops[0]);
5726 out << " ";
5727 PrintOperand(Ops[1]);
5728 out << " ";
5729 PrintMemoryAccess(Ops[2]);
5730 out << " ";
5731 PrintOperand(Ops[3]);
5732 out << "\n";
5733 break;
5734 }
5735 case spv::OpExtension:
5736 case spv::OpControlBarrier:
5737 case spv::OpMemoryBarrier:
5738 case spv::OpBranch:
5739 case spv::OpBranchConditional:
5740 case spv::OpStore:
5741 case spv::OpImageWrite:
5742 case spv::OpReturnValue:
5743 case spv::OpReturn:
5744 case spv::OpFunctionEnd: {
5745 PrintOpcode(Inst);
5746 for (uint32_t i = 0; i < Ops.size(); i++) {
5747 out << " ";
5748 PrintOperand(Ops[i]);
5749 }
5750 out << "\n";
5751 break;
5752 }
5753 case spv::OpExtInstImport:
5754 case spv::OpTypeRuntimeArray:
5755 case spv::OpTypeStruct:
5756 case spv::OpTypeSampler:
5757 case spv::OpTypeSampledImage:
5758 case spv::OpTypeInt:
5759 case spv::OpTypeFloat:
5760 case spv::OpTypeArray:
5761 case spv::OpTypeVector:
5762 case spv::OpTypeBool:
5763 case spv::OpTypeVoid:
5764 case spv::OpTypeFunction:
5765 case spv::OpFunctionParameter:
5766 case spv::OpLabel:
5767 case spv::OpPhi:
5768 case spv::OpLoad:
5769 case spv::OpSelect:
5770 case spv::OpAccessChain:
5771 case spv::OpPtrAccessChain:
5772 case spv::OpInBoundsAccessChain:
5773 case spv::OpUConvert:
5774 case spv::OpSConvert:
5775 case spv::OpConvertFToU:
5776 case spv::OpConvertFToS:
5777 case spv::OpConvertUToF:
5778 case spv::OpConvertSToF:
5779 case spv::OpFConvert:
5780 case spv::OpConvertPtrToU:
5781 case spv::OpConvertUToPtr:
5782 case spv::OpBitcast:
5783 case spv::OpIAdd:
5784 case spv::OpFAdd:
5785 case spv::OpISub:
5786 case spv::OpFSub:
5787 case spv::OpIMul:
5788 case spv::OpFMul:
5789 case spv::OpUDiv:
5790 case spv::OpSDiv:
5791 case spv::OpFDiv:
5792 case spv::OpUMod:
5793 case spv::OpSRem:
5794 case spv::OpFRem:
5795 case spv::OpBitwiseOr:
5796 case spv::OpBitwiseXor:
5797 case spv::OpBitwiseAnd:
5798 case spv::OpShiftLeftLogical:
5799 case spv::OpShiftRightLogical:
5800 case spv::OpShiftRightArithmetic:
5801 case spv::OpBitCount:
5802 case spv::OpCompositeExtract:
5803 case spv::OpVectorExtractDynamic:
5804 case spv::OpCompositeInsert:
5805 case spv::OpVectorInsertDynamic:
5806 case spv::OpVectorShuffle:
5807 case spv::OpIEqual:
5808 case spv::OpINotEqual:
5809 case spv::OpUGreaterThan:
5810 case spv::OpUGreaterThanEqual:
5811 case spv::OpULessThan:
5812 case spv::OpULessThanEqual:
5813 case spv::OpSGreaterThan:
5814 case spv::OpSGreaterThanEqual:
5815 case spv::OpSLessThan:
5816 case spv::OpSLessThanEqual:
5817 case spv::OpFOrdEqual:
5818 case spv::OpFOrdGreaterThan:
5819 case spv::OpFOrdGreaterThanEqual:
5820 case spv::OpFOrdLessThan:
5821 case spv::OpFOrdLessThanEqual:
5822 case spv::OpFOrdNotEqual:
5823 case spv::OpFUnordEqual:
5824 case spv::OpFUnordGreaterThan:
5825 case spv::OpFUnordGreaterThanEqual:
5826 case spv::OpFUnordLessThan:
5827 case spv::OpFUnordLessThanEqual:
5828 case spv::OpFUnordNotEqual:
5829 case spv::OpSampledImage:
5830 case spv::OpFunctionCall:
5831 case spv::OpConstantTrue:
5832 case spv::OpConstantFalse:
5833 case spv::OpConstant:
5834 case spv::OpSpecConstant:
5835 case spv::OpConstantComposite:
5836 case spv::OpSpecConstantComposite:
5837 case spv::OpConstantNull:
5838 case spv::OpLogicalOr:
5839 case spv::OpLogicalAnd:
5840 case spv::OpLogicalNot:
5841 case spv::OpLogicalNotEqual:
5842 case spv::OpUndef:
5843 case spv::OpIsInf:
5844 case spv::OpIsNan:
5845 case spv::OpAny:
5846 case spv::OpAll:
5847 case spv::OpAtomicIAdd:
5848 case spv::OpAtomicISub:
5849 case spv::OpAtomicExchange:
5850 case spv::OpAtomicIIncrement:
5851 case spv::OpAtomicIDecrement:
5852 case spv::OpAtomicCompareExchange:
5853 case spv::OpAtomicUMin:
5854 case spv::OpAtomicSMin:
5855 case spv::OpAtomicUMax:
5856 case spv::OpAtomicSMax:
5857 case spv::OpAtomicAnd:
5858 case spv::OpAtomicOr:
5859 case spv::OpAtomicXor:
5860 case spv::OpDot: {
5861 PrintResID(Inst);
5862 out << " = ";
5863 PrintOpcode(Inst);
5864 for (uint32_t i = 0; i < Ops.size(); i++) {
5865 out << " ";
5866 PrintOperand(Ops[i]);
5867 }
5868 out << "\n";
5869 break;
5870 }
5871 }
5872 }
5873}
5874
5875void SPIRVProducerPass::WriteOneWord(uint32_t Word) {
David Neto0676e6f2017-07-11 18:47:44 -04005876 binaryOut->write(reinterpret_cast<const char *>(&Word), sizeof(uint32_t));
David Neto22f144c2017-06-12 14:26:21 -04005877}
5878
5879void SPIRVProducerPass::WriteResultID(SPIRVInstruction *Inst) {
5880 WriteOneWord(Inst->getResultID());
5881}
5882
5883void SPIRVProducerPass::WriteWordCountAndOpcode(SPIRVInstruction *Inst) {
5884 // High 16 bit : Word Count
5885 // Low 16 bit : Opcode
5886 uint32_t Word = Inst->getOpcode();
5887 Word |= Inst->getWordCount() << 16;
5888 WriteOneWord(Word);
5889}
5890
5891void SPIRVProducerPass::WriteOperand(SPIRVOperand *Op) {
5892 SPIRVOperandType OpTy = Op->getType();
5893 switch (OpTy) {
5894 default: {
5895 llvm_unreachable("Unsupported SPIRV Operand Type???");
5896 break;
5897 }
5898 case SPIRVOperandType::NUMBERID: {
5899 WriteOneWord(Op->getNumID());
5900 break;
5901 }
5902 case SPIRVOperandType::LITERAL_STRING: {
5903 std::string Str = Op->getLiteralStr();
5904 const char *Data = Str.c_str();
5905 size_t WordSize = Str.size() / 4;
5906 for (unsigned Idx = 0; Idx < WordSize; Idx++) {
5907 WriteOneWord(*reinterpret_cast<const uint32_t *>(&Data[4 * Idx]));
5908 }
5909
5910 uint32_t Remainder = Str.size() % 4;
5911 uint32_t LastWord = 0;
5912 if (Remainder) {
5913 for (unsigned Idx = 0; Idx < Remainder; Idx++) {
5914 LastWord |= Data[4 * WordSize + Idx] << 8 * Idx;
5915 }
5916 }
5917
5918 WriteOneWord(LastWord);
5919 break;
5920 }
5921 case SPIRVOperandType::LITERAL_INTEGER:
5922 case SPIRVOperandType::LITERAL_FLOAT: {
5923 auto LiteralNum = Op->getLiteralNum();
5924 // TODO: Handle LiteranNum carefully.
5925 for (auto Word : LiteralNum) {
5926 WriteOneWord(Word);
5927 }
5928 break;
5929 }
5930 }
5931}
5932
5933void SPIRVProducerPass::WriteSPIRVBinary() {
5934 SPIRVInstructionList &SPIRVInstList = getSPIRVInstList();
5935
5936 for (auto Inst : SPIRVInstList) {
5937 SPIRVOperandList Ops = Inst->getOperands();
5938 spv::Op Opcode = static_cast<spv::Op>(Inst->getOpcode());
5939
5940 switch (Opcode) {
5941 default: {
5942 llvm_unreachable("Unsupported SPIRV instruction");
5943 break;
5944 }
5945 case spv::OpCapability:
5946 case spv::OpExtension:
5947 case spv::OpMemoryModel:
5948 case spv::OpEntryPoint:
5949 case spv::OpExecutionMode:
5950 case spv::OpSource:
5951 case spv::OpDecorate:
5952 case spv::OpMemberDecorate:
5953 case spv::OpBranch:
5954 case spv::OpBranchConditional:
5955 case spv::OpSelectionMerge:
5956 case spv::OpLoopMerge:
5957 case spv::OpStore:
5958 case spv::OpImageWrite:
5959 case spv::OpReturnValue:
5960 case spv::OpControlBarrier:
5961 case spv::OpMemoryBarrier:
5962 case spv::OpReturn:
5963 case spv::OpFunctionEnd:
5964 case spv::OpCopyMemory: {
5965 WriteWordCountAndOpcode(Inst);
5966 for (uint32_t i = 0; i < Ops.size(); i++) {
5967 WriteOperand(Ops[i]);
5968 }
5969 break;
5970 }
5971 case spv::OpTypeBool:
5972 case spv::OpTypeVoid:
5973 case spv::OpTypeSampler:
5974 case spv::OpLabel:
5975 case spv::OpExtInstImport:
5976 case spv::OpTypePointer:
5977 case spv::OpTypeRuntimeArray:
5978 case spv::OpTypeStruct:
5979 case spv::OpTypeImage:
5980 case spv::OpTypeSampledImage:
5981 case spv::OpTypeInt:
5982 case spv::OpTypeFloat:
5983 case spv::OpTypeArray:
5984 case spv::OpTypeVector:
5985 case spv::OpTypeFunction: {
5986 WriteWordCountAndOpcode(Inst);
5987 WriteResultID(Inst);
5988 for (uint32_t i = 0; i < Ops.size(); i++) {
5989 WriteOperand(Ops[i]);
5990 }
5991 break;
5992 }
5993 case spv::OpFunction:
5994 case spv::OpFunctionParameter:
5995 case spv::OpAccessChain:
5996 case spv::OpPtrAccessChain:
5997 case spv::OpInBoundsAccessChain:
5998 case spv::OpUConvert:
5999 case spv::OpSConvert:
6000 case spv::OpConvertFToU:
6001 case spv::OpConvertFToS:
6002 case spv::OpConvertUToF:
6003 case spv::OpConvertSToF:
6004 case spv::OpFConvert:
6005 case spv::OpConvertPtrToU:
6006 case spv::OpConvertUToPtr:
6007 case spv::OpBitcast:
6008 case spv::OpIAdd:
6009 case spv::OpFAdd:
6010 case spv::OpISub:
6011 case spv::OpFSub:
6012 case spv::OpIMul:
6013 case spv::OpFMul:
6014 case spv::OpUDiv:
6015 case spv::OpSDiv:
6016 case spv::OpFDiv:
6017 case spv::OpUMod:
6018 case spv::OpSRem:
6019 case spv::OpFRem:
6020 case spv::OpBitwiseOr:
6021 case spv::OpBitwiseXor:
6022 case spv::OpBitwiseAnd:
6023 case spv::OpShiftLeftLogical:
6024 case spv::OpShiftRightLogical:
6025 case spv::OpShiftRightArithmetic:
6026 case spv::OpBitCount:
6027 case spv::OpCompositeExtract:
6028 case spv::OpVectorExtractDynamic:
6029 case spv::OpCompositeInsert:
6030 case spv::OpVectorInsertDynamic:
6031 case spv::OpVectorShuffle:
6032 case spv::OpIEqual:
6033 case spv::OpINotEqual:
6034 case spv::OpUGreaterThan:
6035 case spv::OpUGreaterThanEqual:
6036 case spv::OpULessThan:
6037 case spv::OpULessThanEqual:
6038 case spv::OpSGreaterThan:
6039 case spv::OpSGreaterThanEqual:
6040 case spv::OpSLessThan:
6041 case spv::OpSLessThanEqual:
6042 case spv::OpFOrdEqual:
6043 case spv::OpFOrdGreaterThan:
6044 case spv::OpFOrdGreaterThanEqual:
6045 case spv::OpFOrdLessThan:
6046 case spv::OpFOrdLessThanEqual:
6047 case spv::OpFOrdNotEqual:
6048 case spv::OpFUnordEqual:
6049 case spv::OpFUnordGreaterThan:
6050 case spv::OpFUnordGreaterThanEqual:
6051 case spv::OpFUnordLessThan:
6052 case spv::OpFUnordLessThanEqual:
6053 case spv::OpFUnordNotEqual:
6054 case spv::OpExtInst:
6055 case spv::OpIsInf:
6056 case spv::OpIsNan:
6057 case spv::OpAny:
6058 case spv::OpAll:
6059 case spv::OpUndef:
6060 case spv::OpConstantNull:
6061 case spv::OpLogicalOr:
6062 case spv::OpLogicalAnd:
6063 case spv::OpLogicalNot:
6064 case spv::OpLogicalNotEqual:
6065 case spv::OpConstantComposite:
6066 case spv::OpSpecConstantComposite:
6067 case spv::OpConstantTrue:
6068 case spv::OpConstantFalse:
6069 case spv::OpConstant:
6070 case spv::OpSpecConstant:
6071 case spv::OpVariable:
6072 case spv::OpFunctionCall:
6073 case spv::OpSampledImage:
6074 case spv::OpImageSampleExplicitLod:
6075 case spv::OpSelect:
6076 case spv::OpPhi:
6077 case spv::OpLoad:
6078 case spv::OpAtomicIAdd:
6079 case spv::OpAtomicISub:
6080 case spv::OpAtomicExchange:
6081 case spv::OpAtomicIIncrement:
6082 case spv::OpAtomicIDecrement:
6083 case spv::OpAtomicCompareExchange:
6084 case spv::OpAtomicUMin:
6085 case spv::OpAtomicSMin:
6086 case spv::OpAtomicUMax:
6087 case spv::OpAtomicSMax:
6088 case spv::OpAtomicAnd:
6089 case spv::OpAtomicOr:
6090 case spv::OpAtomicXor:
6091 case spv::OpDot: {
6092 WriteWordCountAndOpcode(Inst);
6093 WriteOperand(Ops[0]);
6094 WriteResultID(Inst);
6095 for (uint32_t i = 1; i < Ops.size(); i++) {
6096 WriteOperand(Ops[i]);
6097 }
6098 break;
6099 }
6100 }
6101 }
6102}