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