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