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