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