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